news 2026/10/15 13:21:34

第 4 篇 硬件一致性:总线侦听与一致性互连

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第 4 篇 硬件一致性:总线侦听与一致性互连

本文属于第一册“硬件原理”,回答第 0 篇提出的问题 4:

  • 同一代码为何在 x86 平台上运行正常,在其他平台上却出现数据错误?
  • 硬件一致性机制具体承担了哪些职责?

第 3 篇分析了设备访问不经过 CPU cache 时产生的两类不一致,以及软件维护一致性的方法。本文说明硬件如何使 DMA 访问参与 cache 一致性协议,从而消除这两类不一致;随后比较 x86 与 ARM 等 SoC 平台在这一机制上的差异,说明 Linux 如何获知并处理设备的一致性属性,最后简要介绍 CXL 对一致性范围的扩展。

1. 问题回顾

第 3 篇的分析建立在一个前提之上:设备的 DMA 请求直接到达内存,既不读取 CPU cache 中的脏数据,也不使 cache 中的副本失效。在这一前提下,驱动须在适当的时机执行 clean 与 invalidate 操作,否则设备或 CPU 将读到旧值。

然而在 x86 平台上,即使驱动没有执行全部的 cache 维护操作,DMA 通常仍能正常工作。同一驱动移植至部分 ARM 或 RISC-V 平台后,才出现偶发的数据错误。这一差异说明,第 3 篇的前提在 x86 平台上并不成立:硬件已经使 DMA 请求参与了 cache 一致性的维护。

2. 硬件一致性的基本原理

2.1 CPU 之间的一致性协议

多核处理器中,每个核心拥有私有的 cache,同一地址可能在多个核心的 cache 中同时存在副本。硬件通过一致性协议保证各核心观察到的数据相同。以常见的 MESI 协议为例,每个 cache 行处于以下四种状态之一:

状态含义
M(Modified)仅本 cache 持有该行,且内容已被修改,与内存不一致
E(Exclusive)仅本 cache 持有该行,内容与内存一致
S(Shared)多个 cache 可能同时持有该行,内容与内存一致
I(Invalid)本 cache 中的该行无效

一个核心写入某一 cache 行之前,须先使其他核心持有的副本失效;一个核心读取的 cache 行若在另一核心中处于 M 状态,则由后者提供最新数据。实现这一协议需要让每个访问请求被其他 cache 获知,具体有两种方式:

  • 总线侦听(bus snooping):每个 cache 监视共享总线上的所有请求,发现涉及自身持有的 cache 行时作出响应。该方式实现简单,但侦听流量随核心数增长,适用于核心数较少的系统。
  • 目录(directory)与侦听过滤器(snoop filter):由一致性控制点记录每个 cache 行被哪些 cache 持有,仅向相关的 cache 发送侦听请求。现代多核处理器与大型 SoC 普遍采用这一方式。

本文将接收访问请求、查询一致性状态并发出侦听请求的部件统称为一致性控制点,在不同的实现中,它可能称为 Home Agent、CHA 或一致性互连中的侦听控制逻辑。

2.2 DMA 请求参与一致性协议

硬件一致性的基本思路,是让设备的 DMA 请求与 CPU 的访问请求一样经过一致性控制点,由其完成侦听,如图 1 所示。

图 1: 一致性控制硬件
  • 设备读取:一致性控制点查询该地址是否在 CPU cache 中处于修改状态。若是,则由 cache 提供最新数据(同时可能将其写回内存);否则从内存读取。
  • 设备写入:一致性控制点使所有 CPU cache 中该地址的副本失效,再将数据写入内存。若写入的数据不足一个 cache 行,而该行在 CPU cache 中处于修改状态,则先取回该行,将二者合并后写入。

由此,第 3 篇所述的各项问题均由硬件消除:

第 3 篇的问题硬件一致性下的处理
设备读到旧值(脏数据未写回)侦听命中脏行,由 cache 提供最新数据
CPU 读到旧值(cache 中的陈旧副本)设备写入时使副本失效,CPU 随后的读取从内存取得新值
推测预取产生新的旧副本失效发生在写入时刻,此后的预取读取的已是新值
共享 cache 行导致相邻数据被破坏软件无需执行 cache 维护操作,问题不再出现

