执行CPU不支持的指令时会发生什么?
如果CPU尝试执行已使用某些CPU不支持的指令编译的二进制文件,会发生什么情况。我特别想知道一些在旧处理器上运行的新AVX指令。执行CPU不支持的指令时会发生什么?
我假设这可以进行测试,友好的消息理论上可以显示给用户。据推测,大多数低级别的图书馆都会代您进行检查。假设你没有做这个检查,你会期望发生什么?您的流程会收到什么信号?
新指令可以设计为“传统兼容”或不能。
对于前者类属于指令像tzcnt
或xacquire
有产生老年架构有效指令编码:tzcnt
被编码为 rep bsf
和xacquire
只是repne
。
语义当然不同。
第二类属于大部分新指令,AVX就是一个流行的例子。
当CPU遇到无效的或保留的编码它生成#UD(对于未定义)异常 - 这是中断号6.
的Linux内核entry_64.S
设置#UD的IDT条目初:
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_trap
在traps.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或检查的指令的存在明确。
[信号'SIGILL'是什么?](https://*.com/q/7901867/608639)和朋友。据我所知,在所有Linux平台上,包括i386,x86_64,ARM,Aarch32,Aarch64和MIPS都会引发SIGILL。 – jww
*“大概最底层的图书馆会代您检查。”*呃,我不这么认为。大多数使用潜在不受支持指令的低级库在速度上高于一切。在调用低级代码之前,高级代码负责验证这些指令是否受支持。在执行它们之前,使用'CPUID'指令(在大多数编译器中作为内部函数公开)来验证是否支持所需的指令集,从而避免出现无效指令异常的风险。然后显示友好的错误消息。 –
停止并着火。 –