Page 1 of 1

Exception Handler not called by processor...

Posted: Sun Feb 18, 2007 1:55 pm
by JJeronimo
For some strange reason, the CPU is not calling any exception handler apart from Divide Error... I'm not going to show you code, but instead some output from the Bochs debugger... It's really strange...

This output is when I try the ud2 instruction, but the same occurs when a GPF or a PF occurs (either called as an exception or as a software interrupt with the int instruction)... The only one that is called correctly is either the cases is the Devide Error...

Code: Select all

(0) [0x00100dc0] 0008:00000000c0000dc0 (unk. ctxt): ud2a                      ; 0f0b
First, the most important: a CPU dump...

Code: Select all

<bochs:9> dump_cpu
CPU#0
eax:0x00000000, ebx:0x00007c00, ecx:0x00000c80, edx:0xc0001a78
ebp:0xc0005b90, esp:0xc0005b78, esi:0x0005465a, edi:0x0005465b
eip:0xc0000dc0, eflags:0x00000046, inhibit_mask:0
cs:s=0x0008, dl=0x0000ffff, dh=0x00cf9a00, valid=1
ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=5
fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0xc0001b14, limit=0x37
idtr:base=0xc0005ba0, limit=0xf
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x80000011, cr1:0x00000000, cr2:0x00000000
cr3:0x00106000, cr4:0x00000000
done
The GDT in two distinct formats...

Code: Select all

<bochs:8> info gdt 0 10

Global Descriptor Table (base=0xc0001b14):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, linearaddr=00000000, limit=fffff * 4Kbytes, Execute/Read, 32-bit  ;Kernel code
GDT[0x02]=Data segment, linearaddr=00000000, limit=fffff * 4Kbytes, Read/Write, Accessed  ;Kernel data
GDT[0x03]=Code segment, linearaddr=00000000, limit=fffff * 4Kbytes, Execute/Read, 32-bit  ;Usermode code
GDT[0x04]=Data segment, linearaddr=00000000, limit=fffff * 4Kbytes, Read/Write            ;Usermode data
GDT[0x05]=Code segment, linearaddr=40100000, limit=fffff * 4Kbytes, Execute/Read, 32-bit  ;These two were used for
GDT[0x06]=Data segment, linearaddr=40100000, limit=fffff * 4Kbytes, Read/Write, Accessed  ;the Tim Robinson's trick
GDT[0x07]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x08]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x09]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x0a]=??? descriptor hi=0x00000000, lo=0x00000000


<bochs:14> x /20w 0xc0001b14
[bochs]:
0xc0001b14 <bogus+       0>:    0x00000000      0x00000000      0x0000ffff      0x00cf9a00
0xc0001b24 <bogus+      16>:    0x0000ffff      0x00cf9300      0x0000ffff      0x00cffa00
0xc0001b34 <bogus+      32>:    0x0000ffff      0x00cff200      0x0000ffff      0x40cf9a10
0xc0001b44 <bogus+      48>:    0x0000ffff      0x40cf9310      0x00000000      0x00000000
0xc0001b54 <bogus+      64>:    0x00000000      0x00000000      0x00000000      0x00000000
And the same for the IDT...

Code: Select all

<bochs:6> info idt 0 14

Interrupt Descriptor Table (base=0x00000000c0005ba0):
IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0xc00004e0, DPL=3   ;This one is called OK...
IDT[0x01]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x02]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x03]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x04]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x05]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x06]=32-Bit Interrupt Gate target=0x0008:0xc00004f4, DPL=3
IDT[0x07]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x08]=32-Bit Interrupt Gate target=0x0008:0xc0000565, DPL=3
IDT[0x09]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x0a]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x0b]=??? descriptor hi=0x00000000, lo=0x00000000
IDT[0x0c]=32-Bit Interrupt Gate target=0x0008:0xc0000508, DPL=3
IDT[0x0d]=32-Bit Interrupt Gate target=0x0008:0xc0000527, DPL=3
IDT[0x0e]=32-Bit Interrupt Gate target=0x0008:0xc0000546, DPL=3


<bochs:16> x /30w 0x00000000c0005ba0

[bochs]:
0xc0005ba0 <bogus+       0>:    0x000804e0      0xc000ee00      0x00000000      0x00000000
0xc0005bb0 <bogus+      16>:    0x00000000      0x00000000      0x00000000      0x00000000
0xc0005bc0 <bogus+      32>:    0x00000000      0x00000000      0x00000000      0x00000000
0xc0005bd0 <bogus+      48>:    0x000804f4      0xc000ee00      0x00000000      0x00000000
0xc0005be0 <bogus+      64>:    0x00080565      0xc000ee00      0x00000000      0x00000000
0xc0005bf0 <bogus+      80>:    0x00000000      0x00000000      0x00000000      0x00000000
0xc0005c00 <bogus+      96>:    0x00080508      0xc000ee00      0x00080527      0xc000ee00
0xc0005c10 <bogus+     112>:    0x00080546      0xc000ee00
Disassembly of the Invalid Opcode handler...

