unbreak build
[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 //
90 // Flags used by the VDM/V8086 emulation engine for determining instruction prefixes
91 //
92 #define PFX_FLAG_ES 0x00000100
93 #define PFX_FLAG_CS 0x00000200
94 #define PFX_FLAG_SS 0x00000400
95 #define PFX_FLAG_DS 0x00000800
96 #define PFX_FLAG_FS 0x00001000
97 #define PFX_FLAG_GS 0x00002000
98 #define PFX_FLAG_OPER32 0x00004000
99 #define PFX_FLAG_ADDR32 0x00008000
100 #define PFX_FLAG_LOCK 0x00010000
101 #define PFX_FLAG_REPNE 0x00020000
102 #define PFX_FLAG_REP 0x00040000
103
104 //
105 // VDM Helper Macros
106 //
107 // All VDM/V8086 opcode emulators have the same FASTCALL function definition.
108 // We need to keep 2 parameters while the original ASM implementation uses 4:
109 // TrapFrame, PrefixFlags, Eip, InstructionSize;
110 //
111 // We pass the trap frame, and prefix flags, in our two parameters.
112 //
113 // We then realize that since the smallest prefix flag is 0x100, this gives us
114 // a count of up to 0xFF. So we OR in the instruction size with the prefix flags
115 //
116 // We further realize that we always have access to EIP from the trap frame, and
117 // that if we want the *current instruction* EIP, we simply have to add the
118 // instruction size *MINUS ONE*, and that gives us the EIP we should be looking
119 // at now, so we don't need to use the stack to push this parameter.
120 //
121 // We actually only care about the *current instruction* EIP in one location,
122 // so although it may be slightly more expensive to re-calculate the EIP one
123 // more time, this way we don't redefine ALL opcode handlers to have 3 parameters,
124 // which would be forcing stack usage in all other scenarios.
125 //
126 #define KiVdmSetVdmEFlags(x) InterlockedOr((PLONG)KiNtVdmState, (x));
127 #define KiVdmClearVdmEFlags(x) InterlockedAnd((PLONG)KiNtVdmState, ~(x))
128 #define KiCallVdmHandler(x) KiVdmOpcode##x(TrapFrame, Flags)
129 #define KiCallVdmPrefixHandler(x) KiVdmOpcodePrefix(TrapFrame, Flags | x)
130 #define KiVdmUnhandledOpcode(x) \
131 BOOLEAN \
132 FASTCALL \
133 KiVdmOpcode##x(IN PKTRAP_FRAME TrapFrame, \
134 IN ULONG Flags) \
135 { \
136 /* Not yet handled */ \
137 UNIMPLEMENTED; \
138 while (TRUE); \
139 return TRUE; \
140 }
141
142
143 //
144 // Registers an interrupt handler with an IDT vector
145 //
146 FORCEINLINE
147 VOID
148 KeRegisterInterruptHandler(IN ULONG Vector,
149 IN PVOID Handler)
150 {
151 UCHAR Entry;
152 ULONG_PTR Address;
153 PKIPCR Pcr = (PKIPCR)KeGetPcr();
154
155 //
156 // Get the entry from the HAL
157 //
158 Entry = HalVectorToIDTEntry(Vector);
159 Address = PtrToUlong(Handler);
160
161 //
162 // Now set the data
163 //
164 Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16);
165 Pcr->IDT[Entry].Offset = (USHORT)Address;
166 }
167
168 //
169 // Returns the registered interrupt handler for a given IDT vector
170 //
171 FORCEINLINE
172 PVOID
173 KeQueryInterruptHandler(IN ULONG Vector)
174 {
175 PKIPCR Pcr = (PKIPCR)KeGetPcr();
176 UCHAR Entry;
177
178 //
179 // Get the entry from the HAL
180 //
181 Entry = HalVectorToIDTEntry(Vector);
182
183 //
184 // Read the entry from the IDT
185 //
186 return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) |
187 (Pcr->IDT[Entry].Offset & 0xFFFF));
188 }
189
190 //
191 // Invalidates the TLB entry for a specified address
192 //
193 FORCEINLINE
194 VOID
195 KeInvalidateTlbEntry(IN PVOID Address)
196 {
197 /* Invalidate the TLB entry for this address */
198 __invlpg(Address);
199 }
200
201 FORCEINLINE
202 VOID
203 KeFlushProcessTb(VOID)
204 {
205 /* Flush the TLB by resetting CR3 */
206 __writecr3(__readcr3());
207 }
208
209 FORCEINLINE
210 PRKTHREAD
211 KeGetCurrentThread(VOID)
212 {
213 /* Return the current thread */
214 return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
215 }
216
217 FORCEINLINE
218 VOID
219 KiRundownThread(IN PKTHREAD Thread)
220 {
221 #ifndef CONFIG_SMP
222 /* Check if this is the NPX Thread */
223 if (KeGetCurrentPrcb()->NpxThread == Thread)
224 {
225 /* Clear it */
226 KeGetCurrentPrcb()->NpxThread = NULL;
227 Ke386FnInit();
228 }
229 #else
230 /* Nothing to do */
231 #endif
232 }
233
234 VOID
235 FASTCALL
236 Ki386InitializeTss(
237 IN PKTSS Tss,
238 IN PKIDTENTRY Idt,
239 IN PKGDTENTRY Gdt
240 );
241
242 VOID
243 NTAPI
244 KiSetCR0Bits(VOID);
245
246 VOID
247 NTAPI
248 KiGetCacheInformation(VOID);
249
250 BOOLEAN
251 NTAPI
252 KiIsNpxPresent(
253 VOID
254 );
255
256 BOOLEAN
257 NTAPI
258 KiIsNpxErrataPresent(
259 VOID
260 );
261
262 VOID
263 NTAPI
264 KiSetProcessorType(VOID);
265
266 ULONG
267 NTAPI
268 KiGetFeatureBits(VOID);
269
270 #ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
271 VOID
272 NTAPI
273 KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
274 PKSTART_ROUTINE StartRoutine,
275 PVOID StartContext,
276 BOOLEAN UserThread,
277 KTRAP_FRAME TrapFrame);
278 #endif
279
280 NTSTATUS
281 NTAPI
282 Ke386GetGdtEntryThread(
283 IN PKTHREAD Thread,
284 IN ULONG Offset,
285 IN PKGDTENTRY Descriptor
286 );
287
288 VOID
289 NTAPI
290 KiFlushNPXState(
291 IN FLOATING_SAVE_AREA *SaveArea
292 );
293
294 VOID
295 NTAPI
296 Ki386AdjustEsp0(
297 IN PKTRAP_FRAME TrapFrame
298 );
299
300 VOID
301 NTAPI
302 Ki386SetupAndExitToV86Mode(
303 OUT PTEB VdmTeb
304 );
305
306 VOID
307 NTAPI
308 KeI386VdmInitialize(
309 VOID
310 );
311
312 ULONG_PTR
313 NTAPI
314 Ki386EnableGlobalPage(
315 IN volatile ULONG_PTR Context
316 );
317
318 VOID
319 NTAPI
320 KiI386PentiumLockErrataFixup(
321 VOID
322 );
323
324 VOID
325 NTAPI
326 KiInitializePAT(
327 VOID
328 );
329
330 VOID
331 NTAPI
332 KiInitializeMTRR(
333 IN BOOLEAN FinalCpu
334 );
335
336 VOID
337 NTAPI
338 KiAmdK6InitializeMTRR(
339 VOID
340 );
341
342 VOID
343 NTAPI
344 KiRestoreFastSyscallReturnState(
345 VOID
346 );
347
348 ULONG_PTR
349 NTAPI
350 Ki386EnableDE(
351 IN ULONG_PTR Context
352 );
353
354 ULONG_PTR
355 NTAPI
356 Ki386EnableFxsr(
357 IN ULONG_PTR Context
358 );
359
360 ULONG_PTR
361 NTAPI
362 Ki386EnableXMMIExceptions(
363 IN ULONG_PTR Context
364 );
365
366 BOOLEAN
367 NTAPI
368 VdmDispatchBop(
369 IN PKTRAP_FRAME TrapFrame
370 );
371
372 BOOLEAN
373 FASTCALL
374 KiVdmOpcodePrefix(
375 IN PKTRAP_FRAME TrapFrame,
376 IN ULONG Flags
377 );
378
379 BOOLEAN
380 FASTCALL
381 Ki386HandleOpcodeV86(
382 IN PKTRAP_FRAME TrapFrame
383 );
384
385 //
386 // Global x86 only Kernel data
387 //
388 extern PVOID Ki386IopmSaveArea;
389 extern ULONG KeI386EFlagsAndMaskV86;
390 extern ULONG KeI386EFlagsOrMaskV86;
391 extern BOOLEAN KeI386VirtualIntExtensions;
392 extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR];
393 extern KDESCRIPTOR KiIdtDescriptor;
394 extern ULONG Ke386GlobalPagesEnabled;
395 extern BOOLEAN KiI386PentiumLockErrataPresent;
396 extern ULONG KeI386NpxPresent;
397 extern ULONG KeI386XMMIPresent;
398 extern ULONG KeI386FxsrPresent;
399 extern ULONG KiMXCsrMask;
400 extern ULONG KeI386CpuType;
401 extern ULONG KeI386CpuStep;
402 extern UCHAR KiDebugRegisterTrapOffsets[9];
403 extern UCHAR KiDebugRegisterContextOffsets[9];
404 extern VOID __cdecl KiTrap2(VOID);
405 extern VOID __cdecl KiTrap8(VOID);
406 extern VOID __cdecl KiTrap19(VOID);
407 extern VOID __cdecl KiFastCallEntry(VOID);
408 extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
409 extern VOID __cdecl CopyParams(VOID);
410 extern VOID __cdecl ReadBatch(VOID);
411 extern VOID __cdecl FrRestore(VOID);
412
413 //
414 // Sanitizes a selector
415 //
416 FORCEINLINE
417 ULONG
418 Ke386SanitizeSeg(IN ULONG Cs,
419 IN KPROCESSOR_MODE Mode)
420 {
421 //
422 // Check if we're in kernel-mode, and force CPL 0 if so.
423 // Otherwise, force CPL 3.
424 //
425 return ((Mode == KernelMode) ?
426 (Cs & (0xFFFF & ~RPL_MASK)) :
427 (RPL_MASK | (Cs & 0xFFFF)));
428 }
429
430 //
431 // Sanitizes EFLAGS
432 //
433 FORCEINLINE
434 ULONG
435 Ke386SanitizeFlags(IN ULONG Eflags,
436 IN KPROCESSOR_MODE Mode)
437 {
438 //
439 // Check if we're in kernel-mode, and sanitize EFLAGS if so.
440 // Otherwise, also force interrupt mask on.
441 //
442 return ((Mode == KernelMode) ?
443 (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
444 (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
445 }
446
447 //
448 // Gets a DR register from a CONTEXT structure
449 //
450 FORCEINLINE
451 PVOID
452 KiDrFromContext(IN ULONG Dr,
453 IN PCONTEXT Context)
454 {
455 return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
456 }
457
458 //
459 // Gets a DR register from a KTRAP_FRAME structure
460 //
461 FORCEINLINE
462 PVOID*
463 KiDrFromTrapFrame(IN ULONG Dr,
464 IN PKTRAP_FRAME TrapFrame)
465 {
466 return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
467 }
468
469 //
470 // Sanitizes a Debug Register
471 //
472 FORCEINLINE
473 PVOID
474 Ke386SanitizeDr(IN PVOID DrAddress,
475 IN KPROCESSOR_MODE Mode)
476 {
477 //
478 // Check if we're in kernel-mode, and return the address directly if so.
479 // Otherwise, make sure it's not inside the kernel-mode address space.
480 // If it is, then clear the address.
481 //
482 return ((Mode == KernelMode) ? DrAddress :
483 (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
484 }
485
486 #endif
487 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */