Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / geekos / tss.c
diff --git a/geekos/src/geekos/tss.c b/geekos/src/geekos/tss.c
new file mode 100644 (file)
index 0000000..3a72fb0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * x86 TSS data structure and routines
+ * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
+ * $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 <geekos/kassert.h>
+#include <geekos/defs.h>
+#include <geekos/gdt.h>
+#include <geekos/segment.h>
+#include <geekos/string.h>
+#include <geekos/tss.h>
+
+#include <geekos/serial.h>
+#include <geekos/debug.h>
+
+
+/*
+ * 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;
+}
+
+
+
+/* ** */