Triple fault when attempting to load the task register
Posted: Sat Jun 22, 2019 9:00 am
I've finished up writing my shell and filesystem for my operating system, and now have decided to move onto user mode and writing system calls. Though the difficulty I've been having in doing that is before actually entering user mode: trying to load a selector from the GDT into the task register, which results in a triple fault and the CPU resetting.
To setup the GDT, IDT, interrupts and exception handling, I followed http://www.osdever.net/bkerndev/Docs/intro.htm (bran's kernel development tutorial). Now for entering user mode, I was following http://jamesmolloy.co.uk/tutorial_html/ ... 0Mode.html (James Molly), but unfortunately couldn't get that to work. Since that wasn't working, I've been looking at other articles on this site about the GDT and exceptions, and the brokenthorne OS dev series to try and help me out. I've found some other questions similar to mine, but none of the answers there have helped me.
The specific instruction that is causing the processor to triple fault is
The code I am using to install the TSS is similar to Jame's Molly's:
I have read the article about the known bugs in that tutorial, and my code doesn't appear to have any of the problems discussed in that article.
This is the function I am using to initialize the GDT:
I added the flag to the qemu command when running my OS, and noticed it ended with a triple fault, with ~2 or 3 general protection faults before that. I tried debugging using gdb, but that didn't help since it still just crashed on the instruction and doesn't provide any other information.
I also read somewhere that a triple fault (or something of the sort) is the result of fault exception handling code. I'm pretty sure that my exception handling code is catching exceptions, because when I doI get a division by zero exception. The IRQs have been remapped and the timer is firing as expected. Should exceptions always result in the exception handler being called (as in my code should be catching exceptions) or are there occasions (like loading some invalid value into the task register) that won't be caught by the exception handler and immediately result in a triple fault/crash?).
My OS can be found at https://github.com/aaron2212/XOS, though I have not pushed the latest code about entering user mode, or rather, even just setting up the task state segment.
I have tried everything I can think of, and searched all of google with avail, so any help is greatly appreciated
To setup the GDT, IDT, interrupts and exception handling, I followed http://www.osdever.net/bkerndev/Docs/intro.htm (bran's kernel development tutorial). Now for entering user mode, I was following http://jamesmolloy.co.uk/tutorial_html/ ... 0Mode.html (James Molly), but unfortunately couldn't get that to work. Since that wasn't working, I've been looking at other articles on this site about the GDT and exceptions, and the brokenthorne OS dev series to try and help me out. I've found some other questions similar to mine, but none of the answers there have helped me.
The specific instruction that is causing the processor to triple fault is
Code: Select all
ltr %ax
Code: Select all
void install_tss(uint32_t i, uint16_t kernel_ss, uint16_t kernel_esp)
{
gdt_set_descriptor(i, 0x00, 0xFFFFFFFF, 0x89, 0x00);
memset(&tss_entry, 0, sizeof(tss_entry));
tss_entry.ss0 = kernel_ss;
tss_entry.esp0 = kernel_esp;
tss_entry.cs = 0x0b;
tss_entry.ss = 0x13;
tss_entry.es = 0x13;
tss_entry.ds = 0x13;
tss_entry.fs = 0x13;
tss_entry.gs = 0x13;
asm(
"mov $0x2b, %ax\n"
"ltr %ax"
);
}
This is the function I am using to initialize the GDT:
Code: Select all
void init_gdt()
{
gdt_ptr.limit = (sizeof(struct gdt_descriptor) * MAX_DESCRIPTORS) - 1;
gdt_ptr.base = (uint32_t) &gdt_desc;
gdt_set_descriptor(0, 0, 0, 0, 0); // Null descriptor
gdt_set_descriptor(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Kernel code descriptor
gdt_set_descriptor(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Kernel data descriptor
gdt_set_descriptor(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User code descriptor
gdt_set_descriptor(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User data descriptor
// Install the TSS to selector 5
install_tss(5, 0x10, 0x0);
/* install the GDT */
install_gdt();
}
Code: Select all
-d int,cpu_reset
Code: Select all
ltr
I also read somewhere that a triple fault (or something of the sort) is the result of fault exception handling code. I'm pretty sure that my exception handling code is catching exceptions, because when I do
Code: Select all
asm("int $0")
My OS can be found at https://github.com/aaron2212/XOS, though I have not pushed the latest code about entering user mode, or rather, even just setting up the task state segment.
I have tried everything I can think of, and searched all of google with avail, so any help is greatly appreciated