Windows ドライバーでの拡張プロセッサ機能の使用
最終更新日
- 2016 年 7 月
拡張プロセッサ機能を使用する x86 および x64 システムの Windows ドライバーは、レジスタを使用している可能性がある同時実行アプリケーションでエラーが発生しないよう、KeSaveExtendedProcessorState と KeRestoreExtendedProcessorState の呼び出しの間で浮動小数点計算をラップする必要があります。
レガシ MMX/x87 レジスタ
これらのレジスタは、XSTATE_MASK_LEGACY_FLOATING_POINT マスクに対応しており、x64 システムのドライバーでは使用できません。 これらのレジスタについて詳しくは、「WDM ドライバーでの浮動小数点の使用」をご覧ください。
SSE レジスタ
これらのレジスタは、XSTATE_MASK_LEGACY_SSE フラグに対応しており、x64 コンパイラによって浮動小数点演算に使用されます。 これらのレジスタを使用する x86 システムのドライバーは、KeSaveExtendedProcessorState の呼び出しで XSTATE_MASK_LEGACY または XSTATE_MASK_LEGACY_SSE フラグを渡して使用する前に保存する必要があります。完了したら、KeRestoreExtendedProcessorState を使用して復元します。 これは x64 システムでは不要ですが、問題を引き起こすことはありません。 これらのレジスタについて詳しくは、「WDM ドライバーでの浮動小数点の使用」をご覧ください。
AVX レジスタ
これらのレジスタは、XSTATE_MASK_GSSE または XSTATE_MASK_AVX マスクに対応しています。 Intel Sandy Bridge (旧 Gesher) プロセッサなどの新しい x86 プロセッサは、AVX 命令とレジスタ セット (YMM0-YMM15) をサポートしています。 Windows 7 Service Pack 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 ドライバーでの浮動小数点の使用