mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- Small patch to fix (delayed) loading of floating point state. Enables the special handling of fpu exceptions caused by frstor when used by the kernel, by implementing its use in assembly so the trap handler gets the instruction address it needs (for ALl compilers!). May or may not fix the fact that floating point state is not properly saved between threads.
See CORE-10005. svn path=/trunk/; revision=68886
This commit is contained in:
parent
bb8a6e700c
commit
fdeca1b2b2
4 changed files with 35 additions and 25 deletions
|
@ -50,21 +50,6 @@ Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)
|
|||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea)
|
||||
{
|
||||
extern ULONG KeI386FxsrPresent;
|
||||
if (KeI386FxsrPresent)
|
||||
{
|
||||
__asm__ __volatile__ ("fxrstor %0\n" : "=m"(SaveArea) : );
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ __volatile__ (".globl _FrRestore\n _FrRestore: \n frstor %0\n wait\n" : "=m"(SaveArea) : );
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
USHORT
|
||||
Ke386GetLocalDescriptorTable()
|
||||
|
|
|
@ -541,7 +541,6 @@ extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
|
|||
extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID);
|
||||
extern VOID __cdecl CopyParams(VOID);
|
||||
extern VOID __cdecl ReadBatch(VOID);
|
||||
extern VOID __cdecl FrRestore(VOID);
|
||||
extern CHAR KiSystemCallExitBranch[];
|
||||
extern CHAR KiSystemCallExit[];
|
||||
extern CHAR KiSystemCallExit2[];
|
||||
|
|
|
@ -159,4 +159,28 @@ PUBLIC @Ki386BiosCallReturnAddress@4
|
|||
popad
|
||||
ret 4
|
||||
|
||||
PUBLIC _FrRestore
|
||||
PUBLIC @Ke386LoadFpuState@4
|
||||
@Ke386LoadFpuState@4:
|
||||
|
||||
/* Check if we have FXSR and choose which operand to use */
|
||||
test byte ptr [_KeI386FxsrPresent], 1
|
||||
jz _FrRestore
|
||||
|
||||
/* Restore all the FPU, MMX, XMM and MXCSR registers */
|
||||
fxrstor [ecx]
|
||||
ret
|
||||
|
||||
/*
|
||||
* Just restore the basic FPU registers.
|
||||
* This may raise an exception depending
|
||||
* on the status word, which KiNpxHandler will
|
||||
* need to check for and handle during delayed load
|
||||
* to avoid raising an unhandled exception
|
||||
* and crashing the system.
|
||||
*/
|
||||
_FrRestore:
|
||||
frstor [ecx]
|
||||
ret
|
||||
|
||||
END
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
VOID KiFastCallEntry(VOID);
|
||||
VOID KiFastCallEntryWithSingleStep(VOID);
|
||||
|
||||
extern PVOID FrRestore;
|
||||
VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea);
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
UCHAR KiTrapPrefixTable[] =
|
||||
|
@ -251,16 +254,16 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
|
|||
SaveArea->Cr0NpxState |= CR0_TS;
|
||||
|
||||
/* Only valid if it happened during a restore */
|
||||
//if ((PVOID)TrapFrame->Eip == FrRestore)
|
||||
if ((PVOID)TrapFrame->Eip == FrRestore)
|
||||
{
|
||||
/* It did, so just skip the instruction */
|
||||
//TrapFrame->Eip += 3; /* sizeof(FRSTOR) */
|
||||
//KiEoiHelper(TrapFrame);
|
||||
TrapFrame->Eip += 3; /* Size of FRSTOR instruction */
|
||||
KiEoiHelper(TrapFrame);
|
||||
}
|
||||
}
|
||||
|
||||
/* User or kernel trap -- get ready to issue an exception */
|
||||
//if (Thread->NpxState == NPX_STATE_NOT_LOADED)
|
||||
if (Thread->NpxState == NPX_STATE_NOT_LOADED)
|
||||
{
|
||||
/* Update CR0 */
|
||||
Cr0 = __readcr0();
|
||||
|
@ -744,7 +747,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
|
|||
KiEnterTrap(TrapFrame);
|
||||
|
||||
/* Try to handle NPX delay load */
|
||||
while (TRUE)
|
||||
for (;;)
|
||||
{
|
||||
/* Get the current thread */
|
||||
Thread = KeGetCurrentThread();
|
||||
|
@ -775,15 +778,14 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
|
|||
NpxSaveArea = KiGetThreadNpxArea(NpxThread);
|
||||
|
||||
/* Save FPU state */
|
||||
DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
|
||||
//Ke386SaveFpuState(NpxSaveArea);
|
||||
Ke386SaveFpuState(NpxSaveArea);
|
||||
|
||||
/* Update NPX state */
|
||||
NpxThread->NpxState = NPX_STATE_NOT_LOADED;
|
||||
}
|
||||
|
||||
/* Load FPU state */
|
||||
//Ke386LoadFpuState(SaveArea);
|
||||
Ke386LoadFpuState(SaveArea);
|
||||
|
||||
/* Update NPX state */
|
||||
Thread->NpxState = NPX_STATE_LOADED;
|
||||
|
@ -823,7 +825,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
|
|||
{
|
||||
/*
|
||||
* If it's incorrectly set, then maybe the state is actually still valid
|
||||
* but we could've lock track of that due to a BIOS call.
|
||||
* but we could have lost track of that due to a BIOS call.
|
||||
* Make sure MP is still set, which should verify the theory.
|
||||
*/
|
||||
if (Cr0 & CR0_MP)
|
||||
|
|
Loading…
Reference in a new issue