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 / gdt.c
diff --git a/geekos/src/geekos/gdt.c b/geekos/src/geekos/gdt.c
new file mode 100644 (file)
index 0000000..707e34a
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Initialize kernel GDT.
+ * 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".
+ */
+
+#include <geekos/kassert.h>
+#include <geekos/segment.h>
+#include <geekos/int.h>
+#include <geekos/tss.h>
+#include <geekos/gdt.h>
+#include <libc/string.h>
+
+#include <geekos/debug.h>
+
+/*
+ * This is defined in lowlevel.asm.
+ */
+extern void Load_GDTR(ushort_t* limitAndBase);
+
+/* ----------------------------------------------------------------------
+ * Data
+ * ---------------------------------------------------------------------- */
+
+/*
+ * Number of entries in the kernel GDT.
+ */
+#define NUM_GDT_ENTRIES 16
+
+/*
+ * This is the kernel's global descriptor table.
+ */
+struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES];
+/*
+ * Number of allocated GDT entries.
+ */
+static int s_numAllocated = 0;
+
+
+
+
+
+void DumpGDT()
+{
+  int i;
+  PrintBoth("GDT Contents:\n");
+
+  for (i=0;i<NUM_GDT_ENTRIES;i++) { 
+    if (s_GDT[i].present) { 
+      PrintBoth("%d: base=%u, limit=%u, sizeLow=%u,  baseLow=%u, type=%u, system=%u, dpl=%u, preent=%u, sizeHigh=%u, avail=%u, reserved=%u, dbBit=%u, granularity=%u, baseHigh=%u\n", 
+           i,
+           (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
+           (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
+           s_GDT[i].sizeLow,
+           s_GDT[i].baseLow,
+           s_GDT[i].type,
+           s_GDT[i].system,
+           s_GDT[i].dpl,
+           s_GDT[i].present,
+           s_GDT[i].sizeHigh,
+           s_GDT[i].avail,
+           s_GDT[i].reserved,
+           s_GDT[i].dbBit,
+           s_GDT[i].granularity,
+           s_GDT[i].baseHigh  );
+    } else {
+      PrintBoth("%d: Not Present\n",i);
+    }
+  }
+}
+
+
+/* ----------------------------------------------------------------------
+ * Functions
+ * ---------------------------------------------------------------------- */
+
+/*
+ * Allocate an descriptor from the GDT.
+ * Returns null if there are none left.
+ */
+struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
+{
+    struct Segment_Descriptor* result = 0;
+    int i;
+    bool iflag;
+
+    iflag = Begin_Int_Atomic();
+
+    /* Note; entry 0 is unused (thus never allocated) */
+    for (i = 1; i < NUM_GDT_ENTRIES; ++i) {
+       struct Segment_Descriptor *desc = &s_GDT[ i ];
+       if (desc->avail) {
+           ++s_numAllocated;
+           desc->avail = 0;
+           result = desc;
+           break;
+       }
+    }
+
+    End_Int_Atomic(iflag);
+
+    return result;
+}
+
+/*
+ * Free a segment descriptor.
+ */
+void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
+{
+    bool iflag = Begin_Int_Atomic();
+
+    KASSERT(!desc->avail);
+
+    Init_Null_Segment_Descriptor(desc);
+    desc->avail = 1;
+    --s_numAllocated;
+
+    End_Int_Atomic(iflag);
+}
+
+/*
+ * Get the index (int the GDT) of given segment descriptor.
+ */
+int Get_Descriptor_Index(struct Segment_Descriptor* desc)
+{
+    return (int) (desc - s_GDT);
+}
+
+/*
+ * Initialize the kernel's GDT.
+ */
+void Init_GDT(void)
+{
+    ushort_t limitAndBase[3];
+    ulong_t gdtBaseAddr = (ulong_t) s_GDT;
+    struct Segment_Descriptor* desc;
+    int i;
+
+
+    KASSERT(sizeof(struct Segment_Descriptor) == 8);
+
+    /* Clear out entries. */
+    for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
+       desc = &s_GDT[ i ];
+       Init_Null_Segment_Descriptor(desc);
+       desc->avail = 1;
+    }
+
+    /* Kernel code segment. */
+    desc = Allocate_Segment_Descriptor();
+    Init_Code_Segment_Descriptor(
+       desc,
+       0,               /* base address */
+       0x100000,        /* num pages (== 2^20) */
+       0                /* privilege level (0 == kernel) */
+    );
+    KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
+
+    /* Kernel data segment. */
+    desc = Allocate_Segment_Descriptor();
+    Init_Data_Segment_Descriptor(
+       desc,
+       0,               /* base address */
+       0x100000,        /* num pages (== 2^20) */
+       0                /* privilege level (0 == kernel) */
+    );
+    KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
+
+    Print("GDT: Base=0x%.8x, limit=%d\n", (uint_t)gdtBaseAddr,  (uint_t)(sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES));
+
+    /* Activate the kernel GDT. */
+    limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES;
+    limitAndBase[1] = gdtBaseAddr & 0xffff;
+    limitAndBase[2] = gdtBaseAddr >> 16;
+    Load_GDTR(limitAndBase);
+}