Share via


WDM 드라이버에서 부동 소수점 사용

마지막 업데이트

  • 2016년 7월

Windows용 커널 모드 WDM 드라이버는 부동 소수점 작업을 사용할 때 특정 지침을 따라야 합니다. x86 및 x64 시스템 간에 다릅니다. 기본적으로 Windows는 두 시스템 모두에 대한 산술 예외를 해제합니다.

x86 시스템

x86 시스템의 커널 모드 WDM 드라이버는 KeSaveExtendedProcessorStateKeRestoreExtendedProcessorState 호출 간에 부동 소수점 계산 사용을 래핑해야 합니다. 부동 소수점 작업은 컴파일러 다시 정렬로 인해 KeSaveExtendedProcessorState 의 반환 값을 확인하기 전에 부동 소수점 계산이 수행되지 않도록 비인라인 서브루틴에 배치해야 합니다.

컴파일러는 사용자 모드 애플리케이션에서 동시에 사용할 수 있는 이러한 계산을 위해 FPU(부동 소수점 단위) 레지스터라고도 하는 MMX/x87을 사용합니다. 이러한 레지스터를 사용하기 전에 저장하지 못하거나 완료되면 복원하지 못하면 애플리케이션에서 계산 오류가 발생할 수 있습니다.

x86 시스템용 드라이버는 KeSaveExtendedProcessorState 를 호출하고 IRQL <= DISPATCH_LEVEL 부동 소수점 계산을 수행할 수 있습니다. 부동 소수점 작업은 x86 시스템의 ISR(인터럽트 서비스 루틴)에서 지원되지 않습니다.

x64 시스템

64비트 컴파일러는 부동 소수점 작업에 MMX/x87 레지스터를 사용하지 않습니다. 대신 SSE 레지스터를 사용합니다. x64 커널 모드 코드는 MMX/x87 레지스터에 액세스할 수 없습니다. 또한 컴파일러는 SSE 상태를 적절히 저장하고 복원하므로 KeSaveExtendedProcessorStateKeRestoreExtendedProcessorState 에 대한 호출은 불필요하며 ISR에서 부동 소수점 작업을 사용할 수 있습니다. AVX와 같은 다른 확장 프로세서 기능을 사용하려면 확장 상태를 저장하고 복원해야 합니다. 자세한 내용은 Windows 드라이버에서 확장 프로세서 기능 사용을 참조하세요.

참고: 일반적으로 Arm64는 먼저 부동 소수점 저장 상태를 호출할 필요가 없다는 점에서 AMD64와 유사합니다. 그러나 커널에서 x86으로 이식할 수 있어야 하는 코드는 플랫폼 간이어야 할 수 있습니다.

예제

다음 예제에서는 WDM 드라이버가 FPU 액세스를 래핑하는 방법을 보여 줍니다.

__declspec(noinline)
VOID
DoFloatingPointCalculation(
    VOID
    )
{
    double Duration;
    LARGE_INTEGER Frequency;

    Duration = 1000000.0;
    DbgPrint("%I64x\n", *(LONGLONG*)&Duration);
    KeQueryPerformanceCounter(&Frequency);
    Duration /= (double)Frequency.QuadPart;
    DbgPrint("%I64x\n", *(LONGLONG*)&Duration);
}

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{

    XSTATE_SAVE SaveState;
    NTSTATUS Status;

    Status = KeSaveExtendedProcessorState(XSTATE_MASK_LEGACY, &SaveState);
    if (!NT_SUCCESS(Status)) {
        goto exit;
    }

    __try {
        DoFloatingPointCalculation();
    }
    __finally {
        KeRestoreExtendedProcessorState(&SaveState);
    }

exit:
    return Status;
}

이 예제에서 부동 소수점 변수에 대한 할당은 KeSaveExtendedProcessorStateKeRestoreExtendedProcessorState 호출 간에 발생합니다. 부동 소수점 변수에 대한 할당은 FPU를 사용하므로 드라이버는 이러한 변수를 초기화하기 전에 KeSaveExtendedProcessorState 가 오류 없이 반환되었는지 확인해야 합니다.

위의 호출은 x64 시스템에서 불필요하며 XSTATE_MASK_LEGACY 플래그를 지정할 때 무해합니다. 따라서 x64 시스템에 대한 드라이버를 컴파일할 때 코드를 변경할 필요가 없습니다.

x86 기반 시스템에서 FPU는 KeSaveExtendedProcessorState에서 반환될 때 FNINIT를 호출하여 기본 상태로 다시 설정됩니다.