PCIe BAR中MMIO地址预取可行性及相关技术问题咨询
PCIe BAR中UC/WC类型MMIO的预取问题
核心结论
标记为可预取的PCIe BAR区域,即使通过UC或WC页表项映射,处理器是支持预取操作的,但要区分显式预取指令和处理器自发的推测性读取,结合Intel手册细节理解:
1. 预取可行性解析
Intel软件开发手册原文:"Prefetches from uncacheable or WC memory are ignored. ... It should be noted that processors are free to speculatively fetch and cache data from system memory regions that are assigned a memory-type that permits speculative reads (that is, the WB, WC, and WT memory types)."
这里的关键是两种预取的区别:
- 显式预取指令(如
PREFETCHNTA):对UC内存确实会被处理器忽略;WC内存的话,部分微架构可能会处理PREFETCHNTA,但手册明确这类操作不保证支持,行为依赖具体处理器型号。 - 处理器自发的推测性读取:因为WC属于手册中“允许推测性读取”的内存类型,再加上PCIe BAR标记了可预取(说明该MMIO区域读取无副作用、重复读结果一致),所以处理器会主动发起预取来隐藏MMIO访问延迟——这也解释了你遇到的load停顿问题,预取能缓解这类延迟。
2. 预取值的存储位置
- UC类型MMIO的预取数据:只会存在**处理器加载缓冲区(Load Buffer)**或临时寄存器中,不会进入L1/L2/L3缓存(UC本身禁止缓存)。
- WC类型MMIO的预取数据:可能进入L1缓存的非临时缓存行(Non-Temporal Cache Line),或者加载缓冲区——
PREFETCHNTA的设计就是让数据存到这类区域,避免污染常规缓存池。
3. 导致预取值失效的操作
以下操作会让预取的数据在load指令执行前失效:
lfence加载屏障:强制等待所有未完成的加载操作完成,同时刷新加载缓冲区,直接清空预取的UC/WC数据;而sfence是存储屏障,只管控存储操作,完全不影响加载预取的数据,所以执行无关的sfence不会让预取值失效。- 上下文切换:线程被换出CPU核心时,加载缓冲区和临时缓存行的预取值会被清空。
- 页表/地址空间变更:修改页表映射、TLB失效操作等,会让预取的地址关联信息失效,对应数据也会被丢弃。
- 特定缓存操作:比如针对该MMIO地址执行
clflush/clflushopt(哪怕UC/WC内存的这类操作行为特殊),或者执行wbnoinvd全局缓存写回无效操作。
内容的提问来源于stack exchange,提问作者Jack Humphries
相关产品推荐
相关产品推荐

