如何为独立的可引导代码启用 SSE?

How do I enable SSE for my freestanding bootable code?

(这个问题最初是关于 CVTSI2SD 指令的,我认为它在 Pentium M CPU 上不起作用,但实际上是因为我使用的是自定义指令OS 而且我需要手动启用 SSE。)

我有一个 Pentium M CPU 和一个自定义的 OS,到目前为止还没有使用 SSE 指令,但我现在需要使用它们。

尝试执行任何 SSE 指令会导致中断 6,非法操作码(在 Linux 中会导致 SIGILL,但这不是 Linux),也提到在 Intel architectures software developer's manual(我从现在开始将其称为 IASDM)中作为 #UD - 无效操作码(未定义的操作码).

编辑:Peter Cordes 实际上找到了正确的原因,并指出了解决方案,我在下面继续:

If you're running an ancient OS that doesn't support saving XMM regs on context switches, the SSE-enabling bit in one of the machine control registers won't be set.

的确,IASDM 提到了这一点:

If an operating system did not provide adequate system level support for SSE, executing an SSE or SSE2 instructions can also generate #UD.

Peter Cordes 向我指出 SSE OSDev wiki,它描述了如何通过写入 CR0CR4 控制寄存器来启用 SSE:

clear the CR0.EM bit (bit 2) [ CR0 &= ~(1 << 2) ]
set the CR0.MP bit (bit 1) [ CR0 |= (1 << 1) ]
set the CR4.OSFXSR bit (bit 9) [ CR4 |= (1 << 9) ]
set the CR4.OSXMMEXCPT bit (bit 10) [ CR4 |= (1 << 10) ]

请注意,为了能够写入这些寄存器,如果您处于保护模式,那么您需要处于特权级别 0。 解释了如何测试它:如果处于保护模式模式,即当 CR0 中的位 0 (PE) 设置为 1 时,您可以从 CS 选择器中测试位 0 和 1,它们应该都是 0.

最后,自定义 OS 必须在上下文切换期间正确处理 XMM 寄存器,在必要时保存和恢复它们。

有此类问题建议您咨询Intel's manual

说明书上写的很清楚CVTSI2SD是SSE2指令

如果您运行使用不支持在上下文切换时保存 XMM regs 的古老或自定义 OS,它不会在机器中设置 SSE 启用位控制寄存器。在这种情况下,所有涉及 xmm regs 的指令都会出错。

我花了一些时间才找到,但 http://wiki.osdev.org/SSE 解释了如何更改 CR0 和 CR4 以允许 SSE 指令在没有 #UD.

的裸机上 运行

我对你的旧版本问题的第一个想法是 你可能已经用 -mavx-march=sandybridge 或等价物编译你的程序,导致编译器发出所有内容的 VEX 编码版本。

CVTSI2SD   xmm1, xmm2/m32         ; SSE2
VCVTSI2SD  xmm1, xmm2, xmm3/m32   ; AVX

请参阅 https://whosebug.com/tags/x86/info 获取链接,包括 Intel 的 insn set ref 手册。


相关: 有一些关于如何检查对 AVX 和 AVX512 的支持的细节(这也引入了新的架构状态,所以 OS 必须设置一点,否则硬件会出错).它是从另一个角度来的,但链接应该指示如何激活/禁用 AVX 支持。