4
votes

As part of some OS development for a 32-bit x86 processor, I am considering using an task gate in the interrupt descriptor table for the page fault vector. The aim is to force a task switch so that the handler's stack will be guaranteed to be mapped (and avoid the case wherein part of stack of the interrupted task was not mapped).

I am running my kernel (such as it is) under QEMU, but am finding that when the page fault occurs, it crashes (I'm back to command prompt). I've been reading and digging searching for hints that may help me figure out the exact cause. I figure that I am missing something and/or have misunderstood something. Incidentally, when I set the page fault vecotr up to use an interrupt gate, I can get things to work as I expect them. It is when I try to use a task gate for this that I encounter problems (and yes, I do want to persist in trying to use the task gate).

The IDT portion is set up correctly to register a task gate for the page fault vector. Its selector refers to a descriptor for the TSS in the GDT. As far as the descriptor for the TSS in the GDT, I am certain that too is set up properly.

However, I am not 100% certain if I have the TSS properly populated and have been unable thus far to determine exactly how to set up all of its fields. Some of them such as esp, eip, cs, ds, es, fs, gs, ss and eflags have been relatively straight forward. However, others such as the LDT segment selector are less clear. Must the LDT segment selector be non-zero AND point to an LDT descriptor in the GDT? Which of these fields must be set for the scenario described above? I am having a heck of time figuring this one out.

Any help would be greatly appreciated.

1
Just in case you've forgotten, a task is still a task and not a subroutine even when interrupts and exceptions trigger its execution. That means, it must have the main loop so when it finishes handling the first interrupt/exception and executes IRET, its state will be such that the next time it will continue running at the instruction immediately following this IRET. If there's "nothing" after IRET, it'll crash.Alexey Frunze
Another thing to note. If you want to switch to a task, it must be done from a task. Task switching is always from a task and to a task. You can't have only one TSS, the one for the page fault handler. You have to have at least two different ones. If you try to switch from an invalid task (invalid TR or invalid TSS it points to (e.g. incorrectly initialized TSS fields)) or to an invalid task, you'll get an exception and likely crash.Alexey Frunze

1 Answers

0
votes

The LDT is not necessary in a correctly functioning x86 operating system (indeed, it is forbidden in a x86-64 operating system).

To avoid using it, set it to zero.

One thing in particular to be aware of - the structures on osdev.org about TSS is back-to-front (http://wiki.osdev.org/TSS). You'll need to be careful, since getting the TSS wrong will trigger a TSS-fault exception.