[NTOS:KE] Remove all checks for x87 not being present

This commit is contained in:
Victor Perevertkin 2022-01-15 04:15:05 +03:00
parent 1aca6937ff
commit 99a6667bd9
No known key found for this signature in database
GPG key ID: C750B7222E9C7830
4 changed files with 151 additions and 335 deletions

View file

@ -24,7 +24,7 @@ UCHAR KiNMITSS[KTSS_IO_MAPS];
ULONG KeI386CpuType;
ULONG KeI386CpuStep;
ULONG KiFastSystemCallDisable = 0;
ULONG KeI386NpxPresent = 0;
ULONG KeI386NpxPresent = TRUE;
ULONG KiMXCsrMask = 0;
ULONG MxcsrFeatureMask = 0;
ULONG KeI386XMMIPresent = 0;
@ -90,66 +90,30 @@ VOID
NTAPI
KiSetProcessorType(VOID)
{
ULONG EFlags, NewEFlags;
CPU_INFO CpuInfo;
ULONG Stepping, Type;
/* Start by assuming no CPUID data */
KeGetCurrentPrcb()->CpuID = 0;
/* Do CPUID 1 now */
KiCpuId(&CpuInfo, 1);
/* Save EFlags */
EFlags = __readeflags();
/*
* Get the Stepping and Type. The stepping contains both the
* Model and the Step, while the Type contains the returned Type.
* We ignore the family.
*
* For the stepping, we convert this: zzzzzzxy into this: x0y
*/
Stepping = CpuInfo.Eax & 0xF0;
Stepping <<= 4;
Stepping += (CpuInfo.Eax & 0xFF);
Stepping &= 0xF0F;
Type = CpuInfo.Eax & 0xF00;
Type >>= 8;
/* XOR out the ID bit and update EFlags */
NewEFlags = EFlags ^ EFLAGS_ID;
__writeeflags(NewEFlags);
/* Get them back and see if they were modified */
NewEFlags = __readeflags();
if (NewEFlags != EFlags)
{
/* The modification worked, so CPUID exists. Set the ID Bit again. */
EFlags |= EFLAGS_ID;
__writeeflags(EFlags);
/* Peform CPUID 0 to see if CPUID 1 is supported */
KiCpuId(&CpuInfo, 0);
if (CpuInfo.Eax > 0)
{
/* Do CPUID 1 now */
KiCpuId(&CpuInfo, 1);
/*
* Get the Stepping and Type. The stepping contains both the
* Model and the Step, while the Type contains the returned Type.
* We ignore the family.
*
* For the stepping, we convert this: zzzzzzxy into this: x0y
*/
Stepping = CpuInfo.Eax & 0xF0;
Stepping <<= 4;
Stepping += (CpuInfo.Eax & 0xFF);
Stepping &= 0xF0F;
Type = CpuInfo.Eax & 0xF00;
Type >>= 8;
/* Save them in the PRCB */
KeGetCurrentPrcb()->CpuID = TRUE;
KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
}
else
{
DPRINT1("CPUID Support lacking\n");
}
}
else
{
DPRINT1("CPUID Support lacking\n");
}
/* Restore EFLAGS */
__writeeflags(EFlags);
/* Save them in the PRCB */
KeGetCurrentPrcb()->CpuID = TRUE;
KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
}
CODE_SEG("INIT")
@ -160,10 +124,6 @@ KiGetCpuVendor(VOID)
PKPRCB Prcb = KeGetCurrentPrcb();
CPU_INFO CpuInfo;
/* Assume no Vendor ID and fail if no CPUID Support. */
Prcb->VendorString[0] = 0;
if (!Prcb->CpuID) return 0;
/* Get the Vendor ID */
KiCpuId(&CpuInfo, 0);
@ -465,7 +425,6 @@ NTAPI
KiGetCacheInformation(VOID)
{
PKIPCR Pcr = (PKIPCR)KeGetPcr();
ULONG Vendor;
CPU_INFO CpuInfo;
ULONG CacheRequests = 0, i;
ULONG CurrentRegister;
@ -476,12 +435,8 @@ KiGetCacheInformation(VOID)
/* Set default L2 size */
Pcr->SecondLevelCacheSize = 0;
/* Get the Vendor ID and make sure we support CPUID */
Vendor = KiGetCpuVendor();
if (!Vendor) return;
/* Check the Vendor ID */
switch (Vendor)
switch (KiGetCpuVendor())
{
/* Handle Intel case */
case CPU_INTEL:
@ -1158,47 +1113,6 @@ KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame,
KiSaveProcessorControlState(&Prcb->ProcessorState);
}
CODE_SEG("INIT")
BOOLEAN
NTAPI
KiIsNpxPresent(VOID)
{
ULONG Cr0;
USHORT Magic;
/* Set magic */
Magic = 0xFFFF;
/* Read CR0 and mask out FPU flags */
Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
/* Store on FPU stack */
#ifdef _MSC_VER
__asm fninit;
__asm fnstsw Magic;
#else
asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
#endif
/* Magic should now be cleared */
if (Magic & 0xFF)
{
/* You don't have an FPU -- enable emulation for now */
__writecr0(Cr0 | CR0_EM | CR0_TS);
return FALSE;
}
/* You have an FPU, enable it */
Cr0 |= CR0_ET;
/* Enable INT 16 on 486 and higher */
if (KeGetCurrentPrcb()->CpuType >= 3) Cr0 |= CR0_NE;
/* Set FPU state */
__writecr0(Cr0 | CR0_EM | CR0_TS);
return TRUE;
}
CODE_SEG("INIT")
BOOLEAN
NTAPI
@ -1208,8 +1122,8 @@ KiIsNpxErrataPresent(VOID)
INT ErrataPresent;
ULONG Cr0;
/* Disable interrupts */
_disable();
/* Interrupts have to be disabled here. */
ASSERT(!(__readeflags() & EFLAGS_INTERRUPT_MASK));
/* Read CR0 and remove FPU flags */
Cr0 = __readcr0();
@ -1247,9 +1161,6 @@ KiIsNpxErrataPresent(VOID)
/* Restore CR0 */
__writecr0(Cr0);
/* Enable interrupts */
_enable();
/* Return if there's an errata */
return ErrataPresent != 0;
}
@ -1370,9 +1281,6 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
UNIMPLEMENTED_ONCE;
/* check if we are doing software emulation */
if (!KeI386NpxPresent) return STATUS_ILLEGAL_FLOAT_CONTEXT;
FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT));
if (!FpState) return STATUS_INSUFFICIENT_RESOURCES;

