next up previous
Next: The test operating system Up: Solution description Previous: x86 implementation outline

IA32 low-level functions implementation details

This section briefly describes the behavior of the IA32 implementation of the functions defined in Sartoris' low-level interface.

arch_init_cpu: (invoked from the bootsector)
PIC reprogramming. The init functions reprograms the programmable interrupt controllers so that the interrupts from the master controller go to the offsets 32-39 and interrupts from the slave controller go to offsets 40-47 of the IDT. The slave PIC is cascaded through the second interrupt request line of the master. All the interrupts are disabled though the PICs interrupt masks.
GDT set up. The dummy, kernel code, kernel data and high memory area descriptors of the GDT are created. All the other descriptors are invalidated.
syscall hooking. All the task gates for the system calls are created in the corresponding GDT positions.
IDT set up. The fist 32 entries of the IDT are filled with interrupt gates8 that point to routines that will dump the cpu registers and information about the currently running task and thread and halt the machine. These handlers should be replaced by the operating system exception handling threads, but for operating system development and to show some diagnostic in case the operating system dies very early in the boot process these default handlers are useful. The rest of the IDT is full with invalid descriptors.
Init service execution. Now the cpu is ready to run the $\mu$-kernel. Using the create_task and create_thread system calls, the operating system init service is created at the exact address to which it was fetched earlier by the bootstrapping code, and executes using the run_thread system call. This is the last action the microkernel will take on it's own initiative.

arch_create_task:
LDT set up. An execute-read segment and a read-write segment are created in the task's local descriptor table first and second descriptors, with the privilege level corresponding to the task being created and base and limit according to the corresponding syscall parameters.
create LDT descriptor. The GDT descriptor for this LDT is created with the correct privilege level.

arch_destroy_task:
invalidate LDT descriptor. The task's LDT descriptor is invalidated, preventing any future access to or execution from the task's address space.

arch_create_thread:
TSS set up. The Task State Segment holds the contents of all the general purpose registers, the base and stack registers for all the privilege levels, the segment selector registers, the eflags register, the LDT selector register, the instruction pointer register, and a few more that are not used under Sartoris.
create TSS descriptor. Once the TSS is in place, a descriptor in the GDT must be created through which the thread may be started and resumed.

arch_run_thread:
do task switch. A task switch to the target thread is initiated by performing a far jump to offset zero of the thread's TSS descriptor in the GDT. No nesting of tasks is produced.

arch_cli:
disable interrupts. The interrupt enable bit of the eflags register is saved and then cleared. The function returns the original value.

arch_sti:
enable interrupts. The previous value of the interrupt enable bit is examined and interrupts are re-enabled only if they weren't disabled before the call to the previous arch_cli.


next up previous
Next: The test operating system Up: Solution description Previous: x86 implementation outline
2002-09-17