Partager via


Utilisation des fonctionnalités de processeur étendues dans les pilotes Windows

Dernière mise à jour

  • Juillet 2016

Les pilotes Windows pour les systèmes x86 et x64 qui utilisent des fonctionnalités de processeur étendues doivent encapsuler les calculs à virgule flottante entre les appels à KeSaveExtendedProcessorState et KeRestoreExtendedProcessorState afin d’éviter les erreurs dans les applications simultanées qui peuvent utiliser les registres.

Registres MMX/x87 hérités

Ces registres correspondent au masque XSTATE_MASK_LEGACY_FLOATING_POINT et ne sont pas disponibles pour les pilotes pour les systèmes x64. Pour plus d’informations sur ces registres, consultez Utilisation de virgule flottante dans un pilote WDM.

Registres SSE

Ces registres correspondent à l’indicateur XSTATE_MASK_LEGACY_SSE et sont utilisés par le compilateur x64 pour les opérations à virgule flottante. Les pilotes pour les systèmes x86 qui utilisent ces registres doivent les enregistrer avant de les utiliser en passant l’indicateur XSTATE_MASK_LEGACY ou XSTATE_MASK_LEGACY_SSE dans l’appel KeSaveExtendedProcessorState et, lorsque vous avez terminé, les restaurer avec KeRestoreExtendedProcessorState. Cela n’est pas nécessaire sur les systèmes x64, mais pas dangereux. Pour plus d’informations sur ces registres, consultez Utilisation de virgule flottante dans un pilote WDM.

Registres AVX

Ces registres correspondent aux masques XSTATE_MASK_GSSE ou XSTATE_MASK_AVX. Les nouveaux processeurs x86, tels que le processeur Intel Sandy Bridge (anciennement Gesher), prennent en charge les instructions AVX et l’ensemble d’inscriptions (YMM0-YMM15). Dans Windows 7 avec Service Pack 1 (SP1), Windows Server 2008 R2 et les versions plus récentes de Windows, les versions x86 et x64 du système d’exploitation conservent les registres AVX sur les commutateurs de thread (et de processus). Pour utiliser les registres AVX en mode noyau, les pilotes (x86 et x64) doivent enregistrer et restaurer explicitement les registres AVX. Les registres AVX ne peuvent pas être utilisés dans une routine de service d’interruption, et les exceptions arithmétiques sont désactivées par défaut.

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
Utilisation de virgule flottante dans un pilote WDM