View file

@ -434,30 +434,25 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Get the FX Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Check if NPX is present */
if (KeI386NpxPresent)
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Copy the FX State */
RtlCopyMemory(&FxSaveArea->U.FxArea,
&Context->ExtendedRegisters[0],
MAXIMUM_SUPPORTED_EXTENSION);
/* Remove reserved bits from MXCSR */
FxSaveArea->U.FxArea.MXCsr &= KiMXCsrMask;
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Copy the FX State */
RtlCopyMemory(&FxSaveArea->U.FxArea,
&Context->ExtendedRegisters[0],
MAXIMUM_SUPPORTED_EXTENSION);
/* Remove reserved bits from MXCSR */
FxSaveArea->U.FxArea.MXCsr &= KiMXCsrMask;
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
}
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState & (CR0_EM | CR0_MP);
}
}
@ -468,88 +463,63 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Get the FX Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Check if NPX is present */
if (KeI386NpxPresent)
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Check if we have Fxsr support */
if (KeI386FxsrPresent)
{
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Convert the Fn Floating Point state to Fx */
FxSaveArea->U.FxArea.ControlWord = (USHORT)Context->FloatSave.ControlWord;
FxSaveArea->U.FxArea.StatusWord = (USHORT)Context->FloatSave.StatusWord;
FxSaveArea->U.FxArea.TagWord =
KiTagWordFnsaveToFxsave((USHORT)Context->FloatSave.TagWord);
FxSaveArea->U.FxArea.ErrorOpcode =
(USHORT)((Context->FloatSave.ErrorSelector >> 16) & 0xFFFF);
FxSaveArea->U.FxArea.ErrorOffset = Context->FloatSave.ErrorOffset;
FxSaveArea->U.FxArea.ErrorSelector = Context->FloatSave.ErrorSelector & 0xFFFF;
FxSaveArea->U.FxArea.DataOffset = Context->FloatSave.DataOffset;
FxSaveArea->U.FxArea.DataSelector = Context->FloatSave.DataSelector;
/* Check if we have Fxsr support */
if (KeI386FxsrPresent)
/* Clear out the Register Area */
RtlZeroMemory(&FxSaveArea->U.FxArea.RegisterArea[0], SIZE_OF_FX_REGISTERS);
/* Loop the 8 floating point registers */
for (i = 0; i < 8; i++)
{
/* Convert the Fn Floating Point state to Fx */
FxSaveArea->U.FxArea.ControlWord =
(USHORT)Context->FloatSave.ControlWord;
FxSaveArea->U.FxArea.StatusWord =
(USHORT)Context->FloatSave.StatusWord;
FxSaveArea->U.FxArea.TagWord =
KiTagWordFnsaveToFxsave((USHORT)Context->FloatSave.TagWord);
FxSaveArea->U.FxArea.ErrorOpcode =
(USHORT)((Context->FloatSave.ErrorSelector >> 16) & 0xFFFF);
FxSaveArea->U.FxArea.ErrorOffset =
Context->FloatSave.ErrorOffset;
FxSaveArea->U.FxArea.ErrorSelector =
Context->FloatSave.ErrorSelector & 0xFFFF;
FxSaveArea->U.FxArea.DataOffset =
Context->FloatSave.DataOffset;
FxSaveArea->U.FxArea.DataSelector =
Context->FloatSave.DataSelector;
/* Clear out the Register Area */
RtlZeroMemory(&FxSaveArea->U.FxArea.RegisterArea[0],
SIZE_OF_FX_REGISTERS);
/* Loop the 8 floating point registers */
for (i = 0; i < 8; i++)
{
/* Copy from Fn to Fx */
RtlCopyMemory(FxSaveArea->U.FxArea.RegisterArea + (i * 16),
Context->FloatSave.RegisterArea + (i * 10),
10);
}
}
else
{
/* Copy the structure */
FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.
ControlWord;
FxSaveArea->U.FnArea.StatusWord = Context->FloatSave.
StatusWord;
FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord;
FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave.
ErrorOffset;
FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave.
ErrorSelector;
FxSaveArea->U.FnArea.DataOffset = Context->FloatSave.
DataOffset;
FxSaveArea->U.FnArea.DataSelector = Context->FloatSave.
DataSelector;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy registers */
FxSaveArea->U.FnArea.RegisterArea[i] =
Context->FloatSave.RegisterArea[i];
}
}
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
/* Copy from Fn to Fx */
RtlCopyMemory(FxSaveArea->U.FxArea.RegisterArea + (i * 16),
Context->FloatSave.RegisterArea + (i * 10),
10);
}
}
else
{
/* FIXME: Handle FPU Emulation */
//ASSERT(FALSE);
UNIMPLEMENTED;
/* Copy the structure */
FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.ControlWord;
FxSaveArea->U.FnArea.StatusWord = Context->FloatSave.StatusWord;
FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord;
FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave.ErrorOffset;
FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave.ErrorSelector;
FxSaveArea->U.FnArea.DataOffset = Context->FloatSave.DataOffset;
FxSaveArea->U.FnArea.DataSelector = Context->FloatSave.DataSelector;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy registers */
FxSaveArea->U.FnArea.RegisterArea[i] = Context->FloatSave.RegisterArea[i];
}
}
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState & (CR0_EM | CR0_MP);
}
}
@ -698,17 +668,13 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
/* Get the FX Save Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Make sure NPX is present */
if (KeI386NpxPresent)
{
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Flush the NPX State */
KiFlushNPXState(NULL);
/* Copy the registers */
RtlCopyMemory(&Context->ExtendedRegisters[0],
&FxSaveArea->U.FxArea,
MAXIMUM_SUPPORTED_EXTENSION);
}
/* Copy the registers */
RtlCopyMemory(&Context->ExtendedRegisters[0],
&FxSaveArea->U.FxArea,
MAXIMUM_SUPPORTED_EXTENSION);
}
/* Handle Floating Point */
@ -718,49 +684,38 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
/* Get the FX Save Area */
FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
/* Make sure we have an NPX */
if (KeI386NpxPresent)
{
/* Check if we have Fxsr support */
if (KeI386FxsrPresent)
{
/* Align the floating area to 16-bytes */
FloatSaveArea = (FLOATING_SAVE_AREA*)
((ULONG_PTR)&FloatSaveBuffer.UnalignedArea &~ 0xF);
/* Check if we have Fxsr support */
if (KeI386FxsrPresent)
{
/* Align the floating area to 16-bytes */
FloatSaveArea = (FLOATING_SAVE_AREA*)((ULONG_PTR)&FloatSaveBuffer.UnalignedArea &~ 0xF);
/* Get the State */
KiFlushNPXState(FloatSaveArea);
}
else
{
/* We don't, use the FN area and flush the NPX State */
FloatSaveArea = (FLOATING_SAVE_AREA*)&FxSaveArea->U.FnArea;
KiFlushNPXState(NULL);
}
/* Get the State */
KiFlushNPXState(FloatSaveArea);
}
else
{
/* We don't, use the FN area and flush the NPX State */
FloatSaveArea = (FLOATING_SAVE_AREA*)&FxSaveArea->U.FnArea;
KiFlushNPXState(NULL);
}
/* Copy structure */
Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
Context->FloatSave.TagWord = FloatSaveArea->TagWord;
Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset;
Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector;
Context->FloatSave.DataOffset = FloatSaveArea->DataOffset;
Context->FloatSave.DataSelector = FloatSaveArea->DataSelector;
Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState;
/* Copy structure */
Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
Context->FloatSave.TagWord = FloatSaveArea->TagWord;
Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset;
Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector;
Context->FloatSave.DataOffset = FloatSaveArea->DataOffset;
Context->FloatSave.DataSelector = FloatSaveArea->DataSelector;
Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy them */
Context->FloatSave.RegisterArea[i] =
FloatSaveArea->RegisterArea[i];
}
}
else
{
/* FIXME: Handle Emulation */
ASSERT(FALSE);
}
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy them */
Context->FloatSave.RegisterArea[i] = FloatSaveArea->RegisterArea[i];
}
}
/* Handle debug registers */

