执行CPU不支持的指令时会发生什么?

问题描述:

如果CPU尝试执行已使用某些CPU不支持的指令编译的二进制文件,会发生什么情况。我特别想知道一些在旧处理器上运行的新AVX指令。执行CPU不支持的指令时会发生什么?

我假设这可以进行测试,友好的消息理论上可以显示给用户。据推测,大多数低级别的图书馆都会代您进行检查。假设你没有做这个检查,你会期望发生什么?您的流程会收到什么信号?

+1

[信号'SIGILL'是什么?](https://*.com/q/7901867/608639)和朋友。据我所知,在所有Linux平台上,包括i386,x86_64,ARM,Aarch32,Aarch64和MIPS都会引发SIGILL。 – jww

+0

*“大概最底层的图书馆会代您检查。”*呃,我不这么认为。大多数使用潜在不受支持指令的低级库在速度上高于一切。在调用低级代码之前,高级代码负责验证这些指令是否受支持。在执行它们之前,使用'CPUID'指令(在大多数编译器中作为内部函数公开)来验证是否支持所需的指令集,从而避免出现无效指令异常的风险。然后显示友好的错误消息。 –

+1

停止并着火。 –

新指令可以设计为“传统兼容”或不能。
对于前者类属于指令像tzcntxacquire有产生老年架构有效指令编码:tzcnt被编码为 rep bsfxacquire只是repne
语义当然不同。

第二类属于大部分新指令,AVX就是一个流行的例子。
当CPU遇到无效的或保留的编码它生成#UD(对于未定义)异常 - 这是中断号6.

的Linux内核entry_64.S设置#UDIDT条目初:

idtentry invalid_op   do_invalid_op   has_error_code=0 

的入口点do_invalid_op,其与宏traps.c生成:

DO_ERROR(X86_TRAP_UD,  SIGILL, "invalid opcode",  invalid_op) 

DO_ERROR生成一个函数,该函数在同一个文件(here)中调用do_error_trap

do_traptraps.c force_sig_info中:

do_error_trap使用fill_trap_info(在同一个文件,here)创建包含Linux的信号的信息的siginfo_t结构:

case X86_TRAP_UD: 
    sicode = ILL_ILLOPN; 
    siaddr = uprobe_get_trap_addr(regs); 
    break; 

从那里下面的调用发生signal.c specific_send_sig_info in signal.c

最终在调用违规流程的SIGILL的信号处理程序时达到高潮。


下面的程序是一个非常简单的例子,其产生#UD

BITS 64 

GLOBAL _start 

SECTION .text 

_start: 

ud2 

我们可以使用strace来检查通过运行程序接收到的信号

--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x400080} --- 
+++ killed by SIGILL +++ 

如预期。


作为Cody Gray commented,图书馆通常不依靠SIGILL,相反,他们使用一个CPU dispatcher或检查的指令的存在明确。