In my kernel routine that executes at HIGH_LEVEL IRQL, I've been trying to manage the floating-point state by directly invoking FXSAVE and FXRSTOR. As KeSaveExtendedProcessorState and KeRestoreExtendedProcessorState are not usable at this level, I had to resort to this method.
Here's my current implementation:
In the assembly code, I've defined two procedures SaveFxState and RestoreFxState:
SaveFxState PROC
; Save the floating point state
mov rax, rcx
fxsave [rax]
ret
SaveFxState ENDP
RestoreFxState PROC
; Restore the floating point state
mov rax, rcx
fxrstor [rax]
ret
RestoreFxState ENDP
These procedures are exposed with extern "C" linkage to my C++ code:
extern "C" {
void SaveFxState(void* saveArea);
void RestoreFxState(void* saveArea);
}
I use these procedures as follows:
FXSAVE_FORMAT g_FxSaveArea;
SaveFxState(&g_FxSaveArea);
// Floating-point operations are here
RestoreFxState(&g_FxSaveArea);
Can anyone confirm whether this approach is correct and safe for managing floating-point state at HIGH_LEVEL IRQL? I would appreciate any insights or suggestions for improvement.
I've been working on kernel programming and needed to perform floating-point operations. One of the challenges with doing this in kernel mode is preserving the floating-point and SIMD state in high level irql . I wanted to share a method I've found to be effective using the _fxsave64 and _fxrstor64 intrinsics.
Prerequisites: Ensure you have a good reason to use floating-point in the kernel, as it can introduce hard-to-debug issues.
Solution: Firstly, declare a buffer to save the FPU state. This buffer should be 16-byte
aligned:
__declspec(align(16)) BYTE FpuState[512]; // Ensure the memory area is 16-byte aligned
Next, wrap your floating-point code between _fxsave64 and _fxrstor64:
void KernelFunctionWithFPUOperations()
{
_fxsave64(FpuState);
__try {
DoFloatingPointCalculation();
}
__finally {
_fxrstor64(FpuState);
}
}
Caveats:
I hope this helps anyone facing similar challenges! Feedback or further insights are welcome!