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

What happens when you execute an instruction that your CPU does not support?

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

我假设这可以进行测试,并且理论上可以向用户显示一条友好的消息。大概大多数低级图书馆会代表你检查这个。假设您没有进行此检查,您希望发生什么?您的进程会收到什么信号?

一条新指令可以设计成"legacy compatible"也可以不
前者 class 属于 tzcntxacquire 之类的指令,它们具有在旧架构中生成有效指令的编码:tzcnt 被编码为 rep bsfxacquire 只是 repne.
语义当然不同。

第二个 class 属于大多数新指令,AVX 是一个流行的例子。
当 CPU 遇到无效或保留编码时,它会生成 #UD(对于 UnDefined)异常 - 这是中断号 6。

Linux内核设置IDT entry for #UD early in entry_64.S:

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_error_trap使用fill_trap_info(在同一个文件中,here)创建一个包含Linux信号信息的siginfo_t结构:

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

从那里发生以下呼叫:

do_traptraps.c force_sig_infosignal.c specific_send_sig_infosignal.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 +++

符合预期。


As , libraries don't usually rely on SIGILL, instead they use a CPU dispatcher 或明确检查指令是否存在。