Export (0) Print
Expand All
3 out of 3 rated this helpful - Rate this topic

Floating-Point Support for 64-Bit Drivers

Floating-point support for 64-bit kernel-mode drivers is implemented differently from floating-point support for 32-bit drivers. In particular, 64-bit drivers never use the legacy MMX and x87 floating-point stack registers (MM0-MM7/ST0-ST7). Therefore, 64-bit drivers that do floating-point operations are not restricted by the rules that apply to the use of these registers. For information about the rules that apply to 32-bit drivers that use floating point, see Using Floating Point or MMX in a WDM Driver.

By default, 32-bit and 64-bit versions of Windows disable arithmetic exceptions that are caused by operations on x87 and SSE floating-point registers. This default applies to both user-mode applications and kernel-mode drivers. Unless an application or a driver explicitly enables these exceptions, an invalid or indeterminate computation (for example, divide-by-zero or overflow) will produce a value of infinity or NaN but will not cause an exception. Similarly, versions of Windows that support the x86 Advanced Vector Extension (AVX) or Itanium-based processors disable, by default, arithmetic exceptions that are caused by operations on AVX registers or Itanium-based floating-point registers.

Legacy MMX/x87 Registers

In 64-bit versions of Windows, the operating system preserves the MMX/x87 registers across thread (and process) switches. However, there is no explicit calling convention for the MMX/x87 registers. Code that is produced by the 64-bit compiler for x64 processors does not use these registers and does not preserve them across function calls.

The use of the MMX/x87 registers is strictly prohibited in 64-bit kernel-mode code. Typically, this restriction affects only assembly-language programmers. The 64-bit compiler for x64 processors automatically converts floating-point operations to SSE instructions.

Eliminating the use of the MMX/x87 registers simplifies floating-point operations in 64-bit drivers. In particular, it is unnecessary for these drivers to surround floating-point operations with calls to the KeSaveFloatingPointState and KeRestoreFloatingPointState routines. As an option, a 64-bit driver can safely call KeSaveFloatingPointState and KeRestoreFloatingPointState, but these routines do not necessarily save and restore any processor state.

SSE Registers

As mentioned earlier, the 64-bit compiler for x64 processors automatically converts floating-point operations to SSE instructions. The x64 compiler follows a calling convention that specifies which of the SSE registers (XMM0-XMM15) are used to pass parameters and which are preserved across function calls. In 64-bit versions of Windows, the operating system preserves the SSE registers across thread (and process) switches. The result is that 64-bit driver code can safely use floating-point operations at any IRQL. For more information about the calling conventions that are used by the x64 compiler, see Register Usage.

Unlike 32-bit drivers, which must explicitly save and restore the SSE registers, 64-bit drivers can rely on the x64 compiler and the operating system to preserve these registers.

For example, a 32-bit driver can explicitly save the SSE registers by calling the KeSaveExtendedProcessorState routine and passing the XSTATE_MASK_LEGACY_SSE flag to this routine as an input parameter. When the 32-bit driver is finished using the SSE registers, it restores them by calling the KeRestoreExtendedProcessorState routine. For a 64-bit driver, these calls are unnecessary. As an option, a 64-bit driver can safely call KeSaveExtendedProcessorState and KeRestoreExtendedProcessorState, but these routines do not necessarily save and restore any processor state.

Instead of KeSaveExtendedProcessorState and KeRestoreExtendedProcessorState, a 32-bit processor can call the KeSaveFloatingPointState and KeRestoreFloatingPointState routines, which save and restore both the MMX/x87 state and SSE state. Again, a 64-bit driver can, as an option, call these routines, but they do not necessarily save and restore any processor state.

AVX Registers

New x86 processors, such as the Intel Sandy Bridge (formerly Gesher) processor, support the AVX instructions and register set (YMM0-YMM15). In Windows 7 with Service Pack 1 (SP1) and Windows Server 2008 R2, both 32-bit and 64-bit versions of the operating system preserve the AVX registers across thread (and process) switches. To use the AVX registers in kernel mode, a 32-bit or 64-bit driver must explicitly save and restore the AVX registers, just as a 32-bit driver that uses the MMX/x87 registers must explicitly save and restore the MMX/x87 registers. Before a 64-bit driver can use the AVX registers, it must save these registers by calling the KeSaveExtendedProcessorState routine and passing the XSTATE_MASK_GSSE flag to this routine as an input parameter. Before a 32-bit driver can use the AVX registers, it must save these registers by calling KeSaveExtendedProcessorState and passing the parameter value XSTATE_MASK_SSE | XSTATE_MASK_GSSE to this routine. When the driver is finished using the AVX registers, it restores them by calling the KeRestoreExtendedProcessorState routine. The driver must make sure that KeSaveExtendedProcessorState has returned without error before it performs an operation that uses an AVX register. If the AVX registers are not saved and restored correctly, calculation errors in concurrent user-mode applications can occur.

Do not access the AVX registers in an interrupt service routine.

Itanium Floating-Point Registers

The Itanium processor architecture supports 128 floating-point registers. In 64-bit versions of Windows that run on Itanium-based processors, the operating system preserves these registers across thread (and process) switches. However, kernel-mode drivers can use only the first 32 floating-point registers, f0-f31. (Registers f0 and f1 contain constants and are read-only.) The use of registers f32-f127 is strictly prohibited in kernel-mode code. Typically, this restriction affects only assembly-language programmers. Code that is produced by the 64-bit compiler for Itanium-based processors (Itanium compiler) uses only registers f0-f31. Therefore, a 64-bit driver that is compiled by the Itanium compiler can safely use floating-point operations at any IRQL. For more information about the calling conventions that are used by the Itanium compiler, see Itanium Software Conventions and Runtime Architecture Guide at the Intel Developer Center website.

 

 

Send comments about this topic to Microsoft

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.