Compartir a través de


Uso de características de procesador extendidas en controladores de Windows

Última actualización

  • Julio de 2016

Los controladores de Windows para sistemas x86 y x64 que usan características de procesador extendidas deben encapsular cálculos de punto flotante entre llamadas a KeSaveExtendedProcessorState y KeRestoreExtendedProcessorState para evitar errores en aplicaciones simultáneas que podrían estar usando los registros.

Registros MMX/x87 heredados

Estos registros corresponden a la máscara de XSTATE_MASK_LEGACY_FLOATING_POINT y no están disponibles para los controladores de los sistemas x64. Para obtener más información sobre estos registros, vea Uso de punto flotante en un controlador WDM.

Registros de SSE

Estos registros corresponden a la marca XSTATE_MASK_LEGACY_SSE y los usa el compilador x64 para las operaciones de punto flotante. Los controladores de los sistemas x86 que usan estos registros deben guardarlos antes de usarlos pasando la marca XSTATE_MASK_LEGACY o XSTATE_MASK_LEGACY_SSE en la llamada KeSaveExtendedProcessorState y, cuando termine, restáurelos con KeRestoreExtendedProcessorState. Esto no es necesario en sistemas x64, pero no perjudiciales. Para obtener más información sobre estos registros, vea Uso de punto flotante en un controlador WDM.

Registros de AVX

Estos registros corresponden a las máscaras de XSTATE_MASK_GSSE o XSTATE_MASK_AVX. Nuevos procesadores x86, como el procesador Intel Sandy Bridge (anteriormente Gesher), admiten las instrucciones de AVX y el conjunto de registros (YMM0-YMM15). En Windows 7 con Service Pack 1 (SP1), Windows Server 2008 R2 y versiones más recientes de Windows, las versiones x86 y x64 del sistema operativo conservan los registros avX entre conmutadores de subproceso (y proceso). Para usar los registros avX en modo kernel, los controladores (x86 y x64) deben guardar y restaurar explícitamente los registros de AVX. Los registros AVX no se pueden usar en una rutina de servicio de interrupción y las excepciones aritméticas están desactivadas de forma predeterminada.

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
Uso de punto flotante en un controlador WDM