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>
17 #include <geekos/debug.h>
20 * This is defined in lowlevel.asm.
22 extern void Load_GDTR(ushort_t* limitAndBase);
24 /* ----------------------------------------------------------------------
26 * ---------------------------------------------------------------------- */
29 * Number of entries in the kernel GDT.
31 #define NUM_GDT_ENTRIES 16
34 * This is the kernel's global descriptor table.
36 struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES];
38 * Number of allocated GDT entries.
40 static int s_numAllocated = 0;
49 PrintBoth("GDT Contents:\n");
51 for (i=0;i<NUM_GDT_ENTRIES;i++) {
52 if (s_GDT[i].present) {
53 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",
55 (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
56 (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
70 PrintBoth("%d: Not Present\n",i);
76 /* ----------------------------------------------------------------------
78 * ---------------------------------------------------------------------- */
81 * Allocate an descriptor from the GDT.
82 * Returns null if there are none left.
84 struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
86 struct Segment_Descriptor* result = 0;
90 iflag = Begin_Int_Atomic();
92 /* Note; entry 0 is unused (thus never allocated) */
93 for (i = 1; i < NUM_GDT_ENTRIES; ++i) {
94 struct Segment_Descriptor *desc = &s_GDT[ i ];
103 End_Int_Atomic(iflag);
109 * Free a segment descriptor.
111 void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
113 bool iflag = Begin_Int_Atomic();
115 KASSERT(!desc->avail);
117 Init_Null_Segment_Descriptor(desc);
121 End_Int_Atomic(iflag);
125 * Get the index (int the GDT) of given segment descriptor.
127 int Get_Descriptor_Index(struct Segment_Descriptor* desc)
129 return (int) (desc - s_GDT);
133 * Initialize the kernel's GDT.
137 ushort_t limitAndBase[3];
138 ulong_t gdtBaseAddr = (ulong_t) s_GDT;
139 struct Segment_Descriptor* desc;
143 KASSERT(sizeof(struct Segment_Descriptor) == 8);
145 /* Clear out entries. */
146 for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
148 Init_Null_Segment_Descriptor(desc);
152 /* Kernel code segment. */
153 desc = Allocate_Segment_Descriptor();
154 Init_Code_Segment_Descriptor(
156 0, /* base address */
157 0x100000, /* num pages (== 2^20) */
158 0 /* privilege level (0 == kernel) */
160 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
162 /* Kernel data segment. */
163 desc = Allocate_Segment_Descriptor();
164 Init_Data_Segment_Descriptor(
166 0, /* base address */
167 0x100000, /* num pages (== 2^20) */
168 0 /* privilege level (0 == kernel) */
170 KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
172 Print("GDT: Base=0x%.8x, limit=%d\n", (uint_t)gdtBaseAddr, (uint_t)(sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES));
174 /* Activate the kernel GDT. */
175 limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES;
176 limitAndBase[1] = gdtBaseAddr & 0xffff;
177 limitAndBase[2] = gdtBaseAddr >> 16;
178 Load_GDTR(limitAndBase);