arm64 TLBI 可以指定核的范围吗

原始问题:arm64 tlbi 可以指定核的范围吗 · 2026-08-04

arm64 TLBI 能否指定核范围?

直接结论

不能。 TLBI 指令编码中没有 CPU 位图(cpumask)参数,它只能通过助记符后缀选择”广播作用域”(本地 PE / Inner Shareable 域 / Outer Shareable 域),作用域边界由硬件互连拓扑静态决定。要实现”精确到指定 CPU 子集”,必须在软件层面用 IPI 把”本地 TLBI”(无后缀变体)投递到目标核上执行。

一、指令编码层面:TLBI 的作用域后缀

助记符形式 作用域 说明
TLBI VAE1, X10(无后缀) 仅当前 PE(Non-shareable) 本地失效,不广播
TLBI VAE1IS, X10 Inner Shareable 域内所有 PE 最常见的内核路径(is 后缀)
TLBI VAE1OS, X10 Outer Shareable 域内所有 PE(ARMv8.4+) 跨域广播用
TLBI RVAE1IS, X10 IS 域 + VA 地址范围(FEAT_TLBIRANGE,ARMv8.4+) 见下方”范围”澄清

关键语义:

  1. “范围”只能选域,不能选 CPU 子集。”域”(Inner/Outer Shareable)是系统静态划分的(由 CMN/CCN 互连、MPIDR 亲和层级决定),软件无法在运行期把任意几个 CPU 划成一个域。
  2. 无后缀 = 本地。这是实现”指定核”的指令级原子构件:每个目标核自己执行一条本地 TLBI。
  3. “范围”歧义澄清:FEAT_TLBIRANGE(RVAE1IS 系列)的”range”指 VA 地址范围(一次失效一段连续虚拟地址),与”CPU 核范围”无关。内核中 __flush_tlb_range_op 的 r##op 宏(arch/arm64/include/asm/tlbflush.h:510)正是这个含义。

二、软件层面:实现”指定核范围”的三种机制

机制 1:IPI 精确投递 + 目标核执行本地 TLBI(最精确)

典型实例是 KVM stage-2 页表维护。nVHE 模式下 hypervisor 通过 kvm_call_hyp 只向”持有该 VMID 的 pCPU 集合”发 IPI,目标核执行无后缀(本地) TLBI:

// arch/arm64/kvm/hyp/nvhe/tlb.c:177
void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu,
				  phys_addr_t ipa, int level)
{
	...
	__tlbi_level(ipas2e1, ipa, level);	// 无 IS 后缀:本地失效
	dsb(nsh);
	__tlbi(vmalle1);			// 本地失效 Stage-1
	dsb(nsh);
	isb();
	...
}

对比同一文件中的广播版本(__kvm_tlb_flush_vmid_ipa,tlb.c:147)用的是 ipas2e1is + dsb(ish)。同一个功能维护两条路径的原因正是:_nsh 版本已经通过 IPI 把执行范围限定在目标核集合上,再做 Inner Shareable 广播纯属浪费——这就是”指定核范围”在软件中的标准实现模式。

机制 2:内核 mm 层 TLBF_NOBROADCAST 标志

内核 TLB flush 框架显式区分”广播 / 仅本地”:

// arch/arm64/include/asm/tlbflush.h:558
/* Perform the tlbi locally without broadcasting to other CPUs. */
#define TLBF_NOBROADCAST	((__force tlbf_t)BIT(3))

__do_flush_tlb_range(tlbflush.h:561)根据标志选择指令变体:

switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
case TLBF_NONE:			// 默认:广播
	__flush_s1_tlb_range_op(vae1is, ...);	// IS 变体 + dsb(ish) 收尾
	break;
case TLBF_NOWALKCACHE | TLBF_NOBROADCAST:	// 仅本地
	__flush_s1_tlb_range_op(vale1, ...);	// 无后缀变体 + dsb(nsh) 收尾
	break;
...
}

实际调用者(这些场景都已知”只有本核可能命中该映射”):

这是”范围由软件静态推断为单核”时内核主动降级为本地 TLBI 的典型优化。

机制 3:位图延迟执行(异步、按需)

ASID rollover 时 flush_context() 只置位 tlb_flush_pending 位图(arch/arm64/mm/context.c:28,131),各 CPU 在 switch_mm 时自行执行本地 TLB 维护(context.c:255)。这是把”一次全系统同步”拆解为”各核自主执行本地 TLBI + dsb(nsh)“,避免同步等待串行化。

三、关于你贴的 BBM 文档示例

STR X11, [X1]  ; update the translation table entry, marking location as invalid
DSB ISH        ; ensures visibility of the update to translation table walks
TLBI VAE1, X10 ; assumes we are in the EL1
DSB ISH        ; ensures completion of the TLB invalidation
ISB            ; synchronise context on this PE

需要注意:TLBI VAE1 无后缀在正式编码中是本地(Non-shareable)操作,只作用于当前 PE;若文档意图是”inner shareability domain 内所有 observer 不再存在旧翻译缓存”,则该处指令应为 TLBI VAE1IS(或该示例隐含单 PE 上下文)。这也再次印证:域级广播与否完全由 IS/OS 后缀决定,指令本身没有任何按核选择的机制。

四、实践建议(多 die / 鲲鹏 2P 平台)

场景 推荐做法
需要失效”全系统所有核” TLBI xxxIS + dsb(ish);注意多 die 平台上 IS 域可能只覆盖单 die,跨 die 需用 OS 变体或 IPI
需要失效”任意 CPU 子集” smp_call_function_many(mask, fn) / kvm_call_hyp,fn 内执行无后缀 TLBI + dsb(nsh) + isb
单核场景(spurious fault、本地映射修改) 内核 TLBF_NOBROADCAST 已自动走本地路径,OOT 补丁应复用该标志而非自己广播
判断 IS 域边界 查平台互连文档(如 CMN 拓扑)+ MPIDR_EL1 亲和层级,决定 IS vs OS 选择

核心结论:TLBI 的”作用域”只能是静态共享域或本地 PE;”指定核范围”必须由软件(IPI 投递)实现,指令层面不存在单条 TLBI 完成该需求的方式——这与上一轮 DSB 的结论一致,二者在设计上是配套的(本地 TLBI 必须配本地 dsb(nsh),域级 TLBI 必须配域级 dsb(ish/osh))。

参考来源

⚠️ 免责声明

本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。