View file

@ -85,58 +85,6 @@ KiInitMachineDependent(VOID)
/* Check for PAT support and enable it */
if (KeFeatureBits & KF_PAT) KiInitializePAT();
/* Assume no errata for now */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
/* Check if we have an NPX */
if (KeI386NpxPresent)
{
/* Loop every CPU */
i = KeActiveProcessors;
for (Affinity = 1; i; Affinity <<= 1)
{
/* Check if this is part of the set */
if (i & Affinity)
{
/* Run on this CPU */
i &= ~Affinity;
KeSetSystemAffinityThread(Affinity);
/* Detect FPU errata */
if (KiIsNpxErrataPresent())
{
/* Disable NPX support */
KeI386NpxPresent = FALSE;
SharedUserData->
ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
TRUE;
break;
}
}
}
}
/* If there's no NPX, then we're emulating the FPU */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
!KeI386NpxPresent;
/* Check if there's no NPX, so that we can disable associated features */
if (!KeI386NpxPresent)
{
/* Remove NPX-related bits */
KeFeatureBits &= ~(KF_XMMI64 | KF_XMMI | KF_FXSR | KF_MMX);
/* Disable kernel flags */
KeI386FxsrPresent = KeI386XMMIPresent = FALSE;
/* Disable processor features that might've been set until now */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 0;
}
/* Check for CR4 support */
if (KeFeatureBits & KF_CR4)
{
@ -459,6 +407,21 @@ KiVerifyCpuFeatures(PKPRCB Prcb)
KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000001, 0, 0);
}
// Set up FPU-related CR0 flags.
ULONG Cr0 = __readcr0();
// Disable emulation and monitoring.
Cr0 &= ~(CR0_EM | CR0_MP);
// Enable FPU exceptions.
Cr0 |= CR0_NE;
__writecr0(Cr0);
// Check for Pentium FPU bug.
if (KiIsNpxErrataPresent())
{
KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000001, 0, 0);
}
// 5. Save feature bits.
Prcb->FeatureBits = FeatureBits;
}
@ -590,6 +553,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
/* Set basic CPU Features that user mode can read */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE;
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
(KeFeatureBits & KF_MMX) ? TRUE: FALSE;
SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =

