在 x86 上发送 IPI 后内存写入是否可见?

unt*_*led 6 x86 assembly operating-system memory-barriers msr

我读过《Intel 64 and IA-32 Architectures SDM vol 3A, 9.2 MEMORY ORDERING》,但有一个问题一直困扰着我。

如果我首先写入内存地址,然后使用 x2APIC 发送处理器间中断(IPI),这意味着发送 IPI 不需要写入内存(只需使用 wrmsr)。另一个核心接收IPI并读取内存,它会读取正确的值吗?

例如:

最初 x = 0

处理器0:

mov [ _x], 1
wrmsr       # use x2APIC to send IPI
Run Code Online (Sandbox Code Playgroud)

处理器1:

# resive IPI, in the interrupt service routine:
mov r1, [ _x]
Run Code Online (Sandbox Code Playgroud)

r1 = 0 允许吗?

Jes*_*ter 3

这是一个有趣的问题。从表面上看,人们会认为,由于WRMSR是一条序列化指令,它会刷新前面的内存写入,一切都很好。即使如此,引用手册:

这些指令强制处理器完成先前指令对标志、寄存器和内存的所有修改,并在获取和执行下一条指令之前耗尽对内存的所有缓冲写入 。

(强调我的)

它没有说明发送 IPI 的任何顺序,因为这是当前指令的一部分,而不是下一条指令的一部分。因此,从理论上讲,这意味着另一个核心可以mov r1, [ _x]在原始核心仍在忙于刷新内容时执行,但鉴于目标核心需要服务可能具有更高延迟的中断,因此这种可能性很小。

正如@harold 提到的,这一点没有实际意义,因为WRMSR并不总是序列化。阅读我最初错过的脚注:

WRMSR 到 IA32_TSC_DEADLINE MSR(MSR 索引 6E0H)和 X2APIC MSR(MSR 索引 802H 到 83FH)未序列化。

所以绝对不能保证写入x会被刷新。

  • 它可能比这更糟糕,因为:“对任何非序列化 MSR 执行 WRMSR 都不是序列化。非序列化 MSR 包括......任何 x2APIC MSR” (4认同)