目录
前述刷新cache的流程也同样可以用于invalid 的操作。
流程设计
1)写程序写数据到内存。
2) 读程序读数据,可能从cache读到老数据,这里invalid
invalid 命令
参考clean的操作,我们采用对应的指令。
DC IVAC, Data or unified Cache line Invalidate by VA to PoC
于是我们设计类似的接口
for (i = 0; i < gen_test_size; i = i + 64)
{
temp_addr=(unsigned char *)((unsigned char *)test_virt_addr_r+i);
__asm volatile("dc ivac,%0"::"r"(temp_addr));
}
但实际运行的时候,报 指令无权限。也就是 用户态不能执行这个指令。
内核态invalid
内核接口,直接调用同样的指令invalid 操作
// 失效指定范围的 D-Cache
static void invalidate_dcache_range(unsigned long start, unsigned long end) {
for (; start < end; start += cache_line_size()) {
asm volatile("dc ivac, %0" :: "r"(start));
}
dsb(ish); // 数据同步屏障
}
if (copy_from_user(&range, (void __user *)arg, sizeof(range))) {
return -EFAULT;
}
invalidate_dcache_range(range.addr, range.addr + range.length);
用户态接口
// 分配测试内存
size_t size = 4096;
char *buffer = malloc(size);
strcpy(buffer, "Test data");
// 构造参数
struct cache_range range = {
.addr = (unsigned long)buffer,
.length = size
};
// 调用 IOCTL 失效 Cache
if (ioctl(fd, 0, &range) < 0) {
上述代码可以正常运行。
内核态invalid,用户态mmap物理地址
内核态同上,但是用户态测试用的地址变为mmap映射
于是我们得到了内核异常,报段错误
576.716499][ 4] [ T2037] Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000007f7b5da740
[ 576.728329][ 4] [ T2037] Mem abort info:
[ 576.732249][ 4] [ T2037] ESR = 0x9600014f
[ 576.736429][ 4] [ T2037] EC = 0x25: DABT (current EL), IL = 32 bits
[ 576.742867][ 4] [ T2037] SET = 0, FnV = 0
[ 576.747048][ 4] [ T2037] EA = 0, S1PTW = 0
[ 576.751313][ 4] [ T2037] Data abort info:
[ 576.755318][ 4] [ T2037] ISV = 0, ISS = 0x0000014f
[ 576.760278][ 4] [ T2037] CM = 1, WnR = 1
[ 576.764371][ 4] [ T2037] user pgtable: 4k pages, 39-bit VAs, pgdp=0000002241257000
PAN机制
PAN(Privileged Access Never) 是 ARMv8 架构引入的一种安全特性,用于防止 内核态(Privileged Mode)直接访问用户态(User Mode)内存,从而增强系统对内存访问漏洞的防护能力。其核心思想是:即使在内核态,也不能绕过 MMU 权限检查直接访问用户空间数据,必须通过安全的拷贝函数(如 copy_from_user
)
PAN 通过 ARM 的页表权限控制,强制内核态访问用户地址时触发异常(即使 MMU 处于内核态)。
若内核需访问用户数据,必须通过
copy_from_user
等安全接口(这些函数会临时禁用 PAN)
目前板卡上此功能并未开启。通过malloc分配的内存可以invalid,也可以验证这一点。
zcat /proc/config.gz |grep CONFIG_ARM64_SW_TTBR0_PAN
CONFIG_ARM64_SW_TTBR0_PAN is not set
PAN机制历程 硬件支持
ARMv8.1-PAN 特性
引入时间:2014 年(ARMv8.1-A 架构)。
核心机制:
新增
SCTLR_ELx.PAN
控制位(EL1/EL2/EL3均可配置)。内核态访问用户地址时触发 Permission Fault(即使 MMU 允许)。
指令支持:
SETPAN
指令动态切换 PAN 状态(需配合ERET
使用)。
Linux 内核的适配
Linux 的实现
初始支持:
Linux 4.10(2016年)合并 ARMv8.1-PAN 支持,通过CONFIG_ARM64_PAN
启用。动态切换:
在合法访问用户数据时(如系统调用),临时禁用 PAN:软件模拟 PAN(SW PAN)
背景
兼容旧硬件:
部分 ARMv8.0 处理器(如 Cortex-A53/A57)无硬件 PAN,需软件模拟。实现原理:
修改页表权限,使用户空间内存在内核态 不可访问。
通过
TTBR0
切换模拟 PAN 效果。
SW PAN 补丁:
Linux 4.3(2015年)引入CONFIG_ARM64_SW_TTBR0_PAN
,通过动态切换TTBR0
实现:性能代价:
每次用户/内核数据拷贝需切换TTBR0
,开销显著高于硬件 PAN。
总结
1)mmap映射的地址并不能被invalid。
2)也不能被lock
总体的拷贝速率比内核管理的慢。后续我们采用巨页来映射,看是否相关的操作是否可行。