当您执行您的 CPU 不支持的指令时会发生什么?
What happens when you execute an instruction that your CPU does not support?
如果 CPU 试图执行使用您的 CPU 不支持的某些指令编译的二进制文件,会发生什么情况。我特别想知道旧处理器上的一些新 AVX 指令 运行。
我假设这可以进行测试,并且理论上可以向用户显示一条友好的消息。大概大多数低级图书馆会代表你检查这个。假设您没有进行此检查,您希望发生什么?您的进程会收到什么信号?
一条新指令可以设计成"legacy compatible"也可以不
前者 class 属于 tzcnt
或 xacquire
之类的指令,它们具有在旧架构中生成有效指令的编码:tzcnt
被编码为
rep bsf
和 xacquire
只是 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_trap
在 traps.c
force_sig_info
在 signal.c
specific_send_sig_info
在 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 +++
符合预期。
As , libraries don't usually rely on SIGILL, instead they use a CPU dispatcher 或明确检查指令是否存在。
如果 CPU 试图执行使用您的 CPU 不支持的某些指令编译的二进制文件,会发生什么情况。我特别想知道旧处理器上的一些新 AVX 指令 运行。
我假设这可以进行测试,并且理论上可以向用户显示一条友好的消息。大概大多数低级图书馆会代表你检查这个。假设您没有进行此检查,您希望发生什么?您的进程会收到什么信号?
一条新指令可以设计成"legacy compatible"也可以不
前者 class 属于 tzcnt
或 xacquire
之类的指令,它们具有在旧架构中生成有效指令的编码:tzcnt
被编码为
rep bsf
和 xacquire
只是 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_trap
在 traps.c
force_sig_info
在 signal.c
specific_send_sig_info
在 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 +++
符合预期。
As