View file

@ -152,28 +152,17 @@ KiInitializeContextThread(IN PKTHREAD Thread,
Context->FloatSave.DataSelector = 0;
}
/* Check if the CPU has NPX */
if (KeI386NpxPresent)
{
/* Set an intial NPX State */
Context->FloatSave.Cr0NpxState = 0;
FxSaveArea->Cr0NpxState = 0;
FxSaveArea->NpxSavedCpu = 0;
/* Set an intial NPX State */
Context->FloatSave.Cr0NpxState = 0;
FxSaveArea->Cr0NpxState = 0;
FxSaveArea->NpxSavedCpu = 0;
/* Now set the context flags depending on XMM support */
ContextFlags |= (KeI386FxsrPresent) ? CONTEXT_EXTENDED_REGISTERS :
CONTEXT_FLOATING_POINT;
/* Now set the context flags depending on XMM support */
ContextFlags |= (KeI386FxsrPresent) ? CONTEXT_EXTENDED_REGISTERS : CONTEXT_FLOATING_POINT;
/* Set the Thread's NPX State */
Thread->NpxState = NPX_STATE_NOT_LOADED;
Thread->Header.NpxIrql = PASSIVE_LEVEL;
}
else
{
/* We'll use emulation */
FxSaveArea->Cr0NpxState = CR0_EM;
Thread->NpxState = NPX_STATE_NOT_LOADED &~ CR0_MP;
}
/* Set the Thread's NPX State */
Thread->NpxState = NPX_STATE_NOT_LOADED;
Thread->Header.NpxIrql = PASSIVE_LEVEL;
/* Disable any debug registers */
Context->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;