x86 - amd和intel程序员模型兼容性

标签 x86 intel cpu-architecture amd-processor instruction-set

我已通读英特尔软件开发指南(第 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 的交互。尽管英特尔没有明确记录 lockxchg 是否旨在与 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/

相关文章:

x86 - 在英特尔酷睿 i3/i7 的情况下,从缓存集驱逐后数据的去向

caching - CPU缓存: does the distance between two address needs to be smaller than 8 bytes to have cache advantage?

assembly - 如果距开始位置 <128 字节,则访问结构成员会更快?

c++ - 使用 GDB 调试英特尔 C++ 编译代码

assembly - 原子指令可以跨越缓存线吗?

c++ - 使用英特尔编译器 12 和 Visual Studio 2010 编译 boost 1_46_1 时出现问题

multithreading - 什么是 CPU 线程,它与代码中的逻辑线程有什么关系?

c - 为什么一个内核执行的指令多于它所占的指令份额?

linux - 如何使用 BSS var 将字符串移动到寄存器 NASM

c - 如何使用自己的函数覆盖系统调用表条目?