如何为独立的可引导代码启用 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,它描述了如何通过写入 CR0
和 CR4
控制寄存器来启用 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 支持。
(这个问题最初是关于 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,它描述了如何通过写入 CR0
和 CR4
控制寄存器来启用 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 手册。
相关: