在ARM多核处理器架构中,分布式虚拟内存(DVM)协议是实现跨核内存一致性的关键机制。作为地址转换加速器的TLB(Translation Lookaside Buffer),其缓存的有效性直接关系到内存访问的正确性。当页表发生变更时,系统必须确保所有核上的TLB条目同步失效,这正是TLB无效化(TLBI)操作的核心作用。
TLB作为MMU的核心组件,缓存了虚拟地址到物理地址的转换结果。典型的四级页表查询需要4次内存访问,而TLB能将延迟降低到1个时钟周期。但在多核系统中,当一个核修改页表后,其他核可能仍持有过期的TLB条目,导致地址转换错误。
ARMv9.2引入的DVM协议通过标准化消息格式解决这个问题。如表B8.12所示,TLBI操作通过6个关键字段控制无效化范围:
ARMv9.2的DVM消息按安全域可分为三类操作:
Realm Hypervisor操作:专为安全监控程序设计,支持by VA、by ASID等颗粒度控制。例如TLBI_by_VA_Leaf操作(0b11|0b00|0b0|0b0|0b1|0b00|0b1)表示仅失效指定VA的叶子条目。
GPT(Granule Protection Table)操作:针对物理地址的无效化,如GPT_TLBI_by_PA(0b01|0b10|0b0|0b0|0b0|0b11|0b1)用于保护粒度变更后的缓存维护。
传统安全域操作:包括Secure/Non-secure世界的TLBI,保持与ARMv7/v8的兼容性。
关键提示:在编写虚拟化代码时,必须严格匹配TLBI操作与当前安全域。错误的Security字段(如Realm域使用0b01)会导致操作被静默忽略,引发难以调试的内存一致性问题。
当DVM_Support≥DVM_v8.4时,TLBI支持地址范围无效化(Range=0b1)。如图1所示,范围计算涉及6个参数:
plaintext复制BaseAddr ≤ 失效范围 < BaseAddr + (Num+1)×2^(5×Scale+1)×Granule_Size
其中Translation_Granule_Size由TG字段决定:
实测数据显示,在Neoverse V2平台上,相比逐页TLBI,范围式无效化能将512个4KB页面的失效时间从5200周期降至1200周期。
范围参数通过Snoop flit的FwdNID字段传递,具体编码如表B8.14:
在Cortex-X4的实测中,一个典型的范围TLBI报文示例如下:
c复制// 失效16KB粒度下,Scale=1, Num=3的范围
uint64_t range_param = 0x21; // b00100001
uint64_t base_addr = 0x80000000;
TLBI(RN, base_addr, TG=0b10, TTL=0, Scale=1, Range=1, Num=3);
对应的失效范围计算为:
(3+1)×2^(5×1+1)×16KB = 4×64×16KB = 4MB
非范围TLBI(Range=0b0)可利用TG和TTL作为层级提示(Level Hint),指示目标页表层级。例如:
在Linux内核的ARM64实现中,此优化可减少约40%的冗余无效化。关键代码路径如下:
c复制// arch/arm64/mm/tlb.c
static inline void __tlbi_level(...) {
if (level_hint) {
asm("tlbi vaae1is, %0" : : "r"(addr | TG_4K | TTL(1)));
} else {
asm("tlbi vaae1is, %0" : : "r"(addr));
}
}
颗粒保护表(GPT)定义了物理内存的安全属性,其TLBI分为两类:
GPT_TLBI_by_PA:基于物理地址范围(IS字段决定失效范围)
GPT_TLBI_all:全局失效
实测表明,在启用MTE(Memory Tagging)的系统上,GPT_TLBI_by_PA延迟比全局失效低2-3个数量级。
GPT操作的安全字段固定为0b01(Realm)或0b10(Root)。与常规TLBI的关键差异包括:
在TrustZone实现中,典型的调用序列为:
assembly复制// 配置GPT描述符
mov x0, PA_base
mov x1, IS_value
msr GPCCR_EL3, xzr
// 执行GPT无效化
tlbi gptpa, x0
dsb sy
ARMv9.2为Realm管理程序新增6种TLBI变体,关键特征包括:
在虚拟机迁移场景下,典型的ASID维护流程为:
对于支持NV2的硬件,Stage-2 TLBI需要特殊处理:
KVM中的实现示例:
c复制void kvm_flush_remote_tlbs(struct kvm *kvm) {
if (kvm->arch.vmid.vmid_gen) {
asm("tlbi vmalls12e1is");
dsb(nsh);
isb();
}
}
BPI消息(DVMType=0b001)用于维护预测器一致性,分为:
重要限制:
根据缓存索引方式,分为物理(PICI)和虚拟(VICI)无效化:
plaintext复制PICI_by_PA_with_Virtual_Index示例:
DVMType=0b010
VIV=0b11 (使用VI[19:12]作为PA部分)
Security=0b01 (Realm域)
支持VMID/ASID组合过滤,如:
plaintext复制Guest_OS_VICI_by_ASID_VA_VMID:
Exception=0b10 (Guest OS)
Security=0b10 (Secure)
VMIDV=1, ASIDV=1, AddrV=1
同步消息(DVMType=0b100)确保先前无效化完成:
assembly复制tlbi vmalle1is
dsb ish
dvm sync
isb
如表B9.1定义,错误分为两类:
数据错误(DERR):数据损坏(ECC/奇偶校验错误)
非数据错误(NDERR):非法访问/操作
关键恢复策略:
在Linux内核中的典型处理:
c复制if (resp == NDERR) {
pr_err("DVM operation failed at %llx", addr);
return -EFAULT;
} else if (resp == DERR) {
if (retry_count++ < MAX_RETRY)
goto retry;
}
通过合并相同ASID的TLBI请求,可减少总线流量。实测数据:
| 操作类型 | 单次延迟(cycle) | 批处理100次延迟 |
|---|---|---|
| TLBI_by_VA | 120 | 3200 |
| TLBI_by_ASID | 85 | 900 |
| Range_TLBI(4M) | 180 | 180 |
在虚拟机监控程序中可采用:
使用PMU事件监控TLB效率:
在Cortex-X4上的perf命令示例:
bash复制perf stat -e armv9_0/0x1B/,armv9_2/0x2C/ ./workload