Page 1 of 1

Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 1:48 am
by yucarp
I am trying to set the IDT right now and this issue baffles me. Loading the IDT works correctly and the GDT is working too as I can do a long jump. I am also sure that all registers are pushed and popped. The structure of table entries are also correct if I didn't miss anything. EDIT: I found out that the IDT pointer isn't actually loaded but I don't know why

Code: Select all

#include <kernel/idt.h>

static struct IDTPointer idt_pointer;
static struct IDTEntry idt_entries[256];

void idt_set_gate(uint8_t n, uint32_t handler, uint16_t selector, uint8_t attributes){
    idt_entries[n].offset_low = (handler & 0xFFFF);
    idt_entries[n].offset_high = ((handler >> 16) & 0xFFFF);
    idt_entries[n].selector = selector;
    idt_entries[n].attributes = attributes;
}

void set_idt(){
    idt_pointer.offset = (uint32_t)(idt_entries);
    idt_pointer.size = sizeof(idt_entries);

    idt_set_gate(0, (uint32_t)_isr0, 0x08, 0x8E);

    asm volatile (
        "lidt %0"
        : : "m"(idt_pointer)
    );
}

void isr_handler(){
    *((char *)(0xB800)) = 'I';
}

Code: Select all

.global _isr0
.type _isr0, @function
_isr0:
    pushl $0
    pushl $0
    jmp isr_common

.extern isr_handler
.type isr_handler, @function

.global isr_common
isr_common:
    pushl %eax
    pushl %ebx
    pushl %ecx
    pushl %edx
    pushl %esi
    pushl %edi
    pushl %ebp
    pushl %esp

    cld
    call isr_handler

    popl %esp
    popl %ebp
    popl %edi
    popl %esi
    popl %edx
    popl %ecx
    popl %ebx
    popl %eax

    add $8, %esp

    iretl
QEMU log:

Code: Select all

     9: v=00 e=0000 i=1 cpl=0 IP=0008:00200072 pc=00200072 SP=0010:00204ff0 env->regs[R_EAX]=00000020
EAX=00000020 EBX=00010000 ECX=00000000 EDX=00000008
ESI=00000000 EDI=00000000 EBP=00204ff8 ESP=00204ff0
EIP=00200072 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00200006 00000028
IDT=     50000000 00000800
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000040 CCD=00000020 CCO=SARL
EFER=0000000000000000
check_exception old: 0xffffffff new 0xd
    10: v=0d e=0002 i=0 cpl=0 IP=0008:00200072 pc=00200072 SP=0010:00204ff0 env->regs[R_EAX]=00000020
EAX=00000020 EBX=00010000 ECX=00000000 EDX=00000008
ESI=00000000 EDI=00000000 EBP=00204ff8 ESP=00204ff0
EIP=00200072 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00200006 00000028
IDT=     50000000 00000800
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000040 CCD=00000020 CCO=SARL
EFER=0000000000000000
check_exception old: 0xd new 0xd
    11: v=08 e=0000 i=0 cpl=0 IP=0008:00200072 pc=00200072 SP=0010:00204ff0 env->regs[R_EAX]=00000020
EAX=00000020 EBX=00010000 ECX=00000000 EDX=00000008
ESI=00000000 EDI=00000000 EBP=00204ff8 ESP=00204ff0
EIP=00200072 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00200006 00000028
IDT=     50000000 00000800
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000040 CCD=00000020 CCO=SARL
EFER=0000000000000000
check_exception old: 0x8 new 0xd
SMM: enter
EAX=00000000 EBX=00000000 ECX=02000000 EDX=02000628
ESI=0000000b EDI=02000000 EBP=00014e40 ESP=00006c5c
EIP=000ea63d EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f61e0 00000037
IDT=     000f621e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000044 CCD=ffffffff CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 8:05 am
by nullplan
I suspect you failed to declare you struct IDTPointer with the "packet" attribute. This causes the data to not be in the right place for the "lidt" instruction.

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 8:16 am
by yucarp
nullplan wrote: Sat Dec 06, 2025 8:05 am I suspect you failed to declare you struct IDTPointer with the "packet" attribute. This causes the data to not be in the right place for the "lidt" instruction.
Nope, after trying packaging the pointers it still triple faults with the same errors.

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 10:25 am
by nullplan
Well, whatever the case, the error is not anywhere in the code you have posted, and you already know that the IDTR contents are wrong, so you need to figure out what data exactly you are giving to the LIDT instruction. It's supposed to be a two-byte value containing the IDT limit, followed by a 4 byte value containing the base pointer, with no padding in between.

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 1:22 pm
by yucarp
Well, I checked it a lot and the size of the IDT pointer was always 6. I have also checked if I was giving the address instead of pointer but it didn't help too. It's really mysterious, everything seems right but it always gives the same fault.

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 3:11 pm
by sebihepp
Limit of IDTD must be size-1. I doubt that's the problem right now, but should nevertheless be fixed.

I think we need the contents of idt.h too. Or better: the entire project. A link to github would be nice.

Re: Triple fault after calling INT 0

Posted: Sat Dec 06, 2025 4:00 pm
by iansjack
Two things you can try:

1. Disassemble your code with objdmp and examine the bit where the lidt instruction is.

2. Step through that part of the code in a debugger to see what’s happening (or isn’t).

Re: Triple fault after calling INT 0

Posted: Sun Dec 07, 2025 2:01 am
by yucarp
Well, I noticed something weird, there is no ".data" section in the kernel executable. When I try to put the GDT into the data section it suddenly stops being a valid multiboot executable. Neither the pointer I put and the IDT table is in the executable. Don't mind the crude GDT table with only kernel segments, it's only for testing.

https://github.com/yucarp/ric There is the github for who are interested

Re: Triple fault after calling INT 0

Posted: Sun Dec 07, 2025 7:54 am
by nullplan
You have no .data section because you have no initialized data. There is no issue with this. The IDT is in the .bss section, so doesn't need to be in the executable.

I tried to find what the problem might be, but I don't see the issue. According to the disassembler, the IDTR should be set correctly. And indeed when I run it in QEMU, I get output saying the IDTR is loaded correctly. However, the interrupt is happening at PC=0008:00000207, which is not in the kernel binary at all. No, it seems like your interrupt gate is incorrect, and the interrupt instruction sends the execution off into the woods.

Re: Triple fault after calling INT 0

Posted: Sun Dec 07, 2025 9:27 am
by yucarp
Thank you so much! It worked after setting the gate setter function to take a void pointer instead of a converted uint32_t and doing a shift operation instead of an and operation to get the higher portion of the offset. I don't know why it happened but probably the pointer got altered in the function.

Re: Triple fault after calling INT 0

Posted: Sun Feb 15, 2026 1:10 am
by DabiiXqx
yucarp wrote: Sun Dec 07, 2025 9:27 am Thank you so much! It worked after setting the gate setter function to take a void pointer instead of a converted uint32_t and doing a shift operation instead of an and operation to get the higher portion of the offset. I don't know why it happened but probably the pointer got altered in the function.

May i have the code please?

Re: Triple fault after calling INT 0

Posted: Sun Feb 15, 2026 11:16 am
by yucarp
I have abandoned that project in order to work a new one but the old project can be found in https://github.com/yucarp/ric/tree/main

Re: Triple fault after calling INT 0

Posted: Tue Feb 17, 2026 7:34 am
by DabiiXqx
thank you