Использование расширенных функций процессора в драйверах Windows
Последнее обновление
- Июль 2016 г.
Драйверы Windows для систем x86 и x64, использующих функции расширенного процессора, должны заключать вычисления с плавающей запятой между вызовами KeSaveExtendedProcessorState и KeRestoreExtendedProcessorState , чтобы избежать ошибок в параллельных приложениях, которые могут использовать регистры.
Устаревшие регистры MMX/x87
Эти регистры соответствуют маске XSTATE_MASK_LEGACY_FLOATING_POINT и недоступны для драйверов для систем x64. Дополнительные сведения об этих регистрах см. в статье Использование с плавающей запятой в драйвере WDM.
Регистры SSE
Эти регистры соответствуют флагу XSTATE_MASK_LEGACY_SSE и используются компилятором x64 для операций с плавающей запятой. Драйверы для систем x86, использующие эти регистры, должны сохранить их перед использованием, передав флаг XSTATE_MASK_LEGACY или XSTATE_MASK_LEGACY_SSE в вызове KeSaveExtendedProcessorState , а по завершении восстановите их с помощью KeRestoreExtendedProcessorState. Это не требуется в системах x64, но не вредно. Дополнительные сведения об этих регистрах см. в статье Использование с плавающей запятой в драйвере WDM.
Регистры AVX
Эти регистры соответствуют маскам XSTATE_MASK_GSSE или XSTATE_MASK_AVX. Новые процессоры x86, такие как процессор Intel Sandy Bridge (ранее Gesher), поддерживают инструкции AVX и набор регистров (YMM0-YMM15). В Windows 7 с пакетом обновления 1 (SP1), Windows Server 2008 R2 и более поздних версиях Windows как x86, так и x64 версии операционной системы сохраняют регистры AVX в коммутаторах потоков (и процессов). Чтобы использовать регистры AVX в режиме ядра, драйверы (x86 и x64) должны явно сохранять и восстанавливать регистры AVX. Регистры AVX нельзя использовать в подпрограмме службы прерываний, а арифметические исключения по умолчанию отключены.
include ksamd64.inc
subttl "Set YMM State."
;++
;
; Routine Description:
;
; This routine loads the first four YMM registers with the state supplied.
;
; Arguments;
;
; rcx - Supplies a pointer to the values we want to load.
;
; Return Value:
;
; None
;
;--
LEAF_ENTRY SetYmmValues, _TEXT$00
vmovdqa ymm0, ymmword ptr[rcx + 0]
vmovdqa ymm1, ymmword ptr[rcx + 32]
vmovdqa ymm2, ymmword ptr[rcx + 64]
vmovdqa ymm3, ymmword ptr[rcx + 96]
ret
LEAF_END SetYmmValues, _TEXT$00
end
typedef DECLSPEC_ALIGN(32) struct _YMM_REGISTERS {
ULONG64 Ymm4Registers[16];
} YMM_REGISTERS, *PYMM_REGISTERS;
VOID
FASTCALL
SetYmmValues(
__in PYMM_REGISTERS YmmRegisterValues
);
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status;
XSTATE_SAVE SaveState;
ULONG64 EnabledFeatures;
//
// Load the first 4 YMM registers as 4 vectors of 4 64-bit integers.
//
YMM_REGISTERS RegisterValues = { 0, 1, 2, 3, // YMM0
4, 5, 6, 7, // YMM1
8, 9, 10, 11, // YMM2
12, 13, 14, 15 }; // YMM3
//
// Check to see if AVX is available. Bail if it is not.
//
EnabledFeatures = RtlGetEnabledExtendedFeatures(-1);
if ((EnabledFeatures & XSTATE_MASK_GSSE) == 0) {
Status = STATUS_FAILED_DRIVER_ENTRY;
goto exit;
}
Status = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
if (!NT_SUCCESS(Status)) {
goto exit;
}
__try {
SetYmmValues(&RegisterValues);
}
__finally {
KeRestoreExtendedProcessorState(&SaveState);
}
exit:
return Status;
}
Связанные темы
KeSaveExtendedProcessorState
KeRestoreExtendedProcessorState
Использование с плавающей запятой в драйвере WDM