26. 总线锁检测与处理

版权所有:

© 2021 Intel Corporation

作者:

26.1. 问题

拆分锁是指操作数跨越两个缓存行的任何原子操作。由于操作数跨越两个缓存行并且操作必须是原子的,因此系统会在 CPU 访问两个缓存行时锁定总线。

总线锁通过对写回 (WB) 内存的拆分锁定访问或对非 WB 内存的任何锁定访问来获取。这通常比缓存行内的原子操作慢数千个周期。它还会扰乱其他内核的性能,并使整个系统瘫痪。

26.2. 检测

英特尔处理器可能支持以下一种或两种硬件机制来检测拆分锁和总线锁。一些 AMD 处理器也支持总线锁检测。

26.2.1. 用于拆分锁检测的 #AC 异常

从 Tremont Atom CPU 开始,当尝试拆分锁操作时,拆分锁操作可能会引发对齐检查 (#AC) 异常。

26.2.2. 用于总线锁检测的 #DB 异常

一些 CPU 能够在用户指令获取总线锁并执行后通过 #DB 陷阱通知内核。这允许内核终止应用程序或强制节流。

26.3. 软件处理

内核 #AC 和 #DB 处理程序基于内核参数“split_lock_detect”处理总线锁。以下是不同选项的摘要

split_lock_detect=

#AC 用于拆分锁

#DB 用于总线锁

off

不执行任何操作

不执行任何操作

warn(默认)

内核 OOPs 每个任务警告一次,添加延迟,添加同步以防止多个核心并行执行拆分锁。 sysctl split_lock_mitigate 可用于避免延迟和同步。当同时支持这两个特性时,在 #AC 中警告

每个任务警告一次并继续运行。

fatal

内核 OOPs 向用户发送 SIGBUS。当同时支持这两个特性时,在 #AC 中致命

向用户发送 SIGBUS。

ratelimit:N (0 < N <= 1000)

不执行任何操作

将总线锁速率限制为每秒 N 个总线锁,并在系统范围内警告总线锁。

26.4. 用法

检测和处理总线锁可能会在各个领域找到用法

对于构建整合实时系统的实时系统设计人员来说,这一点至关重要。这些系统在某些内核上运行硬实时代码,并在其他内核上运行“不受信任”的用户进程。硬实时无法承受来自不受信任进程的任何总线锁来损害实时性能。迄今为止,设计人员一直无法部署这些解决方案,因为他们无法阻止“不受信任”的用户代码生成拆分锁和总线锁,以阻止硬实时代码在总线锁定时访问内存。

它对于通用计算也很有用,可以防止访客或用户应用程序通过执行带有总线锁的指令来减慢整个系统的速度。

26.5. 指导

26.5.1. off

禁用对拆分锁和总线锁的检查。如果存在以低速率触发这些事件的旧应用程序,因此不需要缓解,则此选项可能很有用。

26.5.2. warn

当检测到总线锁时,会发出警告,从而可以识别违规应用程序。这是默认行为。

26.5.3. fatal

在这种情况下,不会容忍总线锁,并且会终止该进程。

26.5.4. ratelimit

指定一个系统范围的总线锁速率限制 N,其中 0 < N <= 1000。这允许每秒最多 N 个总线锁的总线锁速率。当总线锁速率超过时,任何通过总线锁 #DB 异常捕获的任务都会通过强制睡眠来节流,直到速率再次低于限制。

在可以容忍最小影响但必须防止最终的拒绝服务攻击的情况下,这是一种有效的缓解措施。它允许识别违规进程并分析它们是恶意的还是只是编写不佳。

选择 1000 的速率限制允许每秒锁定总线最多约 700 万个周期(假设每个总线锁需要 7000 个周期)。在 2 GHz 处理器上,这大约是 0.35% 的系统减速。