使用SIGILL与CPU探测进行AVX功能检测

时间:2017-05-23 20:51:03

标签: c assembly avx

我试图确定一种检测英特尔和AMD处理器上AVX和AVX2可用性的有效方法。在阅读英特尔软件开发人员手册,第I卷(使用XSAVE功能集管理状态,第310页)时,我更加惊讶地发现它更接近SSE和XSAVE )。

英特尔在{{3}}发布了一些用于检测AVX可用性的代码。代码如下所示,并且不会太痛苦。问题是,Visual Studio是一个痛点,因为我们需要将代码从C / C ++文件中移出到X64的ASM文件中。

其他人似乎采用SIGILL方法来检测AVX可用性。或者他们无意中使用SIGILL方法。例如,请参阅{{3}}。

我的问题是,使用SIGILL方法检测AVX可用性是否安全?这里," safe" 表示当CPU和OS支持AVX时,AVX指令生成SIGILL;否则会生成SIGILL

以下代码适用于32位计算机及其来自英特尔博客{{3}}。令我担心的是操纵控制寄存器。读取和写入某些X86和ARM控制寄存器有时需要超级用户/管理员权限。这是我更喜欢SIGILL(并避免控制寄存器)的原因。

; 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

1 个答案:

答案 0 :(得分:5)

首先是一点理论。

为了使用AVX指令集,必须满足几个条件:

  1. .gitignore必须为1.
    该标志由OS设置,以向处理器发出信号,表明它支持CR4.OSXSAVE[bit 18]扩展 xsave扩展是保存AVX状态的唯一方法(xsave不保存fxsave寄存器),因此操作系统必须支持它们。

  2. ymmXCR0.SSE[bit 1]必须为1.
    这些标志由操作系统设置,以通知处理器它支持保存和恢复SSE和AVX状态(通过XCR0.AVX[bit 2])。

  3. xsave
    当然,处理器必须首先支持AVX扩展。

  4. 所有这些寄存器都是用户模式可读的,但适用于CPUID.1:ECX.AVX[bit 28] = 1 幸运的是,位CR4反映在CR4.OSXSAVE中,因此所有信息都是用户模式可访问的。 没有特权指示。

    要使用AVX扩展程序,必须同时提供硬件(CPUID.1:ECX.OSXSAVE[bit 27]CPUID.1:ECX.AVX)和操作系统(CPUID.1:ECX.XSAVECPUID.1:ECX.OSXSAVEXCR0.SSE)支持。
    由于OS仅在存在硬件支持的情况下发出对XCR0.AVX的支持信号,因此测试前者就足够了 对于AVX扩展,仍建议测试xsave,因为即使不支持AVX,操作系统也可能设置CPUID.1:ECX.AVX

    这导致英特尔官方强烈推荐的算法:

    Official Intel algorithm for AVX detection. Section 14.3 of manual 1

    与您发布的完全相同。

    捕获异常以检测对AVX扩展的支持也将被授予您可以保证捕获的异常是 #UD
    例如,通过执行XCR0.AVX,唯一可能的例外是 #UD #NM 。 第一个只在以下情况下抛出:

      

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

    因此,除非您的汇编程序/编译器损坏,否则它完全等同于开头所述的条件。

    后者被抛出作为保存AVX状态的优化,因此,它不会被操作系统暴露给用户模式程序。

    因此,在vzeroall或类似内容上抓取SIGILL也可以。