- Implement RtlPrefectMemoryNonTemporal. Patch by Patrick Baggett <baggett.patrick...
[reactos.git] / reactos / ntoskrnl / ke / i386 / tss.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/tss.c
6 * PURPOSE: TSS 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 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, Ki386BootInitializeTSS)
19 #endif
20
21 /* GLOBALS *******************************************************************/
22
23 typedef struct _KTSSNOIOPM
24 {
25 UCHAR TssData[KTSS_IO_MAPS];
26 } KTSSNOIOPM;
27
28 static KTSS* Ki386TssArray[MAXIMUM_PROCESSORS];
29 PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
30 static KTSSNOIOPM* Ki386TrapTssArray[MAXIMUM_PROCESSORS];
31 static PVOID Ki386TrapStackArray[MAXIMUM_PROCESSORS];
32
33 KTSS KiBootTss;
34 static KTSSNOIOPM KiBootTrapTss;
35
36 extern USHORT KiBootGdt[];
37 extern ULONG init_stack;
38 extern ULONG init_stack_top;
39 extern VOID KiTrap8(VOID);
40
41 /* FUNCTIONS *****************************************************************/
42
43 BOOL STDCALL
44 Ke386IoSetAccessProcess(PEPROCESS Process, BOOL EnableDisable)
45 {
46 KIRQL oldIrql;
47 USHORT Offset;
48
49 if(EnableDisable > 1) return FALSE;
50 Offset = (EnableDisable) ? (USHORT) FIELD_OFFSET(KTSS, IoMaps) : 0xffff;
51
52 oldIrql = KeRaiseIrqlToSynchLevel();
53 Process->Pcb.IopmOffset = Offset;
54
55 if(PsGetCurrentProcess() == Process)
56 {
57 KeGetCurrentKPCR()->TSS->IoMapBase = Offset;
58 }
59
60 KeLowerIrql(oldIrql);
61 return TRUE;
62 }
63
64
65 BOOL STDCALL
66 Ke386SetIoAccessMap(DWORD MapNumber, PULONG IOMapStart)
67 {
68 KIRQL oldIrql;
69
70 if(MapNumber != 1) return FALSE;
71
72 oldIrql = KeRaiseIrqlToSynchLevel();
73
74 memcpy(&KeGetCurrentKPCR()->TSS->IoMaps[0],
75 IOMapStart,
76 0x2000);
77
78 KeGetCurrentKPCR()->TSS->IoMapBase = KeGetCurrentProcess()->IopmOffset;
79 KeLowerIrql(oldIrql);
80 return TRUE;
81 }
82
83 BOOL STDCALL
84 Ke386QueryIoAccessMap(DWORD MapNumber, PULONG IOMapStart)
85 {
86 KIRQL oldIrql;
87
88 if(MapNumber == 0x0)
89 {
90 memset(IOMapStart, 0xff, 0x2000);
91 return TRUE;
92 } else if(MapNumber != 1) return FALSE;
93
94 oldIrql = KeRaiseIrqlToSynchLevel();
95
96 memcpy(IOMapStart,
97 &KeGetCurrentKPCR()->TSS->IoMaps[0],
98 0x2000);
99
100 KeLowerIrql(oldIrql);
101 return TRUE;
102 }
103
104 VOID
105 Ki386ApplicationProcessorInitializeTSS(VOID)
106 {
107 ULONG cr3_;
108 PKTSS Tss;
109 PKTSS TrapTss;
110 PVOID TrapStack;
111 ULONG Id;
112 PUSHORT Gdt;
113 ULONG base, length;
114
115 Id = KeGetCurrentProcessorNumber();
116 Gdt = KeGetCurrentKPCR()->GDT;
117
118 Ke386GetPageTableDirectory(cr3_);
119
120 Tss = ExAllocatePool(NonPagedPool, sizeof(KTSS));
121 TrapTss = ExAllocatePool(NonPagedPool, sizeof(KTSSNOIOPM));
122 TrapStack = ExAllocatePool(NonPagedPool, MM_STACK_SIZE);
123
124 Ki386TssArray[Id] = Tss;
125 Ki386TrapTssArray[Id] = (KTSSNOIOPM*)TrapTss;
126 Ki386TrapStackArray[Id] = TrapStack;
127 KeGetCurrentKPCR()->TSS = Tss;
128
129 /* Initialize the boot TSS. */
130 Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id] + MM_STACK_SIZE; /* FIXME: - sizeof(FX_SAVE_AREA)? */
131 Tss->Ss0 = KGDT_R0_DATA;
132 Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */
133 Tss->LDT = 0;
134
135 /*
136 * Initialize a descriptor for the TSS
137 */
138 base = (ULONG)Tss;
139 length = sizeof(KTSS) - 1;
140
141 Gdt[(KGDT_TSS / 2) + 0] = (USHORT)(length & 0xFFFF);
142 Gdt[(KGDT_TSS / 2) + 1] = (USHORT)(base & 0xFFFF);
143 Gdt[(KGDT_TSS / 2) + 2] = (USHORT)(((base & 0xFF0000) >> 16) | 0x8900);
144 Gdt[(KGDT_TSS / 2) + 3] = (USHORT)(((length & 0xF0000) >> 16) |
145 ((base & 0xFF000000) >> 16));
146
147 /* Initialize the TSS used for handling double faults. */
148 TrapTss->Flags = 0;
149 TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE); /* FIXME: - sizeof(FX_SAVE_AREA)? */
150 TrapTss->Ss0 = KGDT_R0_DATA;
151 TrapTss->Cs = KGDT_R0_CODE;
152 TrapTss->Eip = (ULONG)KiTrap8;
153 TrapTss->Ds = KGDT_R0_DATA;
154 TrapTss->Es = KGDT_R0_DATA;
155 TrapTss->Fs = KGDT_R0_PCR;
156 TrapTss->IoMapBase = 0xFFFF; /* No i/o bitmap */
157 TrapTss->LDT = 0;
158
159 /*
160 * Initialize a descriptor for the trap TSS.
161 */
162 base = (ULONG)TrapTss;
163 length = sizeof(KTSSNOIOPM) - 1;
164
165 Gdt[(KGDT_DF_TSS / 2) + 0] = (USHORT)(length & 0xFFFF);
166 Gdt[(KGDT_DF_TSS / 2) + 1] = (USHORT)(base & 0xFFFF);
167 Gdt[(KGDT_DF_TSS / 2) + 2] = (USHORT)(((base & 0xFF0000) >> 16) | 0x8900);
168 Gdt[(KGDT_DF_TSS / 2) + 3] = (USHORT)(((length & 0xF0000) >> 16) |
169 ((base & 0xFF000000) >> 16));
170
171 /*
172 * Load the task register
173 */
174 #if defined(__GNUC__)
175 __asm__("ltr %%ax"
176 : /* no output */
177 : "a" (KGDT_TSS));
178 #elif defined(_MSC_VER)
179 __asm mov ax, KGDT_TSS
180 __asm ltr ax
181 #else
182 #error Unknown compiler for inline assembler
183 #endif
184 }
185
186 VOID INIT_FUNCTION
187 Ki386BootInitializeTSS(VOID)
188 {
189 ULONG cr3_;
190 extern unsigned int trap_stack, trap_stack_top;
191 unsigned int base, length;
192 PKTSS Tss;
193
194 Ke386GetPageTableDirectory(cr3_);
195
196 Ki386TssArray[0] = &KiBootTss;
197 Ki386TrapTssArray[0] = &KiBootTrapTss;
198 Ki386TrapStackArray[0] = (PVOID)trap_stack;
199 Ki386InitialStackArray[0] = (PVOID)init_stack;
200
201 /* Initialize the boot TSS. */
202 KiBootTss.Esp0 = (ULONG)init_stack_top - sizeof(FX_SAVE_AREA);
203 KiBootTss.Ss0 = KGDT_R0_DATA;
204 KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */
205 KiBootTss.LDT = KGDT_LDT;
206
207 /*
208 * Initialize a descriptor for the TSS
209 */
210 base = (unsigned int)&KiBootTss;
211 length = sizeof(KiBootTss) - 1;
212
213 KiBootGdt[(KGDT_TSS / 2) + 0] = (length & 0xFFFF);
214 KiBootGdt[(KGDT_TSS / 2) + 1] = (base & 0xFFFF);
215 KiBootGdt[(KGDT_TSS / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900;
216 KiBootGdt[(KGDT_TSS / 2) + 3] = ((length & 0xF0000) >> 16) |
217 ((base & 0xFF000000) >> 16);
218
219 /* Initialize the TSS used for handling double faults. */
220 Tss = (PKTSS)&KiBootTrapTss;
221 Tss->Flags = 0;
222 Tss->Esp0 = (ULONG)trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */
223 Tss->Ss0 = KGDT_R0_DATA;
224 Tss->Cs = KGDT_R0_CODE;
225 Tss->Eip = (ULONG)KiTrap8;
226 Tss->Ds = KGDT_R0_DATA;
227 Tss->Es = KGDT_R0_DATA;
228 Tss->Fs = KGDT_R0_PCR;
229 Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */
230 Tss->LDT = 0x0;
231
232 /*
233 * Initialize a descriptor for the trap TSS.
234 */
235 base = (unsigned int)&KiBootTrapTss;
236 length = sizeof(KiBootTrapTss) - 1;
237
238 KiBootGdt[(KGDT_DF_TSS / 2) + 0] = (length & 0xFFFF);
239 KiBootGdt[(KGDT_DF_TSS / 2) + 1] = (base & 0xFFFF);
240 KiBootGdt[(KGDT_DF_TSS / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900;
241 KiBootGdt[(KGDT_DF_TSS / 2) + 3] = ((length & 0xF0000) >> 16) |
242 ((base & 0xFF000000) >> 16);
243
244 /*
245 * Load the task register
246 */
247 #if defined(__GNUC__)
248 __asm__("ltr %%ax"
249 : /* no output */
250 : "a" (KGDT_TSS));
251 #elif defined(_MSC_VER)
252 __asm mov ax, KGDT_TSS
253 __asm ltr ax
254 #else
255 #error Unknown compiler for inline assembler
256 #endif
257 }
258
259
260
261
262