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
1 /*
2  * Initialize kernel GDT.
3  * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
4  * $Revision: 1.4 $
5  * 
6  * This is free software.  You are permitted to use,
7  * redistribute, and modify it as specified in the file "COPYING".
8  */
9
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>
16
17 #include <geekos/debug.h>
18
19 /*
20  * This is defined in lowlevel.asm.
21  */
22 extern void Load_GDTR(ushort_t* limitAndBase);
23
24 /* ----------------------------------------------------------------------
25  * Data
26  * ---------------------------------------------------------------------- */
27
28 /*
29  * Number of entries in the kernel GDT.
30  */
31 #define NUM_GDT_ENTRIES 16
32
33 /*
34  * This is the kernel's global descriptor table.
35  */
36 struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES];
37 /*
38  * Number of allocated GDT entries.
39  */
40 static int s_numAllocated = 0;
41
42
43
44
45
46 void DumpGDT()
47 {
48   int i;
49   PrintBoth("GDT Contents:\n");
50
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", 
54             i,
55             (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
56             (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
57             s_GDT[i].sizeLow,
58             s_GDT[i].baseLow,
59             s_GDT[i].type,
60             s_GDT[i].system,
61             s_GDT[i].dpl,
62             s_GDT[i].present,
63             s_GDT[i].sizeHigh,
64             s_GDT[i].avail,
65             s_GDT[i].reserved,
66             s_GDT[i].dbBit,
67             s_GDT[i].granularity,
68             s_GDT[i].baseHigh  );
69     } else {
70       PrintBoth("%d: Not Present\n",i);
71     }
72   }
73 }
74
75
76 /* ----------------------------------------------------------------------
77  * Functions
78  * ---------------------------------------------------------------------- */
79
80 /*
81  * Allocate an descriptor from the GDT.
82  * Returns null if there are none left.
83  */
84 struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
85 {
86     struct Segment_Descriptor* result = 0;
87     int i;
88     bool iflag;
89
90     iflag = Begin_Int_Atomic();
91
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 ];
95         if (desc->avail) {
96             ++s_numAllocated;
97             desc->avail = 0;
98             result = desc;
99             break;
100         }
101     }
102
103     End_Int_Atomic(iflag);
104
105     return result;
106 }
107
108 /*
109  * Free a segment descriptor.
110  */
111 void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
112 {
113     bool iflag = Begin_Int_Atomic();
114
115     KASSERT(!desc->avail);
116
117     Init_Null_Segment_Descriptor(desc);
118     desc->avail = 1;
119     --s_numAllocated;
120
121     End_Int_Atomic(iflag);
122 }
123
124 /*
125  * Get the index (int the GDT) of given segment descriptor.
126  */
127 int Get_Descriptor_Index(struct Segment_Descriptor* desc)
128 {
129     return (int) (desc - s_GDT);
130 }
131
132 /*
133  * Initialize the kernel's GDT.
134  */
135 void Init_GDT(void)
136 {
137     ushort_t limitAndBase[3];
138     ulong_t gdtBaseAddr = (ulong_t) s_GDT;
139     struct Segment_Descriptor* desc;
140     int i;
141
142
143     KASSERT(sizeof(struct Segment_Descriptor) == 8);
144
145     /* Clear out entries. */
146     for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
147         desc = &s_GDT[ i ];
148         Init_Null_Segment_Descriptor(desc);
149         desc->avail = 1;
150     }
151
152     /* Kernel code segment. */
153     desc = Allocate_Segment_Descriptor();
154     Init_Code_Segment_Descriptor(
155         desc,
156         0,               /* base address */
157         0x100000,        /* num pages (== 2^20) */
158         0                /* privilege level (0 == kernel) */
159     );
160     KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
161
162     /* Kernel data segment. */
163     desc = Allocate_Segment_Descriptor();
164     Init_Data_Segment_Descriptor(
165         desc,
166         0,               /* base address */
167         0x100000,        /* num pages (== 2^20) */
168         0                /* privilege level (0 == kernel) */
169     );
170     KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
171
172     Print("GDT: Base=0x%.8x, limit=%d\n", (uint_t)gdtBaseAddr,  (uint_t)(sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES));
173
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);
179 }