Uso della virgola mobile in un driver WDM
Ultimo aggiornamento
- Luglio 2016
I driver WDM in modalità kernel per Windows devono seguire determinate linee guida quando si usano operazioni a virgola mobile. Queste differenze variano tra sistemi x86 e x64. Per impostazione predefinita, Windows disattiva le eccezioni aritmetiche per entrambi i sistemi.
Sistemi x86
I driver WDM in modalità kernel per sistemi x86 devono eseguire il wrapping dell'uso di calcoli a virgola mobile tra le chiamate a KeSaveExtendedProcessorState e KeRestoreExtendedProcessorState. Le operazioni a virgola mobile devono essere inserite in una subroutine non inline per assicurarsi che i calcoli a virgola mobile non vengano eseguiti prima di controllare il valore restituito di KeSaveExtendedProcessorState a causa del riordinamento del compilatore.
Il compilatore usa MMX/x87 noto anche come registri di unità a virgola mobile (FPU) per tali calcoli, che possono essere usati simultaneamente da un'applicazione in modalità utente. Se non si salvano questi registri prima di usarli o non è possibile ripristinarli al termine, possono causare errori di calcolo nelle applicazioni.
I driver per sistemi x86 possono chiamare KeSaveExtendedProcessorState ed eseguire calcoli a virgola mobile in IRQL <= DISPATCH_LEVEL. Le operazioni a virgola mobile non sono supportate nelle routine del servizio di interrupt (ISR) nei sistemi x86.
Sistemi x64
Il compilatore a 64 bit non usa i registri MMX/x87 per le operazioni a virgola mobile. Usa invece i registri della crittografia del servizio di archiviazione. Il codice in modalità kernel x64 non è autorizzato ad accedere ai registri MMX/x87. Il compilatore si occupa anche del corretto salvataggio e del ripristino dello stato della crittografia del servizio di archiviazione, pertanto le chiamate a KeSaveExtendedProcessorState e KeRestoreExtendedProcessorState non sono necessarie e le operazioni a virgola mobile possono essere usate nelle richieste isr. L'uso di altre funzionalità del processore estese, ad esempio AVX, richiede il salvataggio e il ripristino dello stato esteso. Per altre informazioni, vedere Uso delle funzionalità estese del processore nei driver di Windows.
Nota: Arm64 in generale, è simile a AMD64 in quanto non è necessario chiamare prima salva stato a virgola mobile. Tuttavia, il codice che deve essere portabile a x86 nei kernel potrebbe comunque dover eseguire questa operazione per essere multipiattaforma.
Esempio
L'esempio seguente mostra come un driver WDM deve eseguire il wrapping dell'accesso 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;
}
Nell'esempio, l'assegnazione alla variabile a virgola mobile avviene tra le chiamate a KeSaveExtendedProcessorState e KeRestoreExtendedProcessorState. Poiché qualsiasi assegnazione a una variabile a virgola mobile usa la FPU, i driver devono assicurarsi che KeSaveExtendedProcessorState abbia restituito senza errori prima di inizializzare tale variabile.
Le chiamate precedenti non sono necessarie in un sistema x64 e innocue quando viene specificato il flag di XSTATE_MASK_LEGACY. Non è quindi necessario modificare il codice durante la compilazione del driver per un sistema x64.
Nei sistemi basati su x86, la FPU viene reimpostata sullo stato predefinito da una chiamata a FNINIT, al ritorno da KeSaveExtendedProcessorState.