2 * Initialize kernel GDT.
3 * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
6 * This is free software. You are permitted to use,
7 * redistribute, and modify it as specified in the file "COPYING".
10 #include <geekos/kassert.h>
11 #include <geekos/segment.h>
12 #include <geekos/int.h>
13 #include <geekos/tss.h>
14 #include <geekos/gdt.h>
15 #include <libc/string.h>
19 * This is defined in lowlevel.asm.
21 extern void Load_GDTR(ushort_t* limitAndBase);
23 /* ----------------------------------------------------------------------
25 * ---------------------------------------------------------------------- */
28 * Number of entries in the kernel GDT.
30 #define NUM_GDT_ENTRIES 16
33 * This is the kernel's global descriptor table.
35 // JRL: why??? Should just call Alloc_Page(), otherwise we have dependencies all over the place
36 //struct Segment_Descriptor *s_GDT=(struct Segment_Descriptor *)GDT_LOCATION;
37 static struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES];
41 * Number of allocated GDT entries.
43 static int s_numAllocated = 0;
52 Print("GDT Contents:\n");
54 for (i=0;i<NUM_GDT_ENTRIES;i++) {
55 if (s_GDT[i].present) {
56 Print("%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",
58 (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
59 (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
73 Print("%d: Not Present\n",i);
79 /* ----------------------------------------------------------------------
81 * ---------------------------------------------------------------------- */
84 * Allocate an descriptor from the GDT.
85 * Returns null if there are none left.
87 struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
89 struct Segment_Descriptor* result = 0;
93 iflag = Begin_Int_Atomic();
95 /* Note; entry 0 is unused (thus never allocated) */
96 for (i = 1; i < NUM_GDT_ENTRIES; ++i) {
97 struct Segment_Descriptor *desc = &s_GDT[ i ];
106 End_Int_Atomic(iflag);
112 * Free a segment descriptor.
114 void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
116 bool iflag = Begin_Int_Atomic();
118 KASSERT(!desc->avail);
120 Init_Null_Segment_Descriptor(desc);
124 End_Int_Atomic(iflag);
128 * Get the index (int the GDT) of given segment descriptor.
130 int Get_Descriptor_Index(struct Segment_Descriptor* desc)
132 return (int) (desc - s_GDT);
136 * Initialize the kernel's GDT.
140 ushort_t limitAndBase[3];
141 ulong_t gdtBaseAddr = (ulong_t) s_GDT;
142 struct Segment_Descriptor* desc;
145 Print("GDT Placed at %x, %d entries\n",GDT_LOCATION,NUM_GDT_ENTRIES);
147 KASSERT(sizeof(struct Segment_Descriptor) == 8);
149 /* Clear out entries. */
150 for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
152 Init_Null_Segment_Descriptor(desc);
156 /* Kernel code segment. */
157 desc = Allocate_Segment_Descriptor();
158 Init_Code_Segment_Descriptor(
160 0, /* base address */
161 0x100000, /* num pages (== 2^20) */
162 0 /* privilege level (0 == kernel) */
164 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
166 /* Kernel data segment. */
167 desc = Allocate_Segment_Descriptor();
168 Init_Data_Segment_Descriptor(
170 0, /* base address */
171 0x100000, /* num pages (== 2^20) */
172 0 /* privilege level (0 == kernel) */
174 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
176 /* Activate the kernel GDT. */
177 limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES;
178 limitAndBase[1] = gdtBaseAddr & 0xffff;
179 limitAndBase[2] = gdtBaseAddr >> 16;
180 Load_GDTR(limitAndBase);