Éviter les erreurs à virgule flottante dans les environnements de build personnalisés

Ces informations sont destinées aux développeurs et aux ingénieurs de build qui compilent des pilotes en mode noyau pour Windows. Dans Microsoft Visual Studio Professional 2012, l’architecture par défaut du compilateur Visual C++ (VC++) est passée de IA32 au jeu d’instructions Streaming SIMD Extensions 2 (SSE2). À la suite de cette modification, les instructions SSE2 à virgule flottante (FP) injectées dans le fichier binaire au moment de la compilation peuvent générer des erreurs à virgule flottante si elles ne sont pas prises en compte. Le problème peut être rencontré par ceux qui utilisent le compilateur Microsoft VC++ ou un environnement de build personnalisé pour développer des pilotes Windows. Toutefois, le problème n’affecte pas les développeurs qui utilisent l’environnement de développement Microsoft Visual Studio ou qui utilisent l’utilitaire MSbuild pour générer des pilotes avec un ensemble d’outils non modifié.

Les erreurs à virgule flottante peuvent entraîner une altération des données ou des pannes d’ordinateur

Si vous compilez un pilote sans utiliser WDK, Visual Studio et l’ensemble d’outils de plateforme recommandé pour les pilotes Windows (WindowsKernelModeDriver8.0), le pilote risque de ne pas gérer correctement les opérations à virgule flottante, même si le pilote se compile sans erreurs.

Le compilateur VC++ Visual Studio Professional 2012 émet du code qui utilise le jeu d’instructions SSE2 en définissant l’option de compilateur /arch:sse2. À compter de Visual Studio Professional 2012, il s’agit de l’option par défaut pour la génération de code du compilateur VC++ x86. Plus précisément, la valeur par défaut passe de /arch:ia32 à /arch:sse2.

Pour les applications, cette modification génère du code qui fonctionne mieux et utilise moins de temps processeur pendant l’exécution. Toutefois, pour les pilotes en mode noyau, cette modification ne gère pas correctement l’état à virgule flottante (FP). Cela est dû au fait que le compilateur VC++ introduit des séquences d’instructions FP dans des endroits où le contexte n’a pas été enregistré. Tout système à virgule flottante binaire ne peut représenter qu’un nombre fini de valeurs à virgule flottante sous forme exacte, le reste étant des approximations. L’état de contrôle à virgule flottante, tel que le mode d’arrondi ou la précision, permet de maintenir la synchronisation des opérations FP les unes avec les autres. Lorsque l’état n’est pas défini, cela entraîne des erreurs de calcul fp. Ces erreurs de calcul sont difficiles à détecter, car dans la plupart des cas, la corruption de l’état de l’application est le seul signe de ce problème. Cette corruption peut se manifester de plusieurs façons, allant des incidents aléatoires à l’altération des données.

Solution

Pour éviter ce problème avec les calculs à virgule flottante, ajoutez l’indicateur /kernel aux lignes de commande du compilateur C++ et de l’éditeur de liens pour empêcher la génération d’instructions SSE2. L’indicateur /kernel remplace la valeur par défaut /arch:sse2 par /arch:ia32.

En outre, si vous générez un pilote à l’aide de WDK et de l’environnement de développement Visual Studio Professional 2012, ou que vous utilisez MSBuild, dans une fenêtre d’invite de commandes Visual Studio, l’ensemble d’outils de plateforme fourni par Microsoft (WindowsKernelModeDriver8.0) définit l’indicateur /kernel. Par conséquent, les erreurs de génération à virgule flottante sont évitées.

msbuild myProject.vcxproj /p:PlatformToolset=WindowsKernelModeDriver8.0

Recommandations

Voici les solutions recommandées en fonction du type d’environnement de développement que vous utilisez :

  • Ensemble d’outils Microsoft (MSBuild) : aucun travail n’est nécessaire. Utilisez WindowsKernelModeDriver8.0 comme ensemble d’outils de plateforme le /kernel est automatiquement ajouté le cas échéant.
  • Compilateur Microsoft VC++ : ajoutez l’indicateur /kernel pour empêcher le compilateur d’émettre SSE2.
  • Outils personnalisés/compilateur non-Microsoft : vous devez prendre en compte manuellement les instructions d’assembly utilisées dans le fichier binaire résultant.