需要说明的是,上述机制是单向的:设备侦听 CPU cache,但设备自身不具备参与一致性协议的 cache。这种方式称为 I/O 一致性(I/O coherency)。设备自身的 cache 与 CPU cache 之间的双向一致性,将在第 6 节讨论。

3. x86 平台

3.1 DMA 默认经过侦听

x86 平台自 PCI 时代起即保证 DMA 对普通内存(写回类型)的访问是一致的。PCIe 设备发出的内存请求到达 Root Complex 后,由处理器内部的一致性控制点完成侦听,驱动无需执行任何 cache 维护操作。

Linux 的 x86 架构因此不选择ARCH_HAS_SYNC_DMA_FOR_DEVICE、ARCH_HAS_SYNC_DMA_FOR_CPU等配置项。在这种配置下,判断设备是否一致的接口恒返回true(include/linux/dma-map-ops.h):

#ifdefined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE)||\defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU)||\defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)externbool dma_default_coherent;staticinlinebooldev_is_dma_coherent(structdevice*dev){returndev->dma_coherent;}#else#definedma_default_coherenttruestaticinlinebooldev_is_dma_coherent(structdevice*dev){returntrue;}#endif

第 2 篇节选的dma_direct_map_phys()中,if (!dev_is_dma_coherent(dev))分支在 x86 上恒不执行。这正是遗漏 cache 维护的驱动在 x86 上仍能正常工作的原因。

3.2 DDIO:DMA 数据直接写入 LLC

在一致性的基础上,Intel 至强处理器进一步提供了 DDIO(Data Direct I/O)。启用 DDIO 时,设备写入的数据不写入 DRAM,而是直接置入末级 cache(LLC);设备读取的数据若位于 LLC 中,也直接从 LLC 提供。对于网卡接收等场景,CPU 随后处理数据时可在 LLC 中命中,既降低了延迟,也减少了内存带宽的消耗。

DDIO 通常仅使用 LLC 中的少数几路。若 CPU 未能及时处理,后续写入的数据会将先前的数据逐出至 DRAM,此时 DDIO 的收益随之消失。这一机制也说明,在一致性平台上,DMA 写入的数据可能根本未到达内存,“设备将数据写入内存”在此类平台上只是一种逻辑上的描述。

3.3 No Snoop 属性

一致性并非 x86 平台上所有 DMA 事务的固定属性。PCIe TLP 头部包含 No Snoop 属性位,置位时表示该请求无需侦听 CPU cache,Root Complex 可以跳过侦听,直接访问内存。设备只有在 PCIe 能力结构中 Device Control 寄存器的 Enable No Snoop 位(PCI_EXP_DEVCTL_NOSNOOP_EN)置位时,才可以发出此类请求。

No Snoop 主要用于 GPU 等高带宽设备:对于 CPU 侧以不可缓存或写合并方式映射的缓冲区,CPU cache 中不存在其副本,侦听没有意义,跳过侦听可以降低延迟与互连负载。此时一致性由软件通过映射方式保证,而非由硬件保证,该做法将在第 22 篇讨论。内核在处理部分硬件缺陷时会关闭这一属性(drivers/pci/quirks.c),其注释表明了这一属性的性质:

*This affects other devices under the same Root Port,but since these*attributes are performance hints,there should be no functional problem.

由此可见,即使在 x86 平台上,一致性也是每个事务的属性,而非平台的固定属性。只是对于驱动通过 DMA 映射接口建立的普通映射,x86 保证其访问经过侦听。

4. ARM 等 SoC 平台

4.1 为何不默认提供一致性

在 SoC 中,侦听逻辑需要占用互连的面积与功耗,侦听请求也会增加访问延迟。早期嵌入式 SoC 的外设多为带宽较低的控制器,通过简单的 AXI 总线连接至内存控制器,设计者通常选择由软件维护一致性,以节省硬件成本。这一设计延续至今,使得许多 ARM 与 RISC-V SoC 中仍存在非一致性的 DMA 主设备。

4.2 一致性互连

