Menggunakan Floating Point dalam Driver WDM
Terakhir diperbarui
- Juli 2016
Driver WDM mode kernel untuk Windows harus mengikuti panduan tertentu saat menggunakan operasi floating-point. Ini berbeda antara sistem x86 dan x64. Secara default, Windows menonaktifkan pengecualian aritmatika untuk kedua sistem.
Sistem x86
Driver WDM mode kernel untuk sistem x86 harus membungkus penggunaan perhitungan titik mengambang antara panggilan ke KeSaveExtendedProcessorState dan KeRestoreExtendedProcessorState. Operasi floating point harus ditempatkan dalam sub-rutin non-sebaris untuk memastikan bahwa perhitungan titik mengambang tidak dilakukan sebelum memeriksa nilai pengembalian KeSaveExtendedProcessorState karena penyusunan ulang kompilator.
Kompilator menggunakan MMX/x87 juga dikenal sebagai register unit floating-point (FPU) untuk perhitungan tersebut, yang dapat digunakan secara bersamaan oleh aplikasi mode pengguna. Kegagalan untuk menyimpan register ini sebelum menggunakannya, atau gagal memulihkannya setelah selesai, dapat menyebabkan kesalahan perhitungan dalam aplikasi.
Driver untuk sistem x86 dapat memanggil KeSaveExtendedProcessorState dan melakukan perhitungan titik mengambang di IRQL <= DISPATCH_LEVEL. Operasi floating-point tidak didukung dalam rutinitas layanan interupsi (ISR) pada sistem x86.
Sistem x64
Pengkompilasi 64-bit tidak menggunakan register MMX/x87 untuk operasi floating point. Sebaliknya, ia menggunakan register SSE. Kode mode kernel x64 tidak diizinkan untuk mengakses register MMX/x87. Kompilator juga mengurus penyimpanan dan pemulihan status SSE dengan benar, oleh karena itu, panggilan ke KeSaveExtendedProcessorState dan KeRestoreExtendedProcessorState tidak perlu dan operasi floating point dapat digunakan dalam ISR. Penggunaan fitur prosesor tambahan lainnya seperti AVX, memerlukan penyimpanan dan pemulihan status yang diperluas. Untuk informasi selengkapnya lihat Menggunakan fitur prosesor yang diperluas di driver Windows.
Catatan: Arm64 secara umum, mirip dengan AMD64 karena Anda tidak perlu memanggil status simpan titik mengambang terlebih dahulu. Namun, kode yang perlu portabel hingga x86 pada kernel mungkin masih perlu melakukan itu untuk menjadi lintas platform.
Contoh
Contoh berikut menunjukkan bagaimana driver WDM harus membungkus akses FPU-nya:
__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;
}
Dalam contoh, penugasan ke variabel floating-point terjadi antara panggilan ke KeSaveExtendedProcessorState dan KeRestoreExtendedProcessorState. Karena setiap penugasan ke variabel floating-point menggunakan FPU, driver harus memastikan bahwa KeSaveExtendedProcessorState telah dikembalikan tanpa kesalahan sebelum menginisialisasi variabel seperti itu.
Panggilan sebelumnya tidak perlu pada sistem x64 dan tidak berbahaya ketika bendera XSTATE_MASK_LEGACY ditentukan. Oleh karena itu, tidak perlu mengubah kode saat mengkompilasi driver untuk sistem x64.
Pada sistem berbasis x86, FPU direset ke status defaultnya dengan panggilan ke FNINIT, setelah dikembalikan dari KeSaveExtendedProcessorState.