SM - Sorry, I forgot silence dbg messages!
[reactos.git] / reactos / ntoskrnl / ke / i386 / gdt.c
1 /* $Id:$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/gdt.c
6 * PURPOSE: GDT managment
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 PUSHORT KiGdtArray[MAXIMUM_PROCESSORS];
20
21 USHORT KiBootGdt[11 * 4] =
22 {
23 0x0, 0x0, 0x0, 0x0, /* Null */
24 0xffff, 0x0, 0x9a00, 0xcf, /* Kernel CS */
25 0xffff, 0x0, 0x9200, 0xcf, /* Kernel DS */
26 0xffff, 0x0, 0xfa00, 0xcf, /* User CS */
27 0xffff, 0x0, 0xf200, 0xcf, /* User DS */
28 0x0, 0x0, 0x0, 0x0, /* TSS */
29 0x0fff, 0x0000, 0x9200, 0xff00, /* PCR */
30 0x0fff, 0x0, 0xf200, 0x0, /* TEB */
31 0x0, 0x0, 0x0, 0x0, /* Reserved */
32 0x0, 0x0, 0x0, 0x0, /* LDT */
33 0x0, 0x0, 0x0, 0x0 /* Trap TSS */
34 };
35
36
37 #include <pshpack1.h>
38
39 struct LocalGdtDescriptor_t
40 {
41 USHORT Length;
42 ULONG Base;
43 } KiGdtDescriptor = { 11 * 8, (ULONG)KiBootGdt };
44
45 #include <poppack.h>
46
47
48 static KSPIN_LOCK GdtLock;
49
50 /* FUNCTIONS *****************************************************************/
51
52 VOID
53 KiGdtPrepareForApplicationProcessorInit(ULONG Id)
54 {
55 KiGdtArray[Id] = ExAllocatePool(NonPagedPool, sizeof(USHORT) * 4 * 11);
56 }
57
58 VOID
59 KiInitializeGdt(PKPCR Pcr)
60 {
61 PUSHORT Gdt;
62 struct LocalGdtDescriptor_t Descriptor;
63 ULONG Entry;
64 ULONG Base;
65
66 if (Pcr == NULL)
67 {
68 KiGdtArray[0] = KiBootGdt;
69 return;
70 }
71
72 /*
73 * Allocate a GDT
74 */
75 Gdt = KiGdtArray[Pcr->ProcessorNumber];
76 if (Gdt == NULL)
77 {
78 DbgPrint("No GDT (%d)\n", Pcr->ProcessorNumber);
79 KEBUGCHECK(0);
80 }
81
82 /*
83 * Copy the boot processor's GDT onto this processor's GDT. Note that
84 * the only entries that can change are the PCR, TEB and LDT descriptors.
85 * We will be initializing these later so their current values are
86 * irrelevant.
87 */
88 memcpy(Gdt, KiBootGdt, sizeof(USHORT) * 4 * 11);
89 Pcr->GDT = Gdt;
90
91 /*
92 * Set the base address of the PCR
93 */
94 Base = (ULONG)Pcr;
95 Entry = PCR_SELECTOR / 2;
96 Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);
97
98 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
99 Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] | ((((ULONG)Base) & 0xff0000) >> 16));
100
101 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
102 Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] | ((((ULONG)Base) & 0xff000000) >> 16));
103
104 /*
105 * Load the GDT
106 */
107 Descriptor.Length = 8 * 11;
108 Descriptor.Base = (ULONG)Gdt;
109 #if defined(__GNUC__)
110 __asm__ ("lgdt %0\n\t" : /* no output */ : "m" (Descriptor));
111
112 /*
113 * Reload the selectors
114 */
115 __asm__ ("movl %0, %%ds\n\t"
116 "movl %0, %%es\n\t"
117 "movl %1, %%fs\n\t"
118 "movl %0, %%gs\n\t"
119 : /* no output */
120 : "a" (KERNEL_DS), "d" (PCR_SELECTOR));
121 __asm__ ("pushl %0\n\t"
122 "pushl $.l4\n\t"
123 "lret\n\t"
124 ".l4:\n\t"
125 : /* no output */
126 : "a" (KERNEL_CS));
127 #elif defined(_MSC_VER)
128 __asm
129 {
130 lgdt Descriptor;
131 mov ax, KERNEL_DS;
132 mov dx, PCR_SELECTOR;
133 mov ds, ax;
134 mov es, ax;
135 mov fs, dx;
136 mov gs, ax;
137 push KERNEL_CS;
138 push offset l4 ;
139 retf
140 l4:
141 }
142 #else
143 #error Unknown compiler for inline assembler
144 #endif
145 }
146
147
148 /*
149 * @unimplemented
150 */
151 NTSTATUS
152 KeI386FlatToGdtSelector(
153 IN ULONG Base,
154 IN USHORT Length,
155 IN USHORT Selector
156 )
157 {
158 UNIMPLEMENTED;
159 return 0;
160 }
161
162 /*
163 * @unimplemented
164 */
165 NTSTATUS
166 KeI386ReleaseGdtSelectors(
167 OUT PULONG SelArray,
168 IN ULONG NumOfSelectors
169 )
170 {
171 UNIMPLEMENTED;
172 return 0;
173 }
174
175 /*
176 * @unimplemented
177 */
178 NTSTATUS
179 KeI386AllocateGdtSelectors(
180 OUT PULONG SelArray,
181 IN ULONG NumOfSelectors
182 )
183 {
184 UNIMPLEMENTED;
185 return 0;
186 }
187
188 VOID
189 KeSetBaseGdtSelector(ULONG Entry,
190 PVOID Base)
191 {
192 KIRQL oldIrql;
193 PUSHORT Gdt;
194
195 DPRINT("KeSetBaseGdtSelector(Entry %x, Base %x)\n",
196 Entry, Base);
197
198 KeAcquireSpinLock(&GdtLock, &oldIrql);
199
200 Gdt = KeGetCurrentKPCR()->GDT;
201 Entry = (Entry & (~0x3)) / 2;
202
203 Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);
204
205 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
206 Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] |
207 ((((ULONG)Base) & 0xff0000) >> 16));
208
209 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
210 Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] |
211 ((((ULONG)Base) & 0xff000000) >> 16));
212
213 DPRINT("%x %x %x %x\n",
214 Gdt[Entry + 0],
215 Gdt[Entry + 1],
216 Gdt[Entry + 2],
217 Gdt[Entry + 3]);
218
219 KeReleaseSpinLock(&GdtLock, oldIrql);
220 }
221
222 VOID
223 KeSetGdtSelector(ULONG Entry,
224 ULONG Value1,
225 ULONG Value2)
226 {
227 KIRQL oldIrql;
228 PULONG Gdt;
229
230 DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n",
231 Entry, Value1, Value2);
232
233 KeAcquireSpinLock(&GdtLock, &oldIrql);
234
235 Gdt = (PULONG) KeGetCurrentKPCR()->GDT;;
236 Entry = (Entry & (~0x3)) / 4;
237
238 Gdt[Entry] = Value1;
239 Gdt[Entry + 1] = Value2;
240
241 DPRINT("%x %x\n",
242 Gdt[Entry + 0],
243 Gdt[Entry + 1]);
244
245 KeReleaseSpinLock(&GdtLock, oldIrql);
246 }
247
248 VOID
249 KeDumpGdtSelector(ULONG Entry)
250 {
251 USHORT a, b, c, d;
252 ULONG RawLimit;
253
254 a = KiBootGdt[Entry*4];
255 b = KiBootGdt[Entry*4 + 1];
256 c = KiBootGdt[Entry*4 + 2];
257 d = KiBootGdt[Entry*4 + 3];
258
259 DbgPrint("Base: %x\n", b + ((c & 0xff) * (1 << 16)) +
260 ((d & 0xff00) * (1 << 16)));
261 RawLimit = a + ((d & 0xf) * (1 << 16));
262 if (d & 0x80)
263 {
264 DbgPrint("Limit: %x\n", RawLimit * 4096);
265 }
266 else
267 {
268 DbgPrint("Limit: %x\n", RawLimit);
269 }
270 DbgPrint("Accessed: %d\n", (c & 0x100) >> 8);
271 DbgPrint("Type: %x\n", (c & 0xe00) >> 9);
272 DbgPrint("System: %d\n", (c & 0x1000) >> 12);
273 DbgPrint("DPL: %d\n", (c & 0x6000) >> 13);
274 DbgPrint("Present: %d\n", (c & 0x8000) >> 15);
275 DbgPrint("AVL: %x\n", (d & 0x10) >> 4);
276 DbgPrint("D: %d\n", (d & 0x40) >> 6);
277 DbgPrint("G: %d\n", (d & 0x80) >> 7);
278 }
279
280 /* EOF */