Continue of MSVC-compiling changes....
[reactos.git] / reactos / ntoskrnl / ke / i386 / gdt.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/gdt.c
22 * PURPOSE: GDT managment
23 * PROGRAMMER: David Welch (welch@cwcom.net)
24 * UPDATE HISTORY:
25 * Created 22/05/98
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <internal/ke.h>
32 #include <internal/ps.h>
33 #include <internal/i386/segment.h>
34
35 #define NDEBUG
36 #include <internal/debug.h>
37
38 /* GLOBALS *******************************************************************/
39
40 PUSHORT KiGdtArray[MAXIMUM_PROCESSORS];
41
42 USHORT KiBootGdt[11 * 4] =
43 {
44 0x0, 0x0, 0x0, 0x0, /* Null */
45 0xffff, 0x0, 0x9a00, 0xcf, /* Kernel CS */
46 0xffff, 0x0, 0x9200, 0xcf, /* Kernel DS */
47 0x0, 0x0, 0xfa00, 0xcc, /* User CS */
48 0x0, 0x0, 0xf200, 0xcc, /* User DS */
49 0x0, 0x0, 0x0, 0x0, /* TSS */
50 0x1000, 0x0000, 0x9200, 0xff00, /* PCR */
51 0x1000, 0x0, 0xf200, 0x0, /* TEB */
52 0x0, 0x0, 0x0, 0x0, /* Reserved */
53 0x0, 0x0, 0x0, 0x0, /* LDT */
54 0x0, 0x0, 0x0, 0x0 /* Trap TSS */
55 };
56
57 struct
58 {
59 USHORT Length;
60 ULONG Base;
61 } __attribute__((packed)) KiGdtDescriptor = { 11 * 8, (ULONG)KiBootGdt };
62
63 static KSPIN_LOCK GdtLock;
64
65 /* FUNCTIONS *****************************************************************/
66
67 VOID
68 KiGdtPrepareForApplicationProcessorInit(ULONG Id)
69 {
70 KiGdtArray[Id] = ExAllocatePool(NonPagedPool, sizeof(USHORT) * 4 * 11);
71 }
72
73 VOID
74 KiInitializeGdt(PKPCR Pcr)
75 {
76 PUSHORT Gdt;
77 struct
78 {
79 USHORT Length;
80 ULONG Base;
81 } __attribute__((packed)) Descriptor;
82 ULONG Entry;
83 ULONG Base;
84
85 if (Pcr == NULL)
86 {
87 KiGdtArray[0] = KiBootGdt;
88 return;
89 }
90
91 /*
92 * Allocate a GDT
93 */
94 Gdt = KiGdtArray[Pcr->ProcessorNumber];
95 if (Gdt == NULL)
96 {
97 DbgPrint("No GDT (%d)\n", Pcr->ProcessorNumber);
98 KEBUGCHECK(0);
99 }
100
101 /*
102 * Copy the boot processor's GDT onto this processor's GDT. Note that
103 * the only entries that can change are the PCR, TEB and LDT descriptors.
104 * We will be initializing these later so their current values are
105 * irrelevant.
106 */
107 memcpy(Gdt, KiBootGdt, sizeof(USHORT) * 4 * 11);
108 Pcr->GDT = Gdt;
109
110 /*
111 * Set the base address of the PCR
112 */
113 Base = (ULONG)Pcr;
114 Entry = PCR_SELECTOR / 2;
115 Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);
116
117 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
118 Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] | ((((ULONG)Base) & 0xff0000) >> 16));
119
120 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
121 Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] | ((((ULONG)Base) & 0xff000000) >> 16));
122
123 /*
124 * Load the GDT
125 */
126 Descriptor.Length = 8 * 11;
127 Descriptor.Base = (ULONG)Gdt;
128 #if defined(__GNUC__)
129 __asm__ ("lgdt %0\n\t" : /* no output */ : "m" (Descriptor));
130
131 /*
132 * Reload the selectors
133 */
134 __asm__ ("movl %0, %%ds\n\t"
135 "movl %0, %%es\n\t"
136 "movl %1, %%fs\n\t"
137 "movl %0, %%gs\n\t"
138 : /* no output */
139 : "a" (KERNEL_DS), "b" (PCR_SELECTOR));
140 __asm__ ("pushl %0\n\t"
141 "pushl $.l4\n\t"
142 "lret\n\t"
143 ".l4:\n\t"
144 : /* no output */
145 : "a" (KERNEL_CS));
146 #elif defined(_MSC_VER)
147 __asm
148 {
149 lgdt Descriptor;
150 mov ax, KERNEL_DS;
151 mov bx, PCR_SELECTOR;
152 mov ds, ax;
153 mov es, ax;
154 mov fs, bx;
155 mov gs, ax;
156 push KERNEL_CS;
157 push offset l4 ; // what the heck...
158 ret
159 l4:
160 }
161 #else
162 #error Unknown compiler for inline assembler
163 #endif
164 }
165
166 VOID
167 KeSetBaseGdtSelector(ULONG Entry,
168 PVOID Base)
169 {
170 KIRQL oldIrql;
171 PUSHORT Gdt = KeGetCurrentKPCR()->GDT;
172
173 DPRINT("KeSetBaseGdtSelector(Entry %x, Base %x)\n",
174 Entry, Base);
175
176 KeAcquireSpinLock(&GdtLock, &oldIrql);
177
178 Entry = (Entry & (~0x3)) / 2;
179
180 Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);
181
182 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
183 Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] |
184 ((((ULONG)Base) & 0xff0000) >> 16));
185
186 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
187 Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] |
188 ((((ULONG)Base) & 0xff000000) >> 16));
189
190 DPRINT("%x %x %x %x\n",
191 Gdt[Entry + 0],
192 Gdt[Entry + 1],
193 Gdt[Entry + 2],
194 Gdt[Entry + 3]);
195
196 KeReleaseSpinLock(&GdtLock, oldIrql);
197 }
198
199 VOID
200 KeSetGdtSelector(ULONG Entry,
201 ULONG Value1,
202 ULONG Value2)
203 {
204 KIRQL oldIrql;
205 PULONG Gdt = (PULONG) KeGetCurrentKPCR()->GDT;
206
207 DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n",
208 Entry, Value1, Value2);
209
210 KeAcquireSpinLock(&GdtLock, &oldIrql);
211
212 Entry = (Entry & (~0x3)) / 4;
213
214 Gdt[Entry] = Value1;
215 Gdt[Entry + 1] = Value2;
216
217 DPRINT("%x %x\n",
218 Gdt[Entry + 0],
219 Gdt[Entry + 1]);
220
221 KeReleaseSpinLock(&GdtLock, oldIrql);
222 }
223
224 VOID
225 KeDumpGdtSelector(ULONG Entry)
226 {
227 USHORT a, b, c, d;
228 ULONG RawLimit;
229
230 a = KiBootGdt[Entry*4];
231 b = KiBootGdt[Entry*4 + 1];
232 c = KiBootGdt[Entry*4 + 2];
233 d = KiBootGdt[Entry*4 + 3];
234
235 DbgPrint("Base: %x\n", b + ((c & 0xff) * (1 << 16)) +
236 ((d & 0xff00) * (1 << 16)));
237 RawLimit = a + ((d & 0xf) * (1 << 16));
238 if (d & 0x80)
239 {
240 DbgPrint("Limit: %x\n", RawLimit * 4096);
241 }
242 else
243 {
244 DbgPrint("Limit: %x\n", RawLimit);
245 }
246 DbgPrint("Accessed: %d\n", (c & 0x100) >> 8);
247 DbgPrint("Type: %x\n", (c & 0xe00) >> 9);
248 DbgPrint("System: %d\n", (c & 0x1000) >> 12);
249 DbgPrint("DPL: %d\n", (c & 0x6000) >> 13);
250 DbgPrint("Present: %d\n", (c & 0x8000) >> 15);
251 DbgPrint("AVL: %x\n", (d & 0x10) >> 4);
252 DbgPrint("D: %d\n", (d & 0x40) >> 6);
253 DbgPrint("G: %d\n", (d & 0x80) >> 7);
254 }
255
256 /* EOF */