There is an ARM SMMUv2 in system, and I want to read its memory mapped registers from Linux user space.
So I opened and mmap /dev/mem
, the offset is the physical address of SMMU_BASE got from DTS, e.g. 0x8000000. But when I read from the mmaped region all I got is 0.
There must be something wrong, I also tried with dd if=/dev/mem of=test bs=4096 skip=32768 count=4
, but it failed with Bad Address
.
Then I tried in kernel space with ioremap(0x8000000, 0x1000)
, all I got is also 0.
So what should I do with it?
The user space code is as follows,
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;
}
Finally, I found this is my fault by reading SMMU memory mapped registers in byte.
ARM SMMUv2 spec says
So it must use 32bit/64bit read or write.