mirror of
https://github.com/reactos/reactos.git
synced 2024-08-29 22:58:34 +00:00
![Justin Miller](/assets/img/avatar_default.png)
Co-authored-by: Victor Perevertkin <victor.perevertkin@reactos.org> Introduce the initial changes needed to get other processors up and into kernel mode. This only supports x86 as of now but is the first real step towards using other system processors.
461 lines
8 KiB
C
461 lines
8 KiB
C
#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 */
|