Linux用户空间读取SMMUv2寄存器时返回全0的问题排查
问题
系统中存在ARM SMMUv2,尝试在Linux用户空间读取其内存映射寄存器时遇到以下问题:
- 打开并mmap了
/dev/mem,偏移量为从DTS获取的SMMU_BASE物理地址(例如0x8000000),但映射区域读取内容全为0; - 执行命令
dd if=/dev/mem of=test bs=4096 skip=32768 count=4时,报错Bad Address; - 在内核空间使用
ioremap(0x8000000, 0x1000)尝试读取,结果同样全为0。
用户空间读取代码如下:
static int smmuread(int fd, unsigned long address, unsigned int length, off_t offset, unsigned long data, unsigned int data_size) { volatile uint8_t *mptr = 0; volatile uint8_t *wptr = NULL; unsigned int range_len = (length - offset); mptr = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address); if (mptr == (void *) -1) { printf("Failed to do mmap\n"); return 1; } wptr = mptr + offset; switch (data_size) { case 1: printf("%02x\n", *wptr);; break; case 2: printf("%04x\n", *(uint16_t *)wptr);; break; case 4: printf("%08x\n", *(uint32_t *)wptr);; break; case 8: printf("%lx\n", *(uint64_t *)wptr);; break; default: range_len = (length - offset); if (data_size) range_len = MIN(range_len, data_size); dump_range(wptr, range_len); break; } munmap(mptr, length); return 0; }
解决思路与方案
检查SMMU硬件使能状态
ARM SMMUv2默认可能处于复位关闭状态,未初始化的寄存器读值会全为0。先确认内核是否开启了SMMU驱动配置CONFIG_ARM_SMMU_V2,未开启则需开启后重新编译内核;若已开启,查看内核日志确认SMMU驱动是否成功探测并初始化设备。如果是自定义内核模块访问,需手动配置SMMU控制寄存器(如SMMU_CR)完成硬件使能。验证设备树与地址映射权限
- 检查DTS中SMMU节点的
status属性是否为"okay",若为"disabled",内核不会映射该硬件区域,需修改DTS后重新烧录; - 内核配置
CONFIG_STRICT_DEVMEM会限制用户空间通过/dev/mem访问非RAM/PCIe区域,可添加启动参数devmem=1临时关闭限制,或修改内核配置关闭CONFIG_STRICT_DEVMEM后重新编译。
- 检查DTS中SMMU节点的
确认地址对齐与访问范围
mmap的偏移参数必须是页大小(通常4KB)的整数倍,确保传入的SMMU_BASE物理地址已对齐;同时确认映射长度覆盖了你要访问的寄存器范围,避免越界或部分映射导致的无效访问。内核空间访问的注意事项
内核中使用ioremap后,需确保SMMU对应的时钟、电源域已被正确开启(多数SoC中外设需先开启时钟才能访问寄存器)。可参考内核原生SMMU驱动的初始化流程,先完成时钟、电源配置,再进行寄存器读写操作。
内容的提问来源于stack exchange,提问作者wangt13
相关产品推荐
相关产品推荐

