27. 总线锁检测和处理¶
- 版权:
© 2021 Intel Corporation
- 作者:
Fenghua Yu <fenghua.yu@intel.com>
Tony Luck <tony.luck@intel.com>
27.1. 问题¶
拆分锁是指操作数跨越两个缓存行的任何原子操作。由于操作数跨越两个缓存行且操作必须是原子的,因此当 CPU 访问这两个缓存行时,系统会锁住总线。
总线锁是通过对写回 (WB) 内存的拆分加锁访问,或对非 WB 内存的任何加锁访问获取的。这通常比缓存行内的原子操作慢数千个周期。它还会破坏其他核心的性能,并使整个系统陷入瘫痪。
27.2. 检测¶
英特尔处理器可能支持以下用于检测拆分锁和总线锁的一种或两种硬件机制。某些 AMD 处理器也支持总线锁检测。
27.2.1. 用于拆分锁检测的 #AC 异常¶
从 Tremont Atom CPU 开始,当尝试进行拆分锁操作时,拆分锁操作可能会引发对齐检查 (#AC) 异常。
27.2.2. 用于总线锁检测的 #DB 异常¶
某些 CPU 具有在用户指令获取总线锁并执行后,通过 #DB 陷阱通知内核的能力。这允许内核终止应用程序或实施限流。
27.3. 软件处理¶
内核的 #AC 和 #DB 处理程序根据内核参数 “split_lock_detect” 来处理总线锁。以下是不同选项的摘要:
split_lock_detect= |
用于拆分锁的 #AC |
用于总线锁的 #DB |
关闭 |
什么也不做 |
什么也不做 |
warn(默认) |
Kernel OOPs 每个任务警告一次,增加延迟,添加同步以防止多个核心并行执行拆分锁。可以使用 sysctl split_lock_mitigate 来避免延迟和同步。当同时支持这两个功能时,在 #AC 中发出警告 |
每个任务警告一次并继续运行。 |
fatal |
Kernel OOPs 向用户发送 SIGBUS。当同时支持这两个功能时,在 #AC 中为 fatal |
向用户发送 SIGBUS。 |
ratelimit:N (0 < N <= 1000) |
什么也不做 |
在全系统范围内将总线锁速率限制为每秒 N 个总线锁,并在出现总线锁时发出警告。 |
27.4. 用途¶
检测和处理总线锁可在各个领域找到用途
这对于构建整合型实时系统的实时系统设计人员至关重要。这些系统在某些核心上运行硬实时代码,在其他核心上运行“不受信任”的用户进程。硬实时代码绝对不能容忍任何来自不受信任进程的总线锁损害实时性能。迄今为止, 设计人员一直无法部署这些解决方案,因为他们无法阻止“不受信任”的用户代码生成拆分锁和总线锁,从而在总线锁定期间阻止硬实时代码访问内存。
它对于通用计算也很有用,可以防止客户机或用户应用程序通过执行带有总线锁的指令来降低整个系统的运行速度。
27.5. 指导意见¶
27.5.1. off¶
禁用拆分锁和总线锁检查。如果存在以极低频率触发这些事件因而无需进行缓解的旧版应用程序,则此选项会很有用。
27.5.2. warn¶
检测到总线锁时会发出警告,从而可以识别出违规的应用程序。这是默认行为。
27.5.3. fatal¶
在这种情况下,不容忍总线锁,进程将被终止。
27.5.4. ratelimit¶
指定一个全系统的总线锁速率限制 N,其中 0 < N <= 1000。这允许总线锁速率最高达到每秒 N 个总线锁。当超过总线锁速率时,通过 buslock #DB 异常捕获的任何任务都会通过强制睡眠进行限流,直到速率再次降至限制以下。
在可以容忍极小影响但必须防止最终拒绝服务攻击的情况下,这是一种有效的缓解措施。它允许识别违规进程并分析它们是恶意的还是编写不良的。
选择 1000 的速率限制允许总线每秒被锁定最多约 700 万个周期(假设每个总线锁 7000 个周期)。在 2 GHz 处理器上,这大约会导致 0.35% 的系统减速。