我已通读英特尔软件开发指南(第 1-3 卷)。
如果没有对 AMD 的编程指南(第 1-5 卷)进行类似的阅读,我想知道英特尔和 AMD 的编程模型的哪些方面是相同的。
当然,即使在处理器系列中,也会有特定于模型的寄存器以及对各种扩展和功能的支持。
但是,英特尔确实对简单的事情做出了一些一般性声明,一般来说,我不确定它们是否适用于 AMD。例如:
- 缓存行大小
- 每种内存类型的内存顺序保证
- 每种内存类型的原子读/写保证
- 等等。
请注意,我并不是专门询问这些示例。我想问的是,从程序员的角度来看,就编写功能等效的代码而言,AMD 和 Intel 编程模型是否等效?
(这里只关注AMD64和Intel 64架构)
最佳答案
总的来说,编程模型并不总是完全相同。如果您想 100% 确定,您需要检查两组文档。
<强> https://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64
例如bsf/bsr :Intel 文档称他们未定义目的地,AMD 表示他们将其保留为 0 且未修改。但实际上,英特尔确实做到了这一点,并在微架构上依赖于输出寄存器。 This false-dependency infected lzcnt/tzcnt as well until Skylake, and popcnt still ,在 Intel 上,但不在 AMD 上。但直到英特尔开始把它写在纸上,他们将继续让他们的硬件以这种方式运行,编译器不会利用它,我们也许也不应该手动利用它。
(维基百科似乎说在 Intel 上,对于 Intel 上的 bsr
/bsf eax, ecx
,目标的高 32 位可能未定义,而不是归零不过,这并不像总是写 EAX 那样严格。我可以在 SKL i7-6700k 上确认这一点: mov rax,-1
; bsf eax, ecx
(使用归零的 ECX )留下 RAX=-1(64 位),不会截断为 2^32-1。但是对于非零 ECX,写入 EAX 具有零扩展为 RAX 的通常效果。)
这对于内核代码尤其重要,特权指令行为可能有更细微的差异。我认为 TLB 失效语义大多匹配,例如两者都保证在将无效条目更改为有效后不需要使 TLB 无效。因此,x86 不允许“负缓存”,因此想要这样做的实现必须监听页表存储以保持一致性。
其中一些可能是无意的,例如 Intel 和 AMD 都对具有非规范 x86-64 地址的 sysret 存在不同的错误,使得在 ptrace
系统调用可能已修改后使用它不安全保存的 RIP。切换到用户堆栈后,内核模式可能会发生潜在的 GP 错误,将内核控制权交给同一进程中的另一个用户空间线程,该线程可以修改该堆栈内存。 ( https://blog.xenproject.org/2012/06/13/the-intel-sysret-privilege-escalation/ ) 这就是 Linux 总是使用 iret
的原因,除了保存的寄存器是已知干净的常见情况快速路径之外。 comments in entry_64.S
in the kernel source summarize a bit
AMD 上未对齐缓存加载/存储的原子性保证较弱:由于 AMD,小至 8 字节的边界在 x86-64 上可能很重要。 Why is integer assignment on a naturally aligned variable atomic on x86?涵盖了其中的公共(public)子集。
缓存线大小从未被正式标准化。实际上,Intel 和 AMD CPU 使用 64 字节行,并且可以在运行时使用 CPUID 以相同的方式对其进行查询。
据我所知,内存顺序规则至少对于 WB 来说是相同的,对于其他类型也可能是相同的,包括 WC 以及与 LFENCE/SFENCE/MFENCE 与 lock add
的交互。尽管英特尔没有明确记录 lock
和 xchg
是否旨在与 mfence
不同。但是您询问的是编程模型本身,而不仅仅是文档在纸上所说的内容。请参阅Does lock xchg have the same behavior as mfence?和 What is the difference in logic and performance between LOCK XCHG and MOV+MFENCE?
关于 AMD 的 IDK,但 NT WC 加载可能会在 Intel 上使用 lock add
/xchg
重新排序(但我认为它们不应该使用 MFENCE,这就是为什么英特尔 ucode 更新必须加强 Skylake 上的 MFENCE,以阻止 OoO exec,就像 LFENCE 的其他效果一样,以防止以后的负载进入管道。)@Bee 在第一个链接上的回答提到了这一点,请参阅 the bottom of this 。在测试真实硬件时,总是很难分辨什么是 future 有保证的行为,什么只是实现细节,这就是手册的用武之地。
关于x86 - amd和intel程序员模型兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54379076/