amd 和 intel 程序员的模型兼容性
amd and intel programmer's model compatibility
我已经通读了 Intel 的软件开发指南(第 1-3 卷)。
如果没有对 AMD 的编程指南(第 1-5 卷)进行类似的阅读,我想知道英特尔和 AMD 的编程模型在哪些方面是相同的。
当然,即使在一个处理器系列中,也会有特定型号的寄存器并支持各种扩展和功能。
但是,英特尔确实对简单的事情做了一些一般性的陈述,一般来说,我不确定它们是否适用于 AMD。例如:
- 缓存行大小
- 内存顺序保证,每种内存类型
- 原子r/w保证,每个内存类型
- 等等
请注意,我并不是专门询问这些示例。我想问的是,从程序员的角度来看,在编写功能等效的代码方面,AMD 和 Intel 的编程模型是否等效?
(这里只关注AMD64和Intel 64架构)
一般来说相当,编程模型并不总是完全等价的。如果您想 100% 确定,您需要检查两组文档。
https://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64
例如bsf/bsr: Intel docs say they leave the destination undefined, AMD says they leaves it unmodified on zero. But in practice Intel does that to, with a microarchitectural dependency on the output register to go with it. This false-dependency infected lzcnt/tzcnt as well until Skylake, and popcnt still,在英特尔而非 AMD 上。但是,直到英特尔着手将其写在纸上,他们将 保持 让他们的硬件以这种方式运行,编译器不会利用它,我们也许不应该要么手。
(维基百科似乎在说,在 Intel 上,目标的高 32 位可能未定义,而不是归零,但是对于 Intel 上的 bsr
/bsf eax, ecx
。所以它并不严格就像总是写 EAX。我可以在 SKL i7-6700k 上确认这一点:mov rax,-1
; bsf eax, ecx
(ECX 归零)留下 RAX=-1(64 位),不截断为 2^32-1 . 但对于非零 ECX,写入 EAX 具有将零扩展到 RAX 的通常效果。)
这对内核代码尤其重要,特权指令行为可能会有更细微的差异。我认为 TLB 失效语义大多匹配,例如两者都保证在将无效条目更改为有效条目后不需要使 TLB 无效。因此 x86 不允许 "negative caching",因此想要这样做的实现必须窥探 page-table 存储以实现一致性。
其中一些可能是无意的,例如 Intel 和 AMD 都对具有非规范 x86-64 地址的 sysret 有不同的错误,因此在 ptrace
系统调用可能修改了已保存 RIP。切换到用户堆栈 后,在 内核模式下可能会发生潜在的 GP 故障,将内核的控制权交给来自同一进程的另一个可以修改该堆栈的用户-space 线程记忆。 (https://blog.xenproject.org/2012/06/13/the-intel-sysret-privilege-escalation/) That's why Linux always uses iret
except for the common case fast-path where the saved registers are known-clean. The comments in entry_64.S
in the kernel source summarize a bit
未对齐缓存的原子性保证 loads/stores 在 AMD 上较弱:由于 AMD,小至 8 字节的边界在 x86-64 上可能很重要。 涵盖了其中的公共子集。
缓存行大小从未被正式标准化。实际上,Intel 和 AMD CPU 使用 64 字节行,这可以在运行时使用 CPUID 在两者上以相同的方式查询。
据我所知,至少 WB 的内存顺序规则是相同的,并且可能对于其他类型,包括 WC 和 LFENCE/SFENCE/MFENCE 与 lock add
的交互是相同的。尽管英特尔没有明确记录 lock
和 xchg
是否与 mfence
不同。但是你问的是编程模型本身,而不仅仅是文档在纸上所说的。参见 Does lock xchg have the same behavior as mfence? and What is the difference in logic and performance between LOCK XCHG and MOV+MFENCE?
关于 AMD 的 IDK,但 NT WC 负载可能会在 Intel 上使用 lock add
/ xchg
重新排序(但我认为它们不应该使用 MFENCE,这就是 Intel ucode 更新的原因必须加强 Skylake 上的 MFENCE 以像 LFENCE 的其他效果一样阻止 OoO exec,以防止以后的负载完全进入管道。)@Bee 在第一个 link 上的回答提到了这一点,请参阅 the bottom of this。在测试真实硬件时,总是很难判断什么是未来保证的行为,什么只是实现细节,而这正是手册的用武之地。
我已经通读了 Intel 的软件开发指南(第 1-3 卷)。
如果没有对 AMD 的编程指南(第 1-5 卷)进行类似的阅读,我想知道英特尔和 AMD 的编程模型在哪些方面是相同的。
当然,即使在一个处理器系列中,也会有特定型号的寄存器并支持各种扩展和功能。
但是,英特尔确实对简单的事情做了一些一般性的陈述,一般来说,我不确定它们是否适用于 AMD。例如:
- 缓存行大小
- 内存顺序保证,每种内存类型
- 原子r/w保证,每个内存类型
- 等等
请注意,我并不是专门询问这些示例。我想问的是,从程序员的角度来看,在编写功能等效的代码方面,AMD 和 Intel 的编程模型是否等效?
(这里只关注AMD64和Intel 64架构)
一般来说相当,编程模型并不总是完全等价的。如果您想 100% 确定,您需要检查两组文档。
https://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64
例如bsf/bsr: Intel docs say they leave the destination undefined, AMD says they leaves it unmodified on zero. But in practice Intel does that to, with a microarchitectural dependency on the output register to go with it. This false-dependency infected lzcnt/tzcnt as well until Skylake, and popcnt still,在英特尔而非 AMD 上。但是,直到英特尔着手将其写在纸上,他们将 保持 让他们的硬件以这种方式运行,编译器不会利用它,我们也许不应该要么手。
(维基百科似乎在说,在 Intel 上,目标的高 32 位可能未定义,而不是归零,但是对于 Intel 上的 bsr
/bsf eax, ecx
。所以它并不严格就像总是写 EAX。我可以在 SKL i7-6700k 上确认这一点:mov rax,-1
; bsf eax, ecx
(ECX 归零)留下 RAX=-1(64 位),不截断为 2^32-1 . 但对于非零 ECX,写入 EAX 具有将零扩展到 RAX 的通常效果。)
这对内核代码尤其重要,特权指令行为可能会有更细微的差异。我认为 TLB 失效语义大多匹配,例如两者都保证在将无效条目更改为有效条目后不需要使 TLB 无效。因此 x86 不允许 "negative caching",因此想要这样做的实现必须窥探 page-table 存储以实现一致性。
其中一些可能是无意的,例如 Intel 和 AMD 都对具有非规范 x86-64 地址的 sysret 有不同的错误,因此在 ptrace
系统调用可能修改了已保存 RIP。切换到用户堆栈 后,在 内核模式下可能会发生潜在的 GP 故障,将内核的控制权交给来自同一进程的另一个可以修改该堆栈的用户-space 线程记忆。 (https://blog.xenproject.org/2012/06/13/the-intel-sysret-privilege-escalation/) That's why Linux always uses iret
except for the common case fast-path where the saved registers are known-clean. The comments in entry_64.S
in the kernel source summarize a bit
未对齐缓存的原子性保证 loads/stores 在 AMD 上较弱:由于 AMD,小至 8 字节的边界在 x86-64 上可能很重要。
缓存行大小从未被正式标准化。实际上,Intel 和 AMD CPU 使用 64 字节行,这可以在运行时使用 CPUID 在两者上以相同的方式查询。
据我所知,至少 WB 的内存顺序规则是相同的,并且可能对于其他类型,包括 WC 和 LFENCE/SFENCE/MFENCE 与 lock add
的交互是相同的。尽管英特尔没有明确记录 lock
和 xchg
是否与 mfence
不同。但是你问的是编程模型本身,而不仅仅是文档在纸上所说的。参见 Does lock xchg have the same behavior as mfence? and What is the difference in logic and performance between LOCK XCHG and MOV+MFENCE?
关于 AMD 的 IDK,但 NT WC 负载可能会在 Intel 上使用 lock add
/ xchg
重新排序(但我认为它们不应该使用 MFENCE,这就是 Intel ucode 更新的原因必须加强 Skylake 上的 MFENCE 以像 LFENCE 的其他效果一样阻止 OoO exec,以防止以后的负载完全进入管道。)@Bee 在第一个 link 上的回答提到了这一点,请参阅 the bottom of this。在测试真实硬件时,总是很难判断什么是未来保证的行为,什么只是实现细节,而这正是手册的用武之地。