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 /* GLOBALS *******************************************************************/
19 typedef struct _KTSSNOIOPM
21 UCHAR TssData
[KTSS_IO_MAPS
];
24 static KTSS
* Ki386TssArray
[MAXIMUM_PROCESSORS
];
25 PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
26 static KTSSNOIOPM
* Ki386TrapTssArray
[MAXIMUM_PROCESSORS
];
27 static PVOID Ki386TrapStackArray
[MAXIMUM_PROCESSORS
];
30 static KTSSNOIOPM KiBootTrapTss
;
32 extern USHORT KiBootGdt
[];
33 extern ULONG init_stack
;
34 extern ULONG init_stack_top
;
35 extern VOID
KiTrap8(VOID
);
37 /* FUNCTIONS *****************************************************************/
40 Ke386IoSetAccessProcess(PEPROCESS Process
, BOOL EnableDisable
)
45 if(EnableDisable
> 1) return FALSE
;
46 Offset
= (EnableDisable
) ? (USHORT
) FIELD_OFFSET(KTSS
, IoMaps
) : 0xffff;
48 oldIrql
= KeRaiseIrqlToSynchLevel();
49 Process
->Pcb
.IopmOffset
= Offset
;
51 if(PsGetCurrentProcess() == Process
)
53 KeGetCurrentKPCR()->TSS
->IoMapBase
= Offset
;
62 Ke386SetIoAccessMap(DWORD MapNumber
, PULONG IOMapStart
)
66 if(MapNumber
!= 1) return FALSE
;
68 oldIrql
= KeRaiseIrqlToSynchLevel();
70 memcpy(&KeGetCurrentKPCR()->TSS
->IoMaps
[0],
74 KeGetCurrentKPCR()->TSS
->IoMapBase
= KeGetCurrentProcess()->IopmOffset
;
80 Ke386QueryIoAccessMap(DWORD MapNumber
, PULONG IOMapStart
)
86 memset(IOMapStart
, 0xff, 0x2000);
88 } else if(MapNumber
!= 1) return FALSE
;
90 oldIrql
= KeRaiseIrqlToSynchLevel();
93 &KeGetCurrentKPCR()->TSS
->IoMaps
[0],
101 Ki386ApplicationProcessorInitializeTSS(VOID
)
111 Id
= KeGetCurrentProcessorNumber();
112 Gdt
= KeGetCurrentKPCR()->GDT
;
114 Ke386GetPageTableDirectory(cr3_
);
116 Tss
= ExAllocatePool(NonPagedPool
, sizeof(KTSS
));
117 TrapTss
= ExAllocatePool(NonPagedPool
, sizeof(KTSSNOIOPM
));
118 TrapStack
= ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
);
120 Ki386TssArray
[Id
] = Tss
;
121 Ki386TrapTssArray
[Id
] = (KTSSNOIOPM
*)TrapTss
;
122 Ki386TrapStackArray
[Id
] = TrapStack
;
123 KeGetCurrentKPCR()->TSS
= Tss
;
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 */
132 * Initialize a descriptor for the TSS
135 length
= sizeof(KTSS
) - 1;
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));
143 /* Initialize the TSS used for handling double faults. */
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 */
156 * Initialize a descriptor for the trap TSS.
158 base
= (ULONG
)TrapTss
;
159 length
= sizeof(KTSSNOIOPM
) - 1;
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));
168 * Load the task register
170 #if defined(__GNUC__)
174 #elif defined(_MSC_VER)
175 __asm mov ax
, KGDT_TSS
178 #error Unknown compiler for inline assembler
183 Ki386BootInitializeTSS(VOID
)
186 extern unsigned int trap_stack
, trap_stack_top
;
187 unsigned int base
, length
;
190 Ke386GetPageTableDirectory(cr3_
);
192 Ki386TssArray
[0] = &KiBootTss
;
193 Ki386TrapTssArray
[0] = &KiBootTrapTss
;
194 Ki386TrapStackArray
[0] = (PVOID
)trap_stack
;
195 Ki386InitialStackArray
[0] = (PVOID
)init_stack
;
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
;
204 * Initialize a descriptor for the TSS
206 base
= (unsigned int)&KiBootTss
;
207 length
= sizeof(KiBootTss
) - 1;
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);
215 /* Initialize the TSS used for handling double faults. */
216 Tss
= (PKTSS
)&KiBootTrapTss
;
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 */
229 * Initialize a descriptor for the trap TSS.
231 base
= (unsigned int)&KiBootTrapTss
;
232 length
= sizeof(KiBootTrapTss
) - 1;
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);
241 * Load the task register
243 #if defined(__GNUC__)
247 #elif defined(_MSC_VER)
248 __asm mov ax
, KGDT_TSS
251 #error Unknown compiler for inline assembler