update for HEAD-2003091401
[reactos.git] / 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 */