Code: Select all

<bochs:19> u /8 0xc00004f4
c00004f4: (                    ): pushad                    ; 60
c00004f5: (                    ): lea eax, dword ptr ss:[esp+0x20] ; 8d442420
c00004f9: (                    ): push esp                  ; 54
c00004fa: (                    ): push eax                  ; 50
c00004fb: (                    ): call .+0x00000c7f         ; e87f0c0000
c0000500: (                    ): add esp, 0x00000008       ; 81c408000000
c0000506: (                    ): popad                     ; 61
c0000507: (                    ): iretd                     ; cf
When I step over the ud2 instruction, triple fault...

Code: Select all

00009658802i[CPU0 ] EFER   = 0x00000000
00009658802i[CPU0 ] | RAX=0000000000000000  RBX=0000000000007c00
00009658802i[CPU0 ] | RCX=0000000000000c80  RDX=00000000c0001a78
00009658802i[CPU0 ] | RSP=00000000c0005b78  RBP=00000000c0005b90
00009658802i[CPU0 ] | RSI=000000000005465a  RDI=000000000005465b
00009658802i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00009658802i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00009658802i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00009658802i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00009658802i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00009658802i[CPU0 ] | SEG selector     base    limit G D
00009658802i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00009658802i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00009658802i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00009658802i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00009658802i[CPU0 ] | RIP=00000000c0000dc0 (00000000c0000dc0)
00009658802i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000000
00009658802i[CPU0 ] | CR3=0x00106000 CR4=0x00000000
00009658802i[CPU0 ] >> ud2a  : 0F0B
00009658802p[CPU0 ] >>PANIC<< exception(): 3rd (13) exception with no resolution
What is really anoying me is that the divide error works but the others don't.
If anyone is able to help, many thanks...



And sorry for the long post... I hope it does not prevent you from reading it!

JJ

Posted: Sun Feb 18, 2007 4:20 pm
by uglyoldbob
interrupt 6 is the invalid/reserved opcode interrupt
interrupt 8 is double fault
(intel programming book 3, page 5-29, page 5-33)
You might show us the int6 handler instead of the int8 handler.
I see paging is enabled, so check the pages (make sure they are marked present and are mapped correctly to physical memory) for the code at the ud2a instruction and the interrupt that is supposed to be called. It kinda looks like you are using segmentation, but I am not so skilled at looking at the GDT dumps.
Other than those things I couldn't tell you without going through bochs on debug mode myself (I think, therefore I am possibly wrong)

Posted: Sun Feb 18, 2007 4:37 pm
by JJeronimo
uglyoldbob wrote:interrupt 6 is the invalid/reserved opcode interrupt
interrupt 8 is double fault
(intel programming book 3, page 5-29, page 5-33)
You might show us the int6 handler instead of the int8 handler.
I've shown the int 6 handler... it's at 0xC00004F4 logical (the code that I disassembled)... the "/8" in the bochs debugger command is the number of instructions...
I see paging is enabled, so check the pages (make sure they are marked present and are mapped correctly to physical memory) for the code at the ud2a instruction and the interrupt that is supposed to be called.
The ud2a instruction is in the virtual address space and is executed. That's what causes the problem because, for some reason, the invalid opcode exception isn't found...
The handler is correctly mapped too... I disassembled it using the debugger...
It kinda looks like you are using segmentation, but I am not so skilled at looking at the GDT dumps.
Everyone uses segmentation in the sense that everyone needs to play with it's datastructures in one way or another. I'm using the flat memory model, but the descriptors 5 and 6 were used for the Tim Robinson's GDT trick...
I included the GDT dumps because the problem could be caused by some of the flags...

JJ

Re: Exception Handler not called by processor...

Posted: Sun Feb 18, 2007 4:52 pm
by Brendan
Hi,
JJeronimo wrote:

Code: Select all

idtr:base=0xc0005ba0, limit=0xf
I'd be tempted to check the IDT limit. Your divide by zero (int 0x00) and debug exception (int 0x01) should work, but anything else in the IDT past offset 0x0F should cause a general protection fault (including a general protection fault).

In general the IDT limit should be something like 0x7FF (or "highest_interrupt * 8 - 1").


Cheers,

Brendan

Re: Exception Handler not called by processor...

Posted: Sun Feb 18, 2007 5:15 pm
by JJeronimo
Brendan wrote:I'd be tempted to check the IDT limit. Your divide by zero (int 0x00) and debug exception (int 0x01) should work, but anything else in the IDT past offset 0x0F should cause a general protection fault
Thanks... Hadn't even thougth about that!
If Bochs took that into account when doing info idt I would have discovered sooner...
(including a general protection fault).
The real problem was the Double Fault, because it's inaccessibility was what led to the triple fault...

Edit: Forget the sentence above!...


JJ