Page 1 of 1

Triple fault in bochs on the second instruction after sti

Posted: Tue Mar 08, 2016 5:23 pm
by Pyrofan1
The triple fault occurs after I set up the GDT. Relevant portions of code

Code: Select all

asm volatile("cli");
    asm volatile("lgdt %0" : : "m"(location));
    loadSegments();
    BOCHS_BREAK();
    asm volatile("sti");
    /*/asm volatile("mov $0xFFFFFFFF, %%eax\n\t"
                 "mov $0xFFFFFFFF, %%ebx\n\t" : : :"ebx", "eax");*/ //triple fault happens on this instruction
    asm volatile("nop\n\t"
                 "nop\n\t" //or this one if the above code is commented out
                 "nop\n\t"
                 "nop\n\t");

Code: Select all

loadSegments:
    ljmp $0x08, $loadcs
loadcs:
    mov $0x10, %ax
    mov %ax, %ds
    mov %ax, %ss
    mov %ax, %fs
    mov %ax, %gs
    mov %ax, %es

    ret
I've set up the gdt with a 32 bit code and data segment as well as a 64 bit code and data segment to be used later. The gdt is successfully loaded and bochs confirms this

Code: Select all

GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, 64-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write
After experimenting a little, I've found that the triple fault happens on the second instruction after the sti instruction. I've tested it with several instructions ret (where I first noticed it), add, push and nop. It also happens at a different memory address when the instructions are different sizes. For example with nops, the fault happens at 0x100850, while with add it happens at 0x100855. It's particularly puzzling because an exception should only occur with nop when used with the lock prefix. Bochs shows that a GPF is the exception that happens, but I'm not sure how a nop could generate a GPF when my segments are set up correctly.

Code: Select all

