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 struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES];
37 * Number of allocated GDT entries.
39 static int s_numAllocated = 0;
48 Print("GDT Contents:\n");
50 for (i=0;i<NUM_GDT_ENTRIES;i++) {
51 if (s_GDT[i].present) {
52 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",
54 (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
55 (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
69 Print("%d: Not Present\n",i);
75 /* ----------------------------------------------------------------------
77 * ---------------------------------------------------------------------- */
80 * Allocate an descriptor from the GDT.
81 * Returns null if there are none left.
83 struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
85 struct Segment_Descriptor* result = 0;
89 iflag = Begin_Int_Atomic();
91 /* Note; entry 0 is unused (thus never allocated) */
92 for (i = 1; i < NUM_GDT_ENTRIES; ++i) {
93 struct Segment_Descriptor *desc = &s_GDT[ i ];
102 End_Int_Atomic(iflag);
108 * Free a segment descriptor.
110 void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
112 bool iflag = Begin_Int_Atomic();
114 KASSERT(!desc->avail);
116 Init_Null_Segment_Descriptor(desc);
120 End_Int_Atomic(iflag);
124 * Get the index (int the GDT) of given segment descriptor.
126 int Get_Descriptor_Index(struct Segment_Descriptor* desc)
128 return (int) (desc - s_GDT);
132 * Initialize the kernel's GDT.
136 ushort_t limitAndBase[3];
137 ulong_t gdtBaseAddr = (ulong_t) s_GDT;
138 struct Segment_Descriptor* desc;
142 KASSERT(sizeof(struct Segment_Descriptor) == 8);
144 /* Clear out entries. */
145 for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
147 Init_Null_Segment_Descriptor(desc);
151 /* Kernel code segment. */
152 desc = Allocate_Segment_Descriptor();
153 Init_Code_Segment_Descriptor(
155 0, /* base address */
156 0x100000, /* num pages (== 2^20) */
157 0 /* privilege level (0 == kernel) */
159 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
161 /* Kernel data segment. */
162 desc = Allocate_Segment_Descriptor();
163 Init_Data_Segment_Descriptor(
165 0, /* base address */
166 0x100000, /* num pages (== 2^20) */
167 0 /* privilege level (0 == kernel) */
169 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
171 Print("GDT: Base=0x%.8x, limit=%d\n", (uint_t)gdtBaseAddr, (uint_t)(sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES));
173 /* Activate the kernel GDT. */
174 limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES;
175 limitAndBase[1] = gdtBaseAddr & 0xffff;
176 limitAndBase[2] = gdtBaseAddr >> 16;
177 Load_GDTR(limitAndBase);