reactos/ntoskrnl/include/internal/i386/intrin_i.h

309 lines
4.9 KiB
C
Raw Normal View History

#pragma once
#if defined(__GNUC__)
#define Ke386SetGlobalDescriptorTable(X) \
__asm__("lgdt %0\n\t" \
: /* no outputs */ \
: "m" (*X));
#define Ke386GetGlobalDescriptorTable(X) \
__asm__("sgdt %0\n\t" \
: "=m" (*X) \
: /* no input */ \
: "memory");
FORCEINLINE
VOID
Ke386FxStore(IN PFX_SAVE_AREA SaveArea)
{
asm volatile ("fxrstor (%0)" : : "r"(SaveArea));
}
FORCEINLINE
VOID
Ke386FxSave(IN PFX_SAVE_AREA SaveArea)
{
asm volatile ("fxsave (%0)" : : "r"(SaveArea));
}
FORCEINLINE
VOID
Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)
{
asm volatile ("fnsave (%0); wait" : : "r"(SaveArea));
}
FORCEINLINE
VOID
Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)
{
extern ULONG KeI386FxsrPresent;
if (KeI386FxsrPresent)
{
__asm__ __volatile__ ("fxsave %0\n" : : "m"(*SaveArea));
}
else
{
__asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(*SaveArea));
}
}
FORCEINLINE
USHORT
Ke386GetLocalDescriptorTable(VOID)
{
USHORT Ldt;
__asm__("sldt %0\n\t"
: "=m" (Ldt)
: /* no input */
: "memory");
return Ldt;
}
#define Ke386SetLocalDescriptorTable(X) \
__asm__("lldt %w0\n\t" \
: /* no outputs */ \
: "q" (X));
#define Ke386SetTr(X) __asm__ __volatile__("ltr %%ax" : :"a" (X));
FORCEINLINE
USHORT
Ke386GetTr(VOID)
{
USHORT Tr;
__asm__("str %0\n\t"
: "=m" (Tr));
return Tr;
}
#define _Ke386GetSeg(N) ({ \
unsigned int __d; \
__asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \
__d; \
})
#define _Ke386SetSeg(N,X) __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
#define Ke386FnInit() __asm__("fninit\n\t");
Trap Handlers in C Patch 1 of X (Patch by Sir_Richard <ros.arm@reactos.org>): [NTOS]: The kernel normally does not save FPU state during Ring 0 transitions since the FPU should not be used. The one exception is when a kernel debugger is attached. Unfortunately, the latter check in ReactOS results in even "print on the serial line" to count as "debugger attached", and thus FPU state was almost always saved, slowing down traps significantly. [NTOS]: The kernel also does not typically save DRx (debug) registers unless they were in use. During an exception dispatch, they are zeroed out, and later during trap exit, if any debug register is set, DR7 is updated to enable that hardware breakpoint. Unfortunately, the code to clear the debug registers had a bug: DR2 was never cleared. Because DR2 ended up being a random stack value during trap frame generation, this caused a bogus address to be added to DR2, and DR7 would then enable the 2nd hardware breakpoint. This caused the kernel to always save DRx state, which is slow, and worse, could cause random hardware breakpoints to fire. [NTOS]: Start implementing trap handling in C. ASM trap handlers will now only be 5 lines of assembly including a function call to a C handler. All C handling code uses maximum two arguments and is all FASTCALL for efficiency. [NTOS]: Implement C versions of TRAP_PROLOG and TRAP_EPILOG. Implement C version of Ki386EoiHelper. Implement C version of CommonDispatchException (and helper) and KiFatalSystemException. Implement C version of CHECK_FOR_APC_DELIVER. Implement trap debugging checks as a separate entity instead of always doing them. [NTOS]: Add missing intrinsics for DS/ES/GS segment query. The kernel is now ready for some trap handling to be done in C. Due to the FPU/Debug fixes and relaxation of paranoid debug checks, the C code will likely be faster than the original assembly. svn path=/trunk/; revision=45000
2010-01-08 15:04:19 +00:00
#define Ke386ClearDirectionFlag() __asm__ __volatile__ ("cld")
//
// CR Macros
//
#define Ke386SetCr2(X) __asm__ __volatile__("movl %0,%%cr2" : :"r" (X));
//
// Segment Macros
//
#define Ke386GetSs() _Ke386GetSeg(ss)
#define Ke386GetFs() _Ke386GetSeg(fs)
Trap Handlers in C Patch 1 of X (Patch by Sir_Richard <ros.arm@reactos.org>): [NTOS]: The kernel normally does not save FPU state during Ring 0 transitions since the FPU should not be used. The one exception is when a kernel debugger is attached. Unfortunately, the latter check in ReactOS results in even "print on the serial line" to count as "debugger attached", and thus FPU state was almost always saved, slowing down traps significantly. [NTOS]: The kernel also does not typically save DRx (debug) registers unless they were in use. During an exception dispatch, they are zeroed out, and later during trap exit, if any debug register is set, DR7 is updated to enable that hardware breakpoint. Unfortunately, the code to clear the debug registers had a bug: DR2 was never cleared. Because DR2 ended up being a random stack value during trap frame generation, this caused a bogus address to be added to DR2, and DR7 would then enable the 2nd hardware breakpoint. This caused the kernel to always save DRx state, which is slow, and worse, could cause random hardware breakpoints to fire. [NTOS]: Start implementing trap handling in C. ASM trap handlers will now only be 5 lines of assembly including a function call to a C handler. All C handling code uses maximum two arguments and is all FASTCALL for efficiency. [NTOS]: Implement C versions of TRAP_PROLOG and TRAP_EPILOG. Implement C version of Ki386EoiHelper. Implement C version of CommonDispatchException (and helper) and KiFatalSystemException. Implement C version of CHECK_FOR_APC_DELIVER. Implement trap debugging checks as a separate entity instead of always doing them. [NTOS]: Add missing intrinsics for DS/ES/GS segment query. The kernel is now ready for some trap handling to be done in C. Due to the FPU/Debug fixes and relaxation of paranoid debug checks, the C code will likely be faster than the original assembly. svn path=/trunk/; revision=45000
2010-01-08 15:04:19 +00:00
#define Ke386GetDs() _Ke386GetSeg(ds)
#define Ke386GetEs() _Ke386GetSeg(es)
#define Ke386GetGs() _Ke386GetSeg(gs)
#define Ke386SetFs(X) _Ke386SetSeg(fs, X)
#define Ke386SetDs(X) _Ke386SetSeg(ds, X)
#define Ke386SetEs(X) _Ke386SetSeg(es, X)
#define Ke386SetSs(X) _Ke386SetSeg(ss, X)
#define Ke386SetGs(X) _Ke386SetSeg(gs, X)
#elif defined(_MSC_VER)
FORCEINLINE
VOID
Ke386FnInit(VOID)
{
__asm fninit;
}
FORCEINLINE
VOID
__sgdt(OUT PVOID Descriptor)
{
__asm
{
mov eax, Descriptor
sgdt [eax]
}
}
FORCEINLINE
VOID
__fxsave(OUT PFX_SAVE_AREA SaveArea)
{
__asm mov eax, SaveArea
__asm fxsave [eax]
}
FORCEINLINE
VOID
__fxrstor(IN PFX_SAVE_AREA SaveArea)
{
__asm mov eax, SaveArea
__asm fxrstor [eax]
}
FORCEINLINE
VOID
__fnsave(OUT PFLOATING_SAVE_AREA SaveArea)
{
__asm mov eax, SaveArea
__asm fnsave [eax]
__asm wait;
}
#define Ke386GetGlobalDescriptorTable __sgdt
FORCEINLINE
VOID
__lgdt(IN PVOID Descriptor)
{
__asm
{
mov eax, Descriptor
lgdt [eax]
}
}
#define Ke386SetGlobalDescriptorTable __lgdt
FORCEINLINE
USHORT
Ke386GetLocalDescriptorTable(VOID)
{
__asm sldt ax;
}
FORCEINLINE
VOID
Ke386SetLocalDescriptorTable(IN USHORT Descriptor)
{
__asm lldt Descriptor;
}
FORCEINLINE
VOID
Ke386SetTr(IN USHORT Tr)
{
__asm ltr Tr;
}
FORCEINLINE
USHORT
Ke386GetTr(VOID)
{
__asm str ax;
}
//
// CR Macros
//
FORCEINLINE
VOID
Ke386SetCr2(IN ULONG Value)
{
__asm mov eax, Value;
__asm mov cr2, eax;
}
//
// Segment Macros
//
FORCEINLINE
USHORT
Ke386GetSs(VOID)
{
__asm mov ax, ss;
}
FORCEINLINE
USHORT
Ke386GetFs(VOID)
{
__asm mov ax, fs;
}
FORCEINLINE
USHORT
Ke386GetDs(VOID)
{
__asm mov ax, ds;
}
FORCEINLINE
USHORT
Ke386GetEs(VOID)
{
__asm mov ax, es;
}
FORCEINLINE
VOID
Ke386SetSs(IN USHORT Value)
{
__asm mov ax, Value;
__asm mov ss, ax;
}
FORCEINLINE
VOID
Ke386SetFs(IN USHORT Value)
{
__asm mov ax, Value;
__asm mov fs, ax;
}
FORCEINLINE
VOID
Ke386SetDs(IN USHORT Value)
{
__asm mov ax, Value;
__asm mov ds, ax;
}
FORCEINLINE
VOID
Ke386SetEs(IN USHORT Value)
{
__asm mov ax, Value;
__asm mov es, ax;
}
FORCEINLINE
VOID
Ke386SetGs(IN USHORT Value)
{
__asm mov ax, Value;
__asm mov gs, ax;
}
extern ULONG KeI386FxsrPresent;
FORCEINLINE
VOID
Ke386SaveFpuState(IN PVOID SaveArea)
{
if (KeI386FxsrPresent)
{
__fxsave(SaveArea);
}
else
{
__fnsave(SaveArea);
}
}
#define Ke386FnSave __fnsave
#define Ke386FxSave __fxsave
// The name suggest, that the original author didn't understand what frstor means
#define Ke386FxStore __fxrstor
#else
#error Unknown compiler for inline assembler
#endif
/* EOF */