00185622638e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
00185622638e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
00185622638e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
00185622638i[CPU0  ] CPU is in protected mode (active)
00185622638i[CPU0  ] CS.mode = 32 bit
00185622638i[CPU0  ] SS.mode = 32 bit
00185622638i[CPU0  ] EFER   = 0x00000000
00185622638i[CPU0  ] | EAX=00000010  EBX=00010000  ECX=00000028  EDX=ffffffff
00185622638i[CPU0  ] | ESP=0010c3bc  EBP=0010c400  ESI=00000000  EDI=00000000
00185622638i[CPU0  ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf ZF af PF cf
00185622638i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00185622638i[CPU0  ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] |  FS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] |  GS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00185622638i[CPU0  ] | EIP=00100850 (00100850)
00185622638i[CPU0  ] | CR0=0x60000011 CR2=0x00000000
00185622638i[CPU0  ] | CR3=0x00000000 CR4=0x00000000
00185622638e[CPU0  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
This code occurs in multiple versions of bochs, but doesn't happen in qemu.

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 6:12 pm
by Brendan
Hi,
Pyrofan1 wrote:

Code: Select all

00185622638e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0

Code: Select all

00185622638i[CPU0  ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf ZF af PF cf
An IRQ occurred (because your "STI" enabled IRQs) causing the CPU to try to start an interrupt handler; but your IDT is not valid (IDT limit is zero) so CPU can't start the interrupt handler and generates an exception instead (which causes another exception which causes double fault which causes triple fault, because the IDT is not valid for any interrupt).


Cheers,

Brendan

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 7:36 pm
by Pyrofan1
It seems like I'm getting interrupts from the PIT on interrupt #8 because I haven't remapped the PIC. The thing is that I'm planning on using the APIC so I disabled the PIC like so.

Code: Select all

//acknowledge any current IRQs
    outportb(0xA0, 0x20);
    outportb(0x20, 0x20);
//disable the PIC
    outportb(0xA1, 0xFF);
    outportb(0x21, 0xFF);
But it doesn't seem to be working

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 8:12 pm
by FallenAvatar
Since you haven't setup an IDT, why are you enabling interrupts? Either don't enable interrupts, or setup an IDT.

- Monk

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 8:19 pm
by Pyrofan1
I do have an IDT setup at this point.

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 8:28 pm
by FallenAvatar
00185622638e[CPU0 ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
Bochs says you are lying.

- Monk

Re: Triple fault in bochs on the second instruction after st

Posted: Tue Mar 08, 2016 8:53 pm
by Pyrofan1
I fixed the issue in my original post. My current issue is that I'm still getting interrupts from the PIT even though I have disabled the PIC.

Re: Triple fault in bochs on the second instruction after st

Posted: Wed Mar 09, 2016 7:15 am
by Combuster
I still see no IDT. I still see no code to mask all PIC interrupts.

Re: Triple fault in bochs on the second instruction after st

Posted: Wed Mar 09, 2016 11:26 am
by Pyrofan1
Here is a dump of my IDT, though I'm not sure how it's relevant. All the non-listed entries are marked as not present.

Code: Select all

Interrupt Descriptor Table (base=0x0000000000103040, limit=2048):
IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x0010084e, DPL=0
IDT[0x01]=32-Bit Interrupt Gate target=0x0008:0x00100854, DPL=0
IDT[0x02]=32-Bit Interrupt Gate target=0x0008:0x0010085a, DPL=0
IDT[0x03]=32-Bit Interrupt Gate target=0x0008:0x00100860, DPL=0
IDT[0x04]=32-Bit Interrupt Gate target=0x0008:0x00100866, DPL=0
IDT[0x05]=32-Bit Interrupt Gate target=0x0008:0x0010086c, DPL=0
IDT[0x06]=32-Bit Interrupt Gate target=0x0008:0x00100872, DPL=0
IDT[0x07]=32-Bit Interrupt Gate target=0x0008:0x00100878, DPL=0
IDT[0x08]=32-Bit Interrupt Gate target=0x0008:0x0010087e, DPL=0
IDT[0x09]=32-Bit Interrupt Gate target=0x0008:0x00100882, DPL=0
IDT[0x0a]=32-Bit Interrupt Gate target=0x0008:0x00100888, DPL=0
IDT[0x0b]=32-Bit Interrupt Gate target=0x0008:0x0010088c, DPL=0
IDT[0x0c]=32-Bit Interrupt Gate target=0x0008:0x00100890, DPL=0
IDT[0x0d]=32-Bit Interrupt Gate target=0x0008:0x00100894, DPL=0
IDT[0x0e]=32-Bit Interrupt Gate target=0x0008:0x00100898, DPL=0
IDT[0x0f]=32-Bit Interrupt Gate target=0x0008:0x0010089c, DPL=0
IDT[0x10]=32-Bit Interrupt Gate target=0x0008:0x001008a2, DPL=0
IDT[0x11]=32-Bit Interrupt Gate target=0x0008:0x001008a8, DPL=0
IDT[0x12]=32-Bit Interrupt Gate target=0x0008:0x001008ac, DPL=0
IDT[0x13]=32-Bit Interrupt Gate target=0x0008:0x001008b2, DPL=0
IDT[0x14]=32-Bit Interrupt Gate target=0x0008:0x001008b8, DPL=0
IDT[0x15]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x16]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x17]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x18]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x19]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1a]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1b]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1c]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1d]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1e]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
IDT[0x1f]=32-Bit Interrupt Gate target=0x0008:0x001008be, DPL=0
Combuster wrote:I still see no code to mask all PIC interrupts.
Pyrofan1 wrote:It seems like I'm getting interrupts from the PIT on interrupt #8 because I haven't remapped the PIC. The thing is that I'm planning on using the APIC so I disabled the PIC like so.

Code: Select all

//acknowledge any current IRQs
    outportb(0xA0, 0x20);
    outportb(0x20, 0x20);
//disable the PIC
    outportb(0xA1, 0xFF);
    outportb(0x21, 0xFF);
But it doesn't seem to be working

Re: Triple fault in bochs on the second instruction after st

Posted: Wed Mar 09, 2016 12:46 pm
by BrightLight
At least in my Bochs, I needed a short delay after I disabled the PIC before it stopped sending interrupts. I waited for IRQs to happen during this short delay, but seeing as your IDT is not working...
If you have a 16-bit stub, it would work...

Re: Triple fault in bochs on the second instruction after st

Posted: Wed Mar 09, 2016 1:22 pm
by Pyrofan1
At least in my Bochs, I needed a short delay after I disabled the PIC before it stopped sending interrupts.
I was not aware of that. I ending up remapping the PIC and filling the rest of the IDT with handlers that only acknowledge the IRQ before disabling the PIC. This works out perfectly, especially since I only need the IDT to handle exceptions before I enter long mode and setup a 64 bit IDT.