随着多簇 CPU 与高带宽外设的出现,ARM 在 AMBA 总线规范中加入了一致性扩展,并提供相应的互连 IP:

  • ACE(AXI Coherency Extensions):用于 CPU 簇、带 cache 的 GPU 等主设备。此类主设备既可以发起一致性访问,也接受互连发来的侦听请求,属于完全一致性(full coherency)。
  • ACE-Lite:用于 PCIe Root Complex、DMA 控制器等自身不带 cache 的主设备。此类主设备发出的请求会侦听 CPU cache,但互连不会向其发出侦听请求,即第 2.2 节所述的 I/O 一致性。
  • CHI(Coherent Hub Interface):面向大规模系统的一致性协议,用于 CMN 等网格互连,多见于 ARM 服务器处理器。

CCI-400、CCI-500 等互连基于 ACE,CCN 与 CMN 系列互连基于 CHI。这些互连通常集成侦听过滤器,部分还包含系统级 cache。图 2 给出了 SoC 中一致性主设备与非一致性主设备的连接关系。

图 2: SoC 中一致性主设备与非一致性主设备的连接关系

主设备的访问是否一致,取决于两方面的因素:一是该主设备通过何种端口接入互连,二是其事务所携带的共享与缓存属性。二者均由 SoC 设计与固件配置决定,驱动无法自行改变。

4.3 一致性是设备级的属性

由图 2 可知,同一 SoC 中可以同时存在一致性与非一致性的主设备。例如 Broadcom NS2 的设备树中包含 CCI-400 互连节点,其 PCIe 控制器标注了dma-coherent属性(arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi):

pcie0: pcie@20020000 { compatible = "brcm,iproc-pcie"; reg = <0 0x20020000 0 0x1000>; dma-coherent; ... }; cci@65590000 { compatible = "arm,cci-400"; ... };

而第 2 篇讨论的 BCM2711 中,外设与 PCIe 控制器均未标注该属性,属于非一致性设备。因此,“ARM 平台需要软件维护一致性”这一说法并不准确:一致性取决于具体的 SoC 与具体的设备。ARM 服务器平台的 PCIe 设备通常是 I/O 一致的,而许多嵌入式 SoC 中的设备则不是。

5. Linux 对设备一致性的处理

5.1 固件描述

Linux 无法通过探测得知设备是否一致,这一信息由固件提供:

  • 设备树:设备节点或其上级总线节点中的dma-coherent属性表示一致,dma-noncoherent属性表示非一致;二者均未出现时,采用架构的默认值。
  • ACPI:设备的_CCA(Cache Coherency Attribute)对象表示其是否一致。

设备树的解析逻辑如下(drivers/of/address.c):

boolof_dma_is_coherent(structdevice_node*np){structdevice_node*node__free(device_node)=of_node_get(np);while(node){if(of_property_read_bool(node,"dma-coherent"))returntrue;if(of_property_read_bool(node,"dma-noncoherent"))returnfalse;node=of_get_next_dma_parent(node);}returndma_default_coherent;}

5.2 内核中的表示

设备探测阶段,of_dma_configure_id()或 ACPI 的相应流程以上述结果调用arch_setup_dma_ops(dev, coherent),后者将其保存至dev->dma_coherent。此后,DMA 映射的各条路径通过dev_is_dma_coherent()决定是否执行 cache 维护:

DMA 操作一致性设备非一致性设备
流式映射与dma_sync_*不执行 cache 维护操作按方向调用arch_sync_dma_for_device()或arch_sync_dma_for_cpu()
dma_alloc_coherent()返回普通的可缓存内存清除内核线性映射上的脏行后,将内存重映射为不可缓存类型,或直接修改其内存属性

后一项可见于dma_direct_alloc()(kernel/dma/direct.c):

if(!dev_is_dma_coherent(dev)){...set_uncached=IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED);remap=IS_ENABLED(CONFIG_DMA_DIRECT_REMAP);...}...if(remap){pgprot_tprot=dma_pgprot(dev,PAGE_KERNEL,attrs);.../* remove any dirty cache lines on the kernel alias */arch_dma_prep_coherent(page,size);/* create a coherent mapping */ret=dma_common_contiguous_remap(page,size,prot,__builtin_return_address(0));...}

可见,同一个dma_alloc_coherent()调用,在一致性设备上得到的是可缓存内存,在非一致性设备上得到的是不可缓存内存,二者的 CPU 访问性能差异可能相当大。驱动对此无需感知,但在评估性能时应予以考虑。

5.3 描述错误的后果

