#pragma once #ifdef __cplusplus extern "C" { #endif FORCEINLINE PKGDTENTRY KiGetGdtEntry( _In_ PVOID pGdt, _In_ USHORT Selector) { return (PKGDTENTRY)((ULONG_PTR)pGdt + (Selector & ~RPL_MASK)); } FORCEINLINE VOID KiSetGdtDescriptorBase( _Inout_ PKGDTENTRY Entry, _In_ ULONG32 Base) { Entry->BaseLow = (USHORT)(Base & 0xffff); Entry->HighWord.Bytes.BaseMid = (UCHAR)((Base >> 16) & 0xff); Entry->HighWord.Bytes.BaseHi = (UCHAR)((Base >> 24) & 0xff); // Entry->BaseUpper = (ULONG)(Base >> 32); } FORCEINLINE VOID KiSetGdtDescriptorLimit( _Inout_ PKGDTENTRY Entry, _In_ ULONG Limit) { if (Limit < 0x100000) { Entry->HighWord.Bits.Granularity = 0; } else { Limit >>= 12; Entry->HighWord.Bits.Granularity = 1; } Entry->LimitLow = (USHORT)(Limit & 0xffff); Entry->HighWord.Bits.LimitHi = ((Limit >> 16) & 0x0f); } FORCEINLINE VOID KiSetGdtEntryEx( _Inout_ PKGDTENTRY Entry, _In_ ULONG32 Base, _In_ ULONG Limit, _In_ UCHAR Type, _In_ UCHAR Dpl, _In_ BOOLEAN Granularity, _In_ UCHAR SegMode) // 0: 16-bit, 1: 32-bit, 2: 64-bit { KiSetGdtDescriptorBase(Entry, Base); KiSetGdtDescriptorLimit(Entry, Limit); Entry->HighWord.Bits.Type = (Type & 0x1f); Entry->HighWord.Bits.Dpl = (Dpl & 0x3); Entry->HighWord.Bits.Pres = (Type != 0); // Present, must be 1 when the GDT entry is valid. Entry->HighWord.Bits.Sys = 0; // System Entry->HighWord.Bits.Reserved_0 = 0; // LongMode = !!(SegMode & 1); Entry->HighWord.Bits.Default_Big = !!(SegMode & 2); Entry->HighWord.Bits.Granularity |= !!Granularity; // The flag may have been already set by KiSetGdtDescriptorLimit(). // Entry->MustBeZero = 0; } FORCEINLINE VOID KiSetGdtEntry( _Inout_ PKGDTENTRY Entry, _In_ ULONG32 Base, _In_ ULONG Limit, _In_ UCHAR Type, _In_ UCHAR Dpl, _In_ UCHAR SegMode) // 0: 16-bit, 1: 32-bit, 2: 64-bit { KiSetGdtEntryEx(Entry, Base, Limit, Type, Dpl, FALSE, SegMode); } #if defined(__GNUC__) FORCEINLINE VOID __lgdt(_Out_ PVOID Descriptor) { PVOID* desc = (PVOID*)Descriptor; __asm__ __volatile__( "lgdt %0" : "=m" (*desc) : /* no input */ : "memory"); } FORCEINLINE VOID __sgdt(_Out_ PVOID Descriptor) { PVOID* desc = (PVOID*)Descriptor; __asm__ __volatile__( "sgdt %0" : "=m" (*desc) : /* 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 VOID Ke386RestoreFpuState(_In_ PFX_SAVE_AREA SaveArea) { extern ULONG KeI386FxsrPresent; if (KeI386FxsrPresent) { __asm__ __volatile__ ("fxrstor %0\n" : : "m"(*SaveArea)); } else { __asm__ __volatile__ ("frstor %0\n\t" : "=m" (*SaveArea)); } } FORCEINLINE VOID Ke386ClearFpExceptions(VOID) { __asm__ __volatile__ ("fnclex"); } FORCEINLINE VOID __sldt(PVOID Descriptor) { __asm__ __volatile__( "sldt %0" : "=m" (*((short*)Descriptor)) : /* no input */ : "memory"); } #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"); #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) #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 __frstor(_In_ PFX_SAVE_AREA SaveArea) { __asm mov eax, SaveArea __asm frstor [eax] } FORCEINLINE VOID __fnsave(OUT PFLOATING_SAVE_AREA SaveArea) { __asm mov eax, SaveArea __asm fnsave [eax] __asm wait; } FORCEINLINE VOID __lgdt(IN PVOID Descriptor) { __asm { mov eax, Descriptor lgdt [eax] } } FORCEINLINE VOID __sldt(PVOID Descriptor) { __asm { sldt ax mov ecx, Descriptor mov [ecx], 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((PFX_SAVE_AREA)SaveArea); } else { __fnsave((PFLOATING_SAVE_AREA)SaveArea); } } FORCEINLINE VOID Ke386RestoreFpuState(_In_ PVOID SaveArea) { if (KeI386FxsrPresent) { __fxrstor((PFX_SAVE_AREA)SaveArea); } else { __frstor((PFX_SAVE_AREA)SaveArea); } } FORCEINLINE VOID Ke386ClearFpExceptions(VOID) { __asm fnclex; } #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 #define Ke386GetGlobalDescriptorTable __sgdt #define Ke386SetGlobalDescriptorTable __lgdt #define Ke386GetLocalDescriptorTable __sldt #ifdef __cplusplus } // extern "C" #endif /* EOF */