5a1ede95aa944d946091c3238365757378bfc934
[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] = ((ULONG)Base) & 0xffff;
116
117 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
118 Gdt[Entry + 2] = Gdt[Entry + 2] | ((((ULONG)Base) & 0xff0000) >> 16);
119
120 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
121 Gdt[Entry + 3] = 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 __asm__ ("lgdt %0\n\t" : /* no output */ : "m" (Descriptor));
129
130 /*
131 * Reload the selectors
132 */
133 __asm__ ("movl %0, %%ds\n\t"
134 "movl %0, %%es\n\t"
135 "movl %1, %%fs\n\t"
136 "movl %0, %%gs\n\t"
137 : /* no output */
138 : "a" (KERNEL_DS), "b" (PCR_SELECTOR));
139 __asm__ ("pushl %0\n\t"
140 "pushl $.l4\n\t"
141 "lret\n\t"
142 ".l4:\n\t"
143 : /* no output */
144 : "a" (KERNEL_CS));
145 }
146
147 VOID
148 KeSetBaseGdtSelector(ULONG Entry,
149 PVOID Base)
150 {
151 KIRQL oldIrql;
152 PUSHORT Gdt = KeGetCurrentKPCR()->GDT;
153
154 DPRINT("KeSetBaseGdtSelector(Entry %x, Base %x)\n",
155 Entry, Base);
156
157 KeAcquireSpinLock(&GdtLock, &oldIrql);
158
159 Entry = (Entry & (~0x3)) / 2;
160
161 Gdt[Entry + 1] = ((ULONG)Base) & 0xffff;
162
163 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
164 Gdt[Entry + 2] = Gdt[Entry + 2] |
165 ((((ULONG)Base) & 0xff0000) >> 16);
166
167 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
168 Gdt[Entry + 3] = Gdt[Entry + 3] |
169 ((((ULONG)Base) & 0xff000000) >> 16);
170
171 DPRINT("%x %x %x %x\n",
172 Gdt[Entry + 0],
173 Gdt[Entry + 1],
174 Gdt[Entry + 2],
175 Gdt[Entry + 3]);
176
177 KeReleaseSpinLock(&GdtLock, oldIrql);
178 }
179
180 VOID
181 KeSetGdtSelector(ULONG Entry,
182 ULONG Value1,
183 ULONG Value2)
184 {
185 KIRQL oldIrql;
186 PULONG Gdt = (PULONG) KeGetCurrentKPCR()->GDT;
187
188 DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n",
189 Entry, Value1, Value2);
190
191 KeAcquireSpinLock(&GdtLock, &oldIrql);
192
193 Entry = (Entry & (~0x3)) / 4;
194
195 Gdt[Entry] = Value1;
196 Gdt[Entry + 1] = Value2;
197
198 DPRINT("%x %x\n",
199 Gdt[Entry + 0],
200 Gdt[Entry + 1]);
201
202 KeReleaseSpinLock(&GdtLock, oldIrql);
203 }
204
205 VOID
206 KeDumpGdtSelector(ULONG Entry)
207 {
208 USHORT a, b, c, d;
209 ULONG RawLimit;
210
211 a = KiBootGdt[Entry*4];
212 b = KiBootGdt[Entry*4 + 1];
213 c = KiBootGdt[Entry*4 + 2];
214 d = KiBootGdt[Entry*4 + 3];
215
216 DbgPrint("Base: %x\n", b + ((c & 0xff) * (1 << 16)) +
217 ((d & 0xff00) * (1 << 16)));
218 RawLimit = a + ((d & 0xf) * (1 << 16));
219 if (d & 0x80)
220 {
221 DbgPrint("Limit: %x\n", RawLimit * 4096);
222 }
223 else
224 {
225 DbgPrint("Limit: %x\n", RawLimit);
226 }
227 DbgPrint("Accessed: %d\n", (c & 0x100) >> 8);
228 DbgPrint("Type: %x\n", (c & 0xe00) >> 9);
229 DbgPrint("System: %d\n", (c & 0x1000) >> 12);
230 DbgPrint("DPL: %d\n", (c & 0x6000) >> 13);
231 DbgPrint("Present: %d\n", (c & 0x8000) >> 15);
232 DbgPrint("AVL: %x\n", (d & 0x10) >> 4);
233 DbgPrint("D: %d\n", (d & 0x40) >> 6);
234 DbgPrint("G: %d\n", (d & 0x80) >> 7);
235 }
236
237 /* EOF */