Verwenden erweiterter Prozessorfeatures in Windows-Treibern

Zuletzt aktualisiert

  • Juli 2016

Windows-Treiber für x86- und x64-Systeme, die erweiterte Prozessorfeatures verwenden, müssen Gleitkommaberechnungen zwischen Aufrufen von KeSaveExtendedProcessorState und KeRestoreExtendedProcessorState umschließen, um Fehler in gleichzeitigen Anwendungen zu vermeiden, die möglicherweise die Register verwenden.

Legacy-MMX/x87-Register

Diese Register entsprechen der XSTATE_MASK_LEGACY_FLOATING_POINT-Maske und sind für Treiber für x64-Systeme nicht verfügbar. Weitere Informationen zu diesen Registern finden Sie unter Verwenden von Gleitkomma in einem WDM-Treiber.

SSE-Register

Diese Register entsprechen dem flag XSTATE_MASK_LEGACY_SSE und werden vom x64-Compiler für Gleitkommavorgänge verwendet. Treiber für x86-Systeme, die diese Register verwenden, müssen diese vor der Verwendung speichern, indem sie das XSTATE_MASK_LEGACY- oder XSTATE_MASK_LEGACY_SSE-Flag im KeSaveExtendedProcessorState-Aufruf übergeben und nach Abschluss mit KeRestoreExtendedProcessorState wiederherstellen. Dies ist auf x64-Systemen unnötig, aber nicht schädlich. Weitere Informationen zu diesen Registern finden Sie unter Verwenden von Gleitkomma in einem WDM-Treiber.

AVX-Register

Diese Register entsprechen den XSTATE_MASK_GSSE oder XSTATE_MASK_AVX Masken. Neue x86-Prozessoren, wie der Intel Sandy Bridge (ehemals Gesher) Prozessor, unterstützen die AVX-Anweisungen und register set (YMM0-YMM15). In Windows 7 mit Service Pack 1 (SP1), Windows Server 2008 R2 und neueren Versionen von Windows behalten sowohl x86- als auch x64-Versionen des Betriebssystems die AVX-Register über Thread- (und Prozessschalter) hinweg bei. Um die AVX-Register im Kernelmodus zu verwenden, müssen Treiber (x86 und x64) die AVX-Register explizit speichern und wiederherstellen. AVX-Register können nicht in einer Interruptdienstroutine verwendet werden, und arithmetische Ausnahmen sind standardmäßig deaktiviert.

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
Verwenden von Gleitkomma in einem WDM-Treiber