X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Ftss.c;fp=geekos%2Fsrc%2Fgeekos%2Ftss.c;h=3a72fb04185bde1b182740f010b591af9a25f8d8;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/tss.c b/geekos/src/geekos/tss.c new file mode 100644 index 0000000..3a72fb0 --- /dev/null +++ b/geekos/src/geekos/tss.c @@ -0,0 +1,102 @@ +/* + * x86 TSS data structure and routines + * Copyright (c) 2001,2004 David H. Hovemeyer + * $Revision: 1.4 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +/* + * Source: _Protected Mode Software Architecture_ by Tom Shanley, + * ISBN 020155447X. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* + * We use one TSS in GeekOS. + */ +static struct TSS s_theTSS; +static struct Segment_Descriptor *s_tssDesc; +static ushort_t s_tssSelector; + +static void __inline__ Load_Task_Register(void) +{ + + /* Critical: TSS must be marked as not busy */ + s_tssDesc->type = 0x09; + + /* Load the task register */ + __asm__ __volatile__ ( + "ltr %0" + : + : "a" (s_tssSelector) + ); +} + +/* + * Initialize the kernel TSS. This must be done after the memory and + * GDT initialization, but before the scheduler is started. + */ +void Init_TSS(void) +{ + PrintBoth("Initializing TSS\n"); + + s_tssDesc = Allocate_Segment_Descriptor(); + KASSERT(s_tssDesc != 0); + + memset(&s_theTSS, '\0', sizeof(struct TSS)); + Init_TSS_Descriptor(s_tssDesc, &s_theTSS); + + s_tssSelector = Selector(0, true, Get_Descriptor_Index(s_tssDesc)); + + Load_Task_Register(); +} + +/* + * Set kernel stack pointer. + * This should be called before switching to a new + * user process, so that interrupts occurring while executing + * in user mode will be delivered on the correct stack. + */ +void Set_Kernel_Stack_Pointer(ulong_t esp0) +{ + s_theTSS.ss0 = KERNEL_DS; + s_theTSS.esp0 = esp0; + + /* + * NOTE: I read on alt.os.development that it is necessary to + * reload the task register after modifying a TSS. + * I haven't verified this in the IA32 documentation, + * but there is certainly no harm in being paranoid. + */ + Load_Task_Register(); +} + + +/* JRL THIS FUCKING SUCKS */ + +uint_t GetTR_Base() { + return (uint_t)(&s_theTSS); +} +uint_t GetTR_Limit() { + return sizeof(struct TSS); +} + +ushort_t GetTR_Selector() { + return s_tssSelector; +} + + + +/* ** */