Using Floating Point or MMX in a WDM Driver

Kernel-mode WDM drivers for Microsoft Windows Me, Windows 98, Windows 98 SE, and Windows 2000 and later must follow certain guidelines for using x87 floating-point operations, MMX, 3DNOW!, or Intel's SSE extensions.

Kernel-mode WDM drivers must wrap use of the floating-point unit (FPU) between calls to KeSaveFloatingPointState and KeRestoreFloatingPointState. Failure to use these routines can cause calculation errors in concurrent user-mode applications.

KeSaveFloatingPointState saves the FPU state of the currently running application in an opaque KFLOATING_SAVE structure and reinitializes the FPU for the driver. The routine takes a single parameter, a driver-allocated buffer, which provides support for nested calls. If the system is low on memory, KeSaveFloatingPointState can fail. Drivers must check the returned status and, if a failure occurs, must not access the FPU.

When a driver has finished using the FPU, it calls KeRestoreFloatingPointState to restore the previous floating-point state.

The following example shows how a WDM driver should wrap its FPU access:

NTSTATUS status;
double floatValue;

status = KeSaveFloatingPointState(&saveData);

if (NT_SUCCESS(status)) {

    floatValue = 1.0;

In the example, the assignment to the floating-point variable occurs between calls to KeSaveFloatingPointState and KeRestoreFloatingPointState. Because any assignment to a floating-point variable uses the FPU, drivers must ensure that KeSaveFloatingPointState has returned without error before initializing such a variable.

WDM drivers can call KeSaveFloatingPointState at IRQL <= DISPATCH_LEVEL. Floating-point operations are not supported in interrupt service routines (ISRs) on 32-bit systems. However, on Itanium-based and x64-based systems, you can use floating-point operations in any IRQL, and calls to the KeSaveFloatingPointState and KeRestoreFloatingPointState routine are unnecessary. Because 64-bit drivers do not use the MMX/x87 registers, they are not subject to the restrictions that these registers impose on 32-bit drivers. For more information, see Floating-Point Support for 64-Bit Drivers.

On NT-based systems, the FPU is set to long real precision (that is, double or 53-bit), with all exceptions masked, upon return from KeSaveFloatingPointState. On Windows Me, Windows 98, and Windows 98 SE, drivers that use the FPU must adhere to the following guidelines:

  • Access the FPU only from system worker threads, which run at IRQL = PASSIVE_LEVEL.

  • Do not call KeSaveFloatingPointState or attempt to use the FPU or MMX from a DPC, from an IOCTL handler, or from any other handler called from user mode. Do not try to circumvent this rule; drivers cannot implement a workaround that is guaranteed to operate correctly on all processors.

  • Reload the FPU control word with 0x27F after KeSaveFloatingPointState returns. Doing so ensures that the FPU is set to long real precision (double or 53-bit), with all exceptions masked, as on NT-based systems.

  • For Windows 98 and Windows 98 SE only, always call KeSaveFloatingPointState at IRQL = PASSIVE_LEVEL. Calling this routine at IRQL = DISPATCH_LEVEL can cause a system crash.



Send comments about this topic to Microsoft

© 2015 Microsoft