我试图确定一种检测英特尔和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
答案 0 :(得分:5)
首先是一点理论。
为了使用AVX指令集,必须满足几个条件:
.gitignore
必须为1.
该标志由OS设置,以向处理器发出信号,表明它支持CR4.OSXSAVE[bit 18]
扩展
xsave
扩展是保存AVX状态的唯一方法(xsave
不保存fxsave
寄存器),因此操作系统必须支持它们。
ymm
和XCR0.SSE[bit 1]
必须为1.
这些标志由操作系统设置,以通知处理器它支持保存和恢复SSE和AVX状态(通过XCR0.AVX[bit 2]
)。
xsave
当然,处理器必须首先支持AVX扩展。
所有这些寄存器都是用户模式可读的,但适用于CPUID.1:ECX.AVX[bit 28] = 1
幸运的是,位CR4
反映在CR4.OSXSAVE
中,因此所有信息都是用户模式可访问的。
没有特权指示。
要使用AVX扩展程序,必须同时提供硬件(CPUID.1:ECX.OSXSAVE[bit 27]
和CPUID.1:ECX.AVX
)和操作系统(CPUID.1:ECX.XSAVE
,CPUID.1:ECX.OSXSAVE
和XCR0.SSE
)支持。
由于OS仅在存在硬件支持的情况下发出对XCR0.AVX
的支持信号,因此测试前者就足够了
对于AVX扩展,仍建议测试xsave
,因为即使不支持AVX,操作系统也可能设置CPUID.1:ECX.AVX
。
这导致英特尔官方强烈推荐的算法:
与您发布的完全相同。
捕获异常以检测对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
也可以。