Kernel reboot after keybord IRQ1

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Sill
Posts: 3
Joined: Sat May 17, 2008 11:22 pm
Location: Gdansk, Poland

Kernel reboot after keybord IRQ1

Post by Sill »

Hi!

After many hours of work and many drops of sudor... i stick.

I have a bootloader loads kernel from raw-data floppy, unblock A20, setts primitives stack and GDT and jump to C coded kernel.

There I set new GDT and IDT tables, reroute hardware ISR (in source generated by nasm macor) for IRQs, set IRQ1 and enable it (and disabling IRQ0 and IRQs 2-15).
After that I 'sti' and for( ; ; ) ;

To this point all seems to be OK.

But when I press any key, the kernel is rebooting, with bochs log listed below.

I try all things i could invent or find over the Inet.
I googled all Internet, i think (-;

What am I doing wrong??

If someone could look up my code it's all in attachment. It is prepared to compile on FreeBSD by typing 'sh make.sh'.

I just can’t look anymore at Vi with asm/c mash (-;
Help! (-:


The Bochs reboot log:

Code: Select all

00091058500i[CPU0 ] CPU is in protected mode (active)
00091058500i[CPU0 ] CS.d_b = 32 bit
00091058500i[CPU0 ] SS.d_b = 32 bit
00091058500i[CPU0 ] EFER   = 0x00000000
00091058500i[CPU0 ] | RAX=0000000000000000  RBX=0000000000000010
00091058500i[CPU0 ] | RCX=0000000000000008  RDX=0000000000000007
00091058500i[CPU0 ] | RSP=0000000000007fd0  RBP=0000000000000000
00091058500i[CPU0 ] | RSI=00000000ffff88ca  RDI=0000000000080001
00091058500i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00091058500i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00091058500i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00091058500i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00091058500i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf af pf cf
00091058500i[CPU0 ] | SEG selector     base    limit G D
00091058500i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00091058500i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00091058500i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00091058500i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00091058500i[CPU0 ] | RIP=0000000000011130 (0000000000011130)
00091058500i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00091058500i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00091058500i[CPU0 ] >> jmp .+0xfffffffe (0x00011130) : EBFE
00091058500e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00091058500i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00091058500i[CPU0 ] cpu software reset
Attachments
os.zip
(14.11 KiB) Downloaded 195 times
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

What are the messages bochs prints before giving the CPU dump?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
edfed
Member
Member
Posts: 42
Joined: Wed Apr 09, 2008 5:44 pm
Location: Mars

Post by edfed »

it looks like a double general protection faillure.

something is not correctlly done in the IRQ and IDT assignements.
welcome in my dream.
Sill
Posts: 3
Joined: Sat May 17, 2008 11:22 pm
Location: Gdansk, Poland

Post by Sill »

@Combuster: Nothing. Only somthing like "booting form 7C00h";
If I don't load IDT, there is message about this. But actually, there is nothing.


@edfed:
(sorry for big parts of code but i have not idea how to avid this)

In entry.asm (the 'header' linked to the kernel.c) i have:

Code: Select all

cli
lgdt [gdt_descr]
lidt [idt_descr]
jmp .1
.1:
...
call reroute_irqs
...
[EXTERN __main]
call __main
...
idt_descr:
 dw 256*8-1
 dd idt
[GLOBAL idt]
idt:
 times 256 dd 0,0
...
 [GLOBAL _irq1]
 _irq1:
 (ISR code, I`ve even tried hlt for test purposes)
...
Then in C code I set IDT table entry by code like this:

Code: Select all

#define __byte(x,y)     (((unsigned char *)&(y))[x])
#define cached_21       (__byte(0,cached_irq_mask))
#define cached_A1       (__byte(1,cached_irq_mask))

static unsigned int cached_irq_mask = 0xffff;

typedef struct {
        unsigned short offset_0;
        unsigned short selector;
        unsigned short type;
        unsigned short offset_16;
} gate_desc[256];

extern gate_desc idt;

void set_gate(int n, unsigned long irq_handle, unsigned short type) {
        idt[n].offset_0  = irq_handle;
        idt[n].selector  = 0x08;
        idt[n].type      = type;
        idt[n].offset_16 = (irq_handle >> 16);
}
void disable_irq(unsigned int irq) {
        unsigned int mask = (1 << irq);
        cached_irq_mask |= mask;
        if (irq & 8) {
                outb(cached_A1,0xA1);
        } else {
                outb(cached_21,0x21);
        }
}

void enable_irq(unsigned int irq) {
        unsigned int mask = ~(1 << irq);
        cached_irq_mask &= mask;
        if (irq & 8) {
                outb(cached_A1,0xA1);
        } else {
                outb(cached_21,0x21);
        }
}

// entry point of kernel
void __main() {
        int i = 0;
        for( i = 0; i < 16; i ++ ) {
                disable_irq(i);
        }
        enable_irq(1);
        set_gate(0x21, (unsigned long)&_irq1, 0x8E00);
        sti();
        for( ; ; );
}
What can be wrong?
I really have no idea...
User avatar
edfed
Member
Member
Posts: 42
Joined: Wed Apr 09, 2008 5:44 pm
Location: Mars

Post by edfed »

| troll just below :evil:
V ](*,)
Last edited by edfed on Mon May 19, 2008 3:19 am, edited 2 times in total.
welcome in my dream.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

edfed wrote:i invite you to not code in C.

asm is enough to make what you want.
seting the IDT in C is hazardous when you know you can set it in asm.
I invite you not to code in assembly.

C is enough to make what you want.
doing anything in assembly is hazardous when you know you can set it in C.


The moral of the story? He's programming in C, so give him an answer in C. Just because you cannot program well enough in C to do what he wants, does not mean he or anyone else can't.

EDIT:

@OP: I notice a couple of things wrong - firstly you don't reload the code segment after your lgdt.

Code: Select all

cli
lgdt [gdt_descr]
lidt [idt_descr]
jmp .1
.1: 
Should be

Code: Select all

cli
lgdt [gdt_descr]
lidt [idt_descr]
jmp 0x08:.1
.1: 
Note the segment selector - this is a FAR jump, and reloads CS.

Also, I notice that you're not masking your base offsets properly:

Code: Select all

void set_gate(int n, unsigned long irq_handle, unsigned short type) {
        idt[n].offset_0  = irq_handle;
        idt[n].selector  = 0x08;
        idt[n].type      = type;
        idt[n].offset_16 = (irq_handle >> 16);
} 
Should be

Code: Select all

void set_gate(int n, unsigned long irq_handle, unsigned short type) {
        idt[n].offset_0  = irq_handle&0xFFFF;
        idt[n].selector  = 0x08;
        idt[n].type      = type;
        idt[n].offset_16 = (irq_handle >> 16) & 0xFFFF;
} 
Now, you'd hope that the compiler would do those masks for you, but I've run into problems before where some versions of GCC didn't and funky things started happening because of it!

HTH,

James
Sill
Posts: 3
Joined: Sat May 17, 2008 11:22 pm
Location: Gdansk, Poland

Post by Sill »

@JamesM:
Well. There was problem with GTD in fact. I`ve fixed it and it is not the case of rebooting.

I was mistrustful to the structure, becous it gave strange outputs , and tried (in set_gate) something like that:

Code: Select all

        unsigned short* idtn;
        idtn = &idt[n];
        idtn[0] = irq_handle & 0xFFFF;
        idtn[1] = 0x08;
        idtn[2] = type;
        idtn[3] = (irq_handle >> 16) & 0xFFFF;
... and still the same ...
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

Code: Select all

typedef struct {
   unsigned short offset_0;
   unsigned short selector;
   unsigned short type;
   unsigned short offset_16;
} gate_desc[256];
I suggest you declare this with __attribute__((packed)) (before the gate_desc[256]). This will prevent GCC padding the fields to 32 bits each.

Cheers,
Adam
Post Reply