由于一致性属性来自固件,描述错误将直接导致问题:

  • 非一致性设备被描述为一致:内核跳过全部 cache 维护操作,出现第 3 篇所述的两类不一致。此类错误通常表现为偶发的数据损坏,且与系统负载、cache 状态相关,难以复现。
  • 一致性设备被描述为非一致:内核执行不必要的 cache 维护,并以不可缓存方式映射一致性缓冲区,导致性能下降;在部分平台上,同一内存以不同属性映射还可能引发其他问题。

在移植新的 SoC 或调试 DMA 数据错误时,核对设备树中的dma-coherent属性是否与硬件设计一致,是一项基本的检查步骤。

6. CXL:双向一致性

前文所述的 I/O 一致性是单向的:设备侦听 CPU cache,CPU 不侦听设备。随着加速器自身配备 cache 与大容量内存,这一模型的局限逐渐显现。CXL(Compute Express Link)在 PCIe 物理层之上定义了三种协议:

协议作用
CXL.io与 PCIe 基本相同,用于设备发现、配置、中断与普通 DMA
CXL.cache设备可缓存主机内存,并参与主机的一致性协议:设备的 cache 也接受主机的侦听
CXL.mem主机可通过 load/store 访问设备所连接的内存

据此,CXL 设备分为三类:仅使用 CXL.cache 的 Type 1 设备(如智能网卡),同时使用 CXL.cache 与 CXL.mem 的 Type 2 设备(如带显存的加速器),以及仅使用 CXL.mem 的 Type 3 设备(内存扩展器)。

CXL.cache 使设备的 cache 成为一致性协议的正式参与者,CPU 与设备之间实现了双向一致性。这为第五册讨论的统一虚拟地址空间提供了另一种硬件基础:在此类平台上,CPU 与设备共享数据时,无需显式的 cache 维护或数据迁移即可保证一致性。

7. 常见误区

7.1 认为代码在 x86 上运行正常即说明一致性处理正确

x86 硬件掩盖了以下各类错误:

错误x86 上的表现非一致性平台上的表现
遗漏dma_sync_*_for_cpu()正常CPU 读到旧数据
遗漏dma_sync_*_for_device()正常设备读到旧数据
DMA 缓冲区与其他数据共享 cache 行正常相邻数据被破坏或 DMA 数据被覆盖
映射方向错误正常维护操作不正确,数据错误

此外,即使在 x86 平台上,上述错误也并非总是无害。在 SWIOTLB 生效的场景中(例如设备寻址能力不足,或机密计算虚拟机强制所有 DMA 经由 SWIOTLB 中转),dma_sync_*负责在原缓冲区与中转缓冲区之间复制数据,该复制与设备是否一致无关(kernel/dma/direct.h):

if(!dev_is_dma_coherent(dev)){arch_sync_dma_for_cpu(paddr,size,dir);...}swiotlb_sync_single_for_cpu(dev,paddr,size,dir);

遗漏dma_sync_*_for_cpu()时,数据停留在中转缓冲区中,CPU 读到的是原缓冲区中的旧内容。SWIOTLB 将在第 11 篇讨论。

7.2 认为硬件一致性使 DMA 映射接口成为多余

硬件一致性仅消除了 cache 维护操作。DMA 映射接口还承担地址转换(第 2 篇)、IOMMU 映射(第 6 篇)与 SWIOTLB 中转(第 11 篇)等职责,这些职责与一致性无关。即使在一致性平台上,驱动也必须通过映射接口获取 DMA 地址,并遵循其调用约定。

7.3 认为硬件一致性同时保证了访问顺序

硬件一致性保证各方观察到的同一地址的数据相同,但不保证对不同地址的访问以程序顺序被观察到。驱动在更新描述符的所有权标志之前,仍需使用dma_wmb()等屏障,保证描述符的其他字段已对设备可见。第 3 篇所述的一致性与顺序是两个独立层次的问题,在一致性平台上同样成立。

8. 小结

