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