系统中有一个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 mmapn");
return 1;
}
wptr = mptr + offset;
switch (data_size) {
case 1:
printf("%02xn", *wptr);;
break;
case 2:
printf("%04xn", *(uint16_t *)wptr);;
break;
case 4:
printf("%08xn", *(uint32_t *)wptr);;
break;
case 8:
printf("%lxn", *(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规范说
SMMU体系结构支持大小为的原子寄存器访问寄存器。其他大小的原子寄存器访问是否为支持的是IMPLEMENTATION DEFINED
所以必须使用32位/64位读写。