다음을 통해 공유


Windows 드라이버에서 확장 프로세서 기능 사용

마지막 업데이트

  • 2016년 7월

확장 프로세서 기능을 사용하는 x86 및 x64 시스템의 Windows 드라이버는 레지스터를 사용할 수 있는 동시 애플리케이션의 오류를 방지하기 위해 KeSaveExtendedProcessorStateKeRestoreExtendedProcessorState 호출 간에 부동 소수점 계산을 래핑해야 합니다.

레거시 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 SP1(서비스 팩 1), 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 드라이버에서 부동 소수점 사용