3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/tss.c
6 * PURPOSE: TSS managment
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, Ki386BootInitializeTSS)
21 /* GLOBALS *******************************************************************/
23 typedef struct _KTSSNOIOPM
25 UCHAR TssData
[KTSS_IO_MAPS
];
28 static KTSS
* Ki386TssArray
[MAXIMUM_PROCESSORS
];
29 PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
30 static KTSSNOIOPM
* Ki386TrapTssArray
[MAXIMUM_PROCESSORS
];
31 static PVOID Ki386TrapStackArray
[MAXIMUM_PROCESSORS
];
34 static KTSSNOIOPM KiBootTrapTss
;
36 extern USHORT KiBootGdt
[];
37 extern ULONG init_stack
;
38 extern ULONG init_stack_top
;
39 extern VOID
KiTrap8(VOID
);
41 /* FUNCTIONS *****************************************************************/
44 Ke386IoSetAccessProcess(PEPROCESS Process
, BOOL EnableDisable
)
49 if(EnableDisable
> 1) return FALSE
;
50 Offset
= (EnableDisable
) ? (USHORT
) FIELD_OFFSET(KTSS
, IoMaps
) : 0xffff;
52 oldIrql
= KeRaiseIrqlToSynchLevel();
53 Process
->Pcb
.IopmOffset
= Offset
;
55 if(PsGetCurrentProcess() == Process
)
57 KeGetCurrentKPCR()->TSS
->IoMapBase
= Offset
;
66 Ke386SetIoAccessMap(DWORD MapNumber
, PULONG IOMapStart
)
70 if(MapNumber
!= 1) return FALSE
;
72 oldIrql
= KeRaiseIrqlToSynchLevel();
74 memcpy(&KeGetCurrentKPCR()->TSS
->IoMaps
[0],
78 KeGetCurrentKPCR()->TSS
->IoMapBase
= KeGetCurrentProcess()->IopmOffset
;
84 Ke386QueryIoAccessMap(DWORD MapNumber
, PULONG IOMapStart
)
90 memset(IOMapStart
, 0xff, 0x2000);
92 } else if(MapNumber
!= 1) return FALSE
;
94 oldIrql
= KeRaiseIrqlToSynchLevel();
97 &KeGetCurrentKPCR()->TSS
->IoMaps
[0],
100 KeLowerIrql(oldIrql
);
105 Ki386ApplicationProcessorInitializeTSS(VOID
)
115 Id
= KeGetCurrentProcessorNumber();
116 Gdt
= KeGetCurrentKPCR()->GDT
;
118 Ke386GetPageTableDirectory(cr3_
);
120 Tss
= ExAllocatePool(NonPagedPool
, sizeof(KTSS
));
121 TrapTss
= ExAllocatePool(NonPagedPool
, sizeof(KTSSNOIOPM
));
122 TrapStack
= ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
);
124 Ki386TssArray
[Id
] = Tss
;
125 Ki386TrapTssArray
[Id
] = (KTSSNOIOPM
*)TrapTss
;
126 Ki386TrapStackArray
[Id
] = TrapStack
;
127 KeGetCurrentKPCR()->TSS
= Tss
;
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 */
136 * Initialize a descriptor for the TSS
139 length
= sizeof(KTSS
) - 1;
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));
147 /* Initialize the TSS used for handling double faults. */
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 */
160 * Initialize a descriptor for the trap TSS.
162 base
= (ULONG
)TrapTss
;
163 length
= sizeof(KTSSNOIOPM
) - 1;
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));
172 * Load the task register
174 #if defined(__GNUC__)
178 #elif defined(_MSC_VER)
179 __asm mov ax
, KGDT_TSS
182 #error Unknown compiler for inline assembler
187 Ki386BootInitializeTSS(VOID
)
190 extern unsigned int trap_stack
, trap_stack_top
;
191 unsigned int base
, length
;
194 Ke386GetPageTableDirectory(cr3_
);
196 Ki386TssArray
[0] = &KiBootTss
;
197 Ki386TrapTssArray
[0] = &KiBootTrapTss
;
198 Ki386TrapStackArray
[0] = (PVOID
)trap_stack
;
199 Ki386InitialStackArray
[0] = (PVOID
)init_stack
;
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
;
208 * Initialize a descriptor for the TSS
210 base
= (unsigned int)&KiBootTss
;
211 length
= sizeof(KiBootTss
) - 1;
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);
219 /* Initialize the TSS used for handling double faults. */
220 Tss
= (PKTSS
)&KiBootTrapTss
;
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 */
233 * Initialize a descriptor for the trap TSS.
235 base
= (unsigned int)&KiBootTrapTss
;
236 length
= sizeof(KiBootTrapTss
) - 1;
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);
245 * Load the task register
247 #if defined(__GNUC__)
251 #elif defined(_MSC_VER)
252 __asm mov ax
, KGDT_TSS
255 #error Unknown compiler for inline assembler