对问题 4 的回答可归纳如下:

  • 硬件一致性使 DMA 请求参与 cache 一致性协议。设备读取时,侦听命中的脏行由 cache 提供数据;设备写入时,CPU cache 中的副本被置为无效。第 3 篇所述的两类不一致及其附加问题由此全部消除。
  • x86 平台默认提供 I/O 一致性。Linux x86 上dev_is_dma_coherent()恒为真,cache 维护路径不被执行,这是遗漏 cache 维护的代码在 x86 上仍能正常运行的原因。DDIO 在此基础上将 DMA 数据直接置入 LLC;PCIe 的 No Snoop 属性则允许特定事务跳过侦听。
  • ARM 等 SoC 平台的一致性取决于具体设备。通过 ACE-Lite 等端口接入一致性互连的主设备是 I/O 一致的,其余主设备需要软件维护一致性。这一属性由设备树的dma-coherent或 ACPI 的_CCA描述,内核据此决定是否执行 cache 维护以及一致性缓冲区的映射方式。
  • CXL.cache 将一致性扩展为双向,设备的 cache 同样接受主机的侦听。
  • “x86 上能运行”不等于“一致性处理正确”,遵循 DMA 映射接口的约定是保证代码可移植的唯一方式。

至此,第一册已讨论了设备访问内存时所用的地址,以及访问双方的数据一致性。此外,设备对其所访问内存的物理布局还存在约束:部分设备要求缓冲区物理连续,部分设备只能访问一定范围以内的地址。这些约束源于何处,即为问题 5,也是下一篇讨论的内容。


系列导航:

  • 上一篇《第 3 篇 一致性问题的根源:CPU cache 与设备访问的视角差异》
  • 下一篇《第 5 篇 DMA 与内存布局:物理连续性、寻址位宽与反弹缓冲》将回答问题 5:设备为何对内存的物理布局存在约束。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 13:19:41

Flutter+OpenHarmony电子合同应用性能优化实践

1. 项目背景与核心挑战电子合同签署应用在现代商务场景中扮演着越来越重要的角色。我们团队最近基于Flutter框架和OpenHarmony操作系统开发了一款跨平台的电子合同签署应用&#xff0c;但在实际测试中遇到了明显的性能瓶颈。当用户处理超过20页的PDF合同时&#xff0c;应用会出…

作者头像 李华
网站建设 2026/10/15 13:19:40

context-mode:SQLite+FTS5+BM25构建确定性上下文感知架构

1. “context-mode”到底是什么&#xff1f;别被术语唬住&#xff0c;它本质是让AI真正“听懂上下文”的工程实践最近在多个技术社区和开源项目讨论里&#xff0c;“context-mode”这个词高频出现&#xff0c;尤其和MCP、SQLite、FTS5、BM25这些词绑在一起。很多人第一反应是&a…

作者头像 李华
网站建设 2026/10/15 13:19:25

单周期CPU设计入门:从数据通路到Verilog实现的完整工程实践

简介&#xff1a;面向计算机组成原理课程的单周期CPU设计完整实验资料包&#xff0c;覆盖MIPS32指令集下十六条指令的实现&#xff0c;配套完整Verilog HDL源代码与详细实验报告。资源能帮助学习者理解MIPS常用指令系统&#xff0c;掌握单周期CPU的工作原理、数据通路与控制信号…

作者头像 李华
网站建设 2026/10/15 13:19:24

排序题分析误区与Bradley-Terry模型实战指南

1. 问卷排序题到底在测什么&#xff1f;——别再当成普通多选题来处理“问卷排序题应该怎样分析&#xff1f;”这个问题看似简单&#xff0c;但我在过去十年带过的几十个用户研究、产品验证和市场调研项目里&#xff0c;发现超过七成的团队把它当成了“加了序号的多选题”——导…

作者头像 李华
网站建设 2026/10/15 13:18:53

Jenkins Pipeline 中 docker: not found 报错排查与解决方案

1. 问题现象与根因定位1.1 报错现场还原Pipeline 跑到docker build或docker push这一步&#xff0c;控制台突然甩出一行红字&#xff1a;docker: not found第一次遇到这个报错的人&#xff0c;十有八九会先去 Jenkins 服务器上敲一遍docker version&#xff0c;发现宿主机上 Do…

作者头像 李华
网站建设 2026/10/15 13:18:15

Spring Boot+区块链防疫物资管理系统开发实战

1. 项目背景与核心价值去年参与某公益组织信息化改造时&#xff0c;我亲眼目睹了传统纸质登记方式在突发疫情中的窘境——捐赠物资信息滞后、分配效率低下、库存统计混乱。这正是我们开发这套防疫物资管理系统的初衷。基于Spring Boot的技术选型&#xff0c;我们实现了从捐赠对…

作者头像 李华