d2cb14256d4484e9a768311ed36610e4155167ac
[reactos.git] / reactos / ntoskrnl / include / internal / i386 / ke.h
1 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H
2 #define __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H
3
4 #ifndef __ASM__
5
6 #include "intrin_i.h"
7 #include "v86m.h"
8
9 extern ULONG Ke386CacheAlignment;
10
11 //
12 // Thread Dispatcher Header DebugActive Mask
13 //
14 #define DR_MASK(x) (1 << (x))
15 #define DR_REG_MASK 0x4F
16
17 #define IMAGE_FILE_MACHINE_ARCHITECTURE IMAGE_FILE_MACHINE_I386
18
19 //
20 // INT3 is 1 byte long
21 //
22 #define KD_BREAKPOINT_TYPE UCHAR
23 #define KD_BREAKPOINT_SIZE sizeof(UCHAR)
24 #define KD_BREAKPOINT_VALUE 0xCC
25
26 //
27 // Macros for getting and setting special purpose registers in portable code
28 //
29 #define KeGetContextPc(Context) \
30 ((Context)->Eip)
31
32 #define KeSetContextPc(Context, ProgramCounter) \
33 ((Context)->Eip = (ProgramCounter))
34
35 #define KeGetTrapFramePc(TrapFrame) \
36 ((TrapFrame)->Eip)
37
38 #define KeGetContextReturnRegister(Context) \
39 ((Context)->Eax)
40
41 #define KeSetContextReturnRegister(Context, ReturnValue) \
42 ((Context)->Eax = (ReturnValue))
43
44 //
45 // Macro to get trap and exception frame from a thread stack
46 //
47 #define KeGetTrapFrame(Thread) \
48 (PKTRAP_FRAME)((ULONG_PTR)((Thread)->InitialStack) - \
49 sizeof(KTRAP_FRAME) - \
50 sizeof(FX_SAVE_AREA))
51
52 #define KeGetExceptionFrame(Thread) \
53 NULL
54
55 //
56 // Macro to get context switches from the PRCB
57 // All architectures but x86 have it in the PRCB's KeContextSwitches
58 //
59 #define KeGetContextSwitches(Prcb) \
60 CONTAINING_RECORD(Prcb, KIPCR, PrcbData)->ContextSwitches
61
62 //
63 // Returns the Interrupt State from a Trap Frame.
64 // ON = TRUE, OFF = FALSE
65 //
66 #define KeGetTrapFrameInterruptState(TrapFrame) \
67 BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
68
69 //
70 // Flags for exiting a trap
71 //
72 #define KTE_SKIP_PM_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipPreviousMode = TRUE } }).Bits)
73 #define KTE_SKIP_SEG_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipSegments = TRUE } }).Bits)
74 #define KTE_SKIP_VOL_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipVolatiles = TRUE } }).Bits)
75
76 typedef union _KTRAP_EXIT_SKIP_BITS
77 {
78 struct
79 {
80 UCHAR SkipPreviousMode:1;
81 UCHAR SkipSegments:1;
82 UCHAR SkipVolatiles:1;
83 UCHAR Reserved:5;
84 };
85 UCHAR Bits;
86 } KTRAP_EXIT_SKIP_BITS, *PKTRAP_EXIT_SKIP_BITS;
87
88 //
89 // Registers an interrupt handler with an IDT vector
90 //
91 FORCEINLINE
92 VOID
93 KeRegisterInterruptHandler(IN ULONG Vector,
94 IN PVOID Handler)
95 {
96 UCHAR Entry;
97 ULONG_PTR Address;
98 PKIPCR Pcr = (PKIPCR)KeGetPcr();
99
100 //
101 // Get the entry from the HAL
102 //
103 Entry = HalVectorToIDTEntry(Vector);
104 Address = PtrToUlong(Handler);
105
106 //
107 // Now set the data
108 //
109 Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16);
110 Pcr->IDT[Entry].Offset = (USHORT)Address;
111 }
112
113 //
114 // Returns the registered interrupt handler for a given IDT vector
115 //
116 FORCEINLINE
117 PVOID
118 KeQueryInterruptHandler(IN ULONG Vector)
119 {
120 PKIPCR Pcr = (PKIPCR)KeGetPcr();
121 UCHAR Entry;
122
123 //
124 // Get the entry from the HAL
125 //
126 Entry = HalVectorToIDTEntry(Vector);
127
128 //
129 // Read the entry from the IDT
130 //
131 return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) |
132 (Pcr->IDT[Entry].Offset & 0xFFFF));
133 }
134
135 //
136 // Invalidates the TLB entry for a specified address
137 //
138 FORCEINLINE
139 VOID
140 KeInvalidateTlbEntry(IN PVOID Address)
141 {
142 /* Invalidate the TLB entry for this address */
143 __invlpg(Address);
144 }
145
146 FORCEINLINE
147 VOID
148 KeFlushProcessTb(VOID)
149 {
150 /* Flush the TLB by resetting CR3 */
151 __writecr3(__readcr3());
152 }
153
154 FORCEINLINE
155 PRKTHREAD
156 KeGetCurrentThread(VOID)
157 {
158 /* Return the current thread */
159 return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
160 }
161
162 FORCEINLINE
163 VOID
164 KiRundownThread(IN PKTHREAD Thread)
165 {
166 #ifndef CONFIG_SMP
167 /* Check if this is the NPX Thread */
168 if (KeGetCurrentPrcb()->NpxThread == Thread)
169 {
170 /* Clear it */
171 KeGetCurrentPrcb()->NpxThread = NULL;
172 Ke386FnInit();
173 }
174 #else
175 /* Nothing to do */
176 #endif
177 }
178
179 VOID
180 FASTCALL
181 Ki386InitializeTss(
182 IN PKTSS Tss,
183 IN PKIDTENTRY Idt,
184 IN PKGDTENTRY Gdt
185 );
186
187 VOID
188 NTAPI
189 KiSetCR0Bits(VOID);
190
191 VOID
192 NTAPI
193 KiGetCacheInformation(VOID);
194
195 BOOLEAN
196 NTAPI
197 KiIsNpxPresent(
198 VOID
199 );
200
201 BOOLEAN
202 NTAPI
203 KiIsNpxErrataPresent(
204 VOID
205 );
206
207 VOID
208 NTAPI
209 KiSetProcessorType(VOID);
210
211 ULONG
212 NTAPI
213 KiGetFeatureBits(VOID);
214
215 #ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
216 VOID
217 NTAPI
218 KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
219 PKSTART_ROUTINE StartRoutine,
220 PVOID StartContext,
221 BOOLEAN UserThread,
222 KTRAP_FRAME TrapFrame);
223 #endif
224
225 NTSTATUS
226 NTAPI
227 Ke386GetGdtEntryThread(
228 IN PKTHREAD Thread,
229 IN ULONG Offset,
230 IN PKGDTENTRY Descriptor
231 );
232
233 VOID
234 NTAPI
235 KiFlushNPXState(
236 IN FLOATING_SAVE_AREA *SaveArea
237 );
238
239 VOID
240 NTAPI
241 Ki386AdjustEsp0(
242 IN PKTRAP_FRAME TrapFrame
243 );
244
245 VOID
246 NTAPI
247 Ki386SetupAndExitToV86Mode(
248 OUT PTEB VdmTeb
249 );
250
251 VOID
252 NTAPI
253 KeI386VdmInitialize(
254 VOID
255 );
256
257 ULONG_PTR
258 NTAPI
259 Ki386EnableGlobalPage(
260 IN volatile ULONG_PTR Context
261 );
262
263 VOID
264 NTAPI
265 KiI386PentiumLockErrataFixup(
266 VOID
267 );
268
269 VOID
270 NTAPI
271 KiInitializePAT(
272 VOID
273 );
274
275 VOID
276 NTAPI
277 KiInitializeMTRR(
278 IN BOOLEAN FinalCpu
279 );
280
281 VOID
282 NTAPI
283 KiAmdK6InitializeMTRR(
284 VOID
285 );
286
287 VOID
288 NTAPI
289 KiRestoreFastSyscallReturnState(
290 VOID
291 );
292
293 ULONG_PTR
294 NTAPI
295 Ki386EnableDE(
296 IN ULONG_PTR Context
297 );
298
299 ULONG_PTR
300 NTAPI
301 Ki386EnableFxsr(
302 IN ULONG_PTR Context
303 );
304
305 ULONG_PTR
306 NTAPI
307 Ki386EnableXMMIExceptions(
308 IN ULONG_PTR Context
309 );
310
311 BOOLEAN
312 NTAPI
313 VdmDispatchBop(
314 IN PKTRAP_FRAME TrapFrame
315 );
316
317 BOOLEAN
318 FASTCALL
319 KiVdmOpcodePrefix(
320 IN PKTRAP_FRAME TrapFrame,
321 IN ULONG Flags
322 );
323
324 BOOLEAN
325 FASTCALL
326 Ki386HandleOpcodeV86(
327 IN PKTRAP_FRAME TrapFrame
328 );
329
330 //
331 // Global x86 only Kernel data
332 //
333 extern PVOID Ki386IopmSaveArea;
334 extern ULONG KeI386EFlagsAndMaskV86;
335 extern ULONG KeI386EFlagsOrMaskV86;
336 extern BOOLEAN KeI386VirtualIntExtensions;
337 extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR];
338 extern KDESCRIPTOR KiIdtDescriptor;
339 extern ULONG Ke386GlobalPagesEnabled;
340 extern BOOLEAN KiI386PentiumLockErrataPresent;
341 extern ULONG KeI386NpxPresent;
342 extern ULONG KeI386XMMIPresent;
343 extern ULONG KeI386FxsrPresent;
344 extern ULONG KiMXCsrMask;
345 extern ULONG KeI386CpuType;
346 extern ULONG KeI386CpuStep;
347 extern UCHAR KiDebugRegisterTrapOffsets[9];
348 extern UCHAR KiDebugRegisterContextOffsets[9];
349 extern VOID __cdecl KiTrap2(VOID);
350 extern VOID __cdecl KiTrap8(VOID);
351 extern VOID __cdecl KiTrap19(VOID);
352 extern VOID __cdecl KiFastCallEntry(VOID);
353 extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
354 extern VOID __cdecl CopyParams(VOID);
355 extern VOID __cdecl ReadBatch(VOID);
356 extern VOID __cdecl FrRestore(VOID);
357
358 //
359 // Sanitizes a selector
360 //
361 FORCEINLINE
362 ULONG
363 Ke386SanitizeSeg(IN ULONG Cs,
364 IN KPROCESSOR_MODE Mode)
365 {
366 //
367 // Check if we're in kernel-mode, and force CPL 0 if so.
368 // Otherwise, force CPL 3.
369 //
370 return ((Mode == KernelMode) ?
371 (Cs & (0xFFFF & ~RPL_MASK)) :
372 (RPL_MASK | (Cs & 0xFFFF)));
373 }
374
375 //
376 // Sanitizes EFLAGS
377 //
378 FORCEINLINE
379 ULONG
380 Ke386SanitizeFlags(IN ULONG Eflags,
381 IN KPROCESSOR_MODE Mode)
382 {
383 //
384 // Check if we're in kernel-mode, and sanitize EFLAGS if so.
385 // Otherwise, also force interrupt mask on.
386 //
387 return ((Mode == KernelMode) ?
388 (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
389 (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
390 }
391
392 //
393 // Gets a DR register from a CONTEXT structure
394 //
395 FORCEINLINE
396 PVOID
397 KiDrFromContext(IN ULONG Dr,
398 IN PCONTEXT Context)
399 {
400 return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
401 }
402
403 //
404 // Gets a DR register from a KTRAP_FRAME structure
405 //
406 FORCEINLINE
407 PVOID*
408 KiDrFromTrapFrame(IN ULONG Dr,
409 IN PKTRAP_FRAME TrapFrame)
410 {
411 return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
412 }
413
414 //
415 // Sanitizes a Debug Register
416 //
417 FORCEINLINE
418 PVOID
419 Ke386SanitizeDr(IN PVOID DrAddress,
420 IN KPROCESSOR_MODE Mode)
421 {
422 //
423 // Check if we're in kernel-mode, and return the address directly if so.
424 // Otherwise, make sure it's not inside the kernel-mode address space.
425 // If it is, then clear the address.
426 //
427 return ((Mode == KernelMode) ? DrAddress :
428 (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
429 }
430
431 #endif
432 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */