Détection de fonctionnalités AVX à l’aide de SIGILL par rapport à la détection du processeur

J’essaie de déterminer une méthode efficace pour détecter la disponibilité d’AVX et d’AVX2 sur les processeurs Intel et AMD. J’ai été un peu surpris d’apprendre qu’il était plus proche de SSE et de XSAVE lors de la lecture du volume I du Manuel du développeur Intel , Manuel Gérer l’état avec le jeu de fonctionnalités XSAVE , p.

Intel publie du code permettant de détecter la disponibilité d’AVX sur AVX est-il activé? Le code est montré ci-dessous et ce n’est pas trop douloureux. Le problème est que Visual Studio est un point difficile car nous devons déplacer le code des fichiers C / C ++ vers les fichiers ASM pour X64.

D’autres semblent adopter l’approche SIGILL pour détecter la disponibilité d’AVX. Ou bien ils utilisent involontairement la méthode SIGILL . Voir, par exemple, l’ instruction SIGILL sur AVX .

Ma question est la suivante: est-il prudent d’utiliser la méthode SIGILL pour détecter la disponibilité d’AVX? Ici, “sûr” signifie qu’une instruction AVX ne générera pas de SIGILL lorsque la CPU et le système d’exploitation prennent en charge AVX; et sinon, cela générera un SIGILL .


Le code ci-dessous est destiné aux ordinateurs 32 bits et provient du blog d’Intel. AVX est-il activé? Ce qui me préoccupe, c’est de manipuler les registres de contrôle. La lecture et l’écriture de certains registres de contrôle X86 et ARM nécessitent parfois des privilèges de super utilisateur / administrateur. C’est la raison pour laquelle je préfère un SIGILL (et évite les registres de contrôle).

 ; int isAvxSupported(); isAvxSupported proc xor eax, eax cpuid cmp eax, 1 ; does CPUID support eax = 1? jb not_supported mov eax, 1 cpuid and ecx, 018000000h ; check 27 bit (OS uses XSAVE/XRSTOR) cmp ecx, 018000000h ; and 28 (AVX supported by CPU) jne not_supported xor ecx, ecx ; XFEATURE_ENABLED_MASK/XCR0 register number = 0 xgetbv ; XFEATURE_ENABLED_MASK register is in edx:eax and eax, 110b cmp eax, 110b ; check the AVX registers restore at context switch jne not_supported supported: mov eax, 1 ret not_supported: xor eax, eax ret isAvxSupported endp 

Un peu de théorie d’abord.

Pour pouvoir utiliser les instructions AVX, quelques conditions doivent être remplies:

  1. CR4.OSXSAVE[bit 18] doit être 1.
    Cet indicateur est défini par le système d’exploitation pour signaler au processeur qu’il prend en charge les extensions xsave .
    Les extensions xsave sont le seul moyen de sauvegarder l’état AVX ( fxsave n’enregistre pas les registres ymm ) et le système d’exploitation doit donc les prendre en charge.

  2. XCR0.SSE[bit 1] et XCR0.AVX[bit 2] doivent être 1.
    Ces indicateurs sont définis par le système d’exploitation pour signaler au processeur qu’il prend en charge l’enregistrement et la restauration des états SSE et AVX (via xsave ).

  3. CPUID.1:ECX.AVX[bit 28] = 1
    Bien entendu, le processeur doit d’abord prendre en charge les extensions AVX.

Tous ces registres sont lisibles en mode utilisateur, sauf pour CR4 .
Heureusement, le bit CR4.OSXSAVE est reflété dans CPUID.1:ECX.OSXSAVE[bit 27] et toutes les informations sont donc accessibles en mode utilisateur. Aucune instruction privilégiée n’est impliquée.

Pour pouvoir utiliser les extensions AVX, une prise en charge matérielle ( CPUID.1:ECX.AVX et CPUID.1:ECX.XSAVE ) et OS ( CPUID.1:ECX.OSXSAVE , XCR0.SSE et XCR0.AVX ) doit être présente.
Étant donné que le système d’exploitation signale sa prise en charge de xsave uniquement en présence de la prise en charge matérielle, le test de cette dernière suffit.
CPUID.1:ECX.AVX est toujours recommandé de tester CPUID.1:ECX.AVX pour les extensions AVX, car le système d’exploitation peut définir XCR0.AVX même si AVX n’est pas pris en charge.

Cela conduit à l’algorithme officiel d’Intel, vivement recommandé:

Algorithme officiel Intel pour la détection AVX. Section 14.3 du manuel 1

qui est exactement le même que vous avez posté.


Attraper des exceptions pour détecter la prise en charge des extensions AVX permettra également de garantir que l’exception interceptée est #UD .
Par exemple, en exécutant vzeroall les seules exceptions possibles sont #UD et #NM .
Le premier est lancé seulement quand:

Si XCR0 [2: 1] ’11b’.
Si CR4.OSXSAVE [bit 18] = 0.
Si CPUID.01H.ECX.AVX [bit 28] = 0.
Si VEX.vvvv ≠ 1111B.

Donc, sauf si vous avez un assembleur / compilateur cassé, cela correspond exactement aux conditions énoncées au début.

Ce dernier est utilisé comme une optimisation pour enregistrer l’état AVX et n’est donc pas exposé aux programmes en mode utilisateur par le système d’exploitation.

De ce fait, attraper SIGILL sur vzeroall ou similaire ferait également l’affaire.