Triple faulting after setting up IDT with default ISRs
Posted: Tue Jan 10, 2023 9:37 pm
I have begun some further work on my current C-based OS project, specifically implementing a basic IDT populated with default ISRs. Unsurprisingly, at the moment this triple faults more or less as soon as I enable interrupts. The current code can be seen here, while the structure definitions are here.
The relevant declarations are:
as well as
While the code I suspect as being at fault is in these three functions (which are partly based on the Interrupts Tutorial):
Note that I deviated from the recommendations in the tutorial in that I defined the default ISR in C, using the GCC __attribute__((interrupt)) extension, rather than in assembly. I also tried breaking the attribute field of the IDT entries into separate bitfields, and while I doubt this is relevant, it is worth noting as another deviation from the tutorial's recommendations.
The output from QEMU with the -d int option set (for the section following the switch to p-mode) is as follows:
The relevant declarations are:
Code: Select all
#define IDT_SIZE 256
#define EXCEPTIONS_SIZE 32
enum IDT_gate_type: uint8_t // note: requires -std=c2x for typed enum support
{
TASK_GATE = 0x05,
INT_GATE_16 = 0x06,
TRAP_GATE_16 = 0x07,
INT_GATE_32 = 0x0E,
TRAP_GATE_32 = 0x0F
};
struct IDT_R
{
uint16_t size;
uint32_t base;
} __attribute__((packed));
struct Interrupt_Descriptor_32
{
uint16_t offset_low;
enum GDT_entry segment_selector;
uint8_t reserved;
struct
{
uint8_t gate_type:4;
uint8_t zero:1;
uint8_t dpl:2;
uint8_t p:1;
} attributes;
uint16_t offset_high;
} __attribute__((packed));
struct Interrupt_Frame
{
uint16_t ip;
uint16_t cs;
uint16_t flags;
uint16_t sp;
uint16_t ss;
} __attribute__((packed));
Code: Select all
__attribute__((aligned(0x10))) static struct IDT_R idt_r;
__attribute__((aligned(0x10))) static struct Interrupt_Descriptor_32 idt[IDT_SIZE];
Code: Select all
void idt_set_descriptor(uint8_t vector, void isr(struct Interrupt_Frame*), enum PRIVILEGE_LEVEL dpl, enum IDT_gate_type gate_type)
{
struct Interrupt_Descriptor_32* descriptor = &idt[vector];
descriptor->offset_low = (uint16_t) ((uint32_t) isr & 0xFFFF);
descriptor->segment_selector = system_code_entry;
descriptor->attributes.p = 1;
descriptor->attributes.dpl = dpl;
descriptor->attributes.zero = 0;
descriptor->attributes.gate_type = gate_type;
descriptor->offset_high = (uint16_t) ((uint32_t) isr >> 16);
descriptor->reserved = 0;
}
__attribute__((interrupt)) void default_exception_handler(struct Interrupt_Frame* frame)
{
disable_interrupts();
clear_screen();
kprints("Unhandled exception.", WHITE, BLACK, 0);
__asm__("hlt");
}
void init_default_interrupts()
{
// initialize the values to put into the IDT register
idt_r.base = (uintptr_t) &idt[0];
idt_r.size = (uint16_t) sizeof(struct Interrupt_Descriptor_32) * IDT_SIZE - 1;
// As a precaution, populate the IDT with default ISRs.
// This is done in two phases, first populating the exception handlers,
// then populating the interrupt handlers.
for (uint8_t vector = 0; vector < (EXCEPTIONS_SIZE - 1); vector++)
{
idt_set_descriptor(vector, default_exception_handler, RING_0, TRAP_GATE_32);
}
for (uint8_t vector = EXCEPTIONS_SIZE; vector < (IDT_SIZE - 1); vector++)
{
idt_set_descriptor(vector, default_interrupt_handler, RING_0, INT_GATE_32);
}
// add exception-specific handlers
idt_set_descriptor(0x00, div_zero_exception_handler, RING_0, TRAP_GATE_32);
idt_set_descriptor(0x08, double_fault_exception_handler, RING_0, TRAP_GATE_32);
// add interrupt-specific handlers
load_IDT(&idt_r);
}
The output from QEMU with the -d int option set (for the section following the switch to p-mode) is as follows:
Code: Select all
Servicing hardware INT=0x08
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x08
[... several lines repeating this ...]
36: v=08 e=0000 i=0 cpl=0 IP=0008:00000000c0000006 pc=00000000c0000006 SP=0010:00000000c00ffffc env->regs[R_EAX]=00000000c0003070
EAX=c0003070 EBX=00040c00 ECX=0000000f EDX=0000c000
ESI=0000b482 EDI=00000004 EBP=0000ffde ESP=c00ffffc
EIP=c0000006 EFL=00000282 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 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 =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= 0000b616 00000100
IDT= fff4c000 00003010
CR0=80000011 CR2=00000000 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000080 CCD=c00fffc4 CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0xffffffff new 0xe
37: v=0e e=0000 i=0 cpl=0 IP=0008:00000000c0000006 pc=00000000c0000006 SP=0010:00000000c00ffffc CR2=00000000fff4c040
EAX=c0003070 EBX=00040c00 ECX=0000000f EDX=0000c000
ESI=0000b482 EDI=00000004 EBP=0000ffde ESP=c00ffffc
EIP=c0000006 EFL=00000282 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 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 =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= 0000b616 00000100
IDT= fff4c000 00003010
CR0=80000011 CR2=fff4c040 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000080 CCD=c00fffc4 CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0xe new 0xe
38: v=08 e=0000 i=0 cpl=0 IP=0008:00000000c0000006 pc=00000000c0000006 SP=0010:00000000c00ffffc env->regs[R_EAX]=00000000c0003070
EAX=c0003070 EBX=00040c00 ECX=0000000f EDX=0000c000
ESI=0000b482 EDI=00000004 EBP=0000ffde ESP=c00ffffc
EIP=c0000006 EFL=00000282 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 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 =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= 0000b616 00000100
IDT= fff4c000 00003010
CR0=80000011 CR2=fff4c070 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000080 CCD=c00fffc4 CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0x8 new 0xe
39: v=03 e=0000 i=1 cpl=0 IP=0008:00000000000f35ea pc=00000000000f35ea SP=0010:0000000000000fc8 env->regs[R_EAX]=0000000000000006
EAX=00000006 EBX=00000000 ECX=00000000 EDX=00000cf9
ESI=00000000 EDI=00100000 EBP=00000000 ESP=00000fc8
EIP=000f35ea 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= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=000f74a8 CCD=00008b54 CCO=CLR
EFER=0000000000000000
check_exception old: 0xffffffff new 0xd
40: v=0d e=001a i=0 cpl=0 IP=0008:00000000000f35ea pc=00000000000f35ea SP=0010:0000000000000fc8 env->regs[R_EAX]=0000000000000006
EAX=00000006 EBX=00000000 ECX=00000000 EDX=00000cf9
ESI=00000000 EDI=00100000 EBP=00000000 ESP=00000fc8
EIP=000f35ea 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= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=000f74a8 CCD=00008b54 CCO=CLR
EFER=0000000000000000
check_exception old: 0xd new 0xd
41: v=08 e=0000 i=0 cpl=0 IP=0008:00000000000f35ea pc=00000000000f35ea SP=0010:0000000000000fc8 env->regs[R_EAX]=0000000000000006
EAX=00000006 EBX=00000000 ECX=00000000 EDX=00000cf9
ESI=00000000 EDI=00100000 EBP=00000000 ESP=00000fc8
EIP=000f35ea 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= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=000f74a8 CCD=00008b54 CCO=CLR
EFER=0000000000000000
check_exception old: 0x8 new 0xd
SMM: enter
EAX=00000001 EBX=00000000 ECX=02000000 EDX=02000628
ESI=0000000b EDI=02000000 EBP=000a0000 ESP=00006c58
EIP=000ef1cd EFL=00000002 [-------] 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= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000080 CCD=00000001 CCO=LOGICB
EFER=0000000000000000
SMM: after RSM
EAX=00000001 EBX=00000000 ECX=02000000 EDX=02000628
ESI=0000000b EDI=02000000 EBP=000a0000 ESP=00006c58
EIP=000ef1cd EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
Servicing hardware INT=0x08
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=00006cff
ESI=00006cc0 EDI=06fff5fd EBP=00006c80 ESP=00006c80
EIP=00008742 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =0000 00000000 ffffffff 008f9300
DS =0000 00000000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =0000 00000000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00006c80 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=00006cff
ESI=00006cc0 EDI=06fff5fd EBP=00006c80 ESP=00006c80
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=06feb0c0
ESI=000ecae0 EDI=06fff5fd EBP=00006c80 ESP=00006c80
EIP=000f875c EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f7460 00000037
IDT= 000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00006c6c CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=06feb0c0
ESI=000ecae0 EDI=06fff5fd EBP=00006c80 ESP=00006c80
EIP=0000875d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =0000 00000000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000