Reading 0 when reading SMMUv2 registers from user space in Linux

47 Views Asked by At

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;
}

1

There are 1 best solutions below

0
On

Finally, I found this is my fault by reading SMMU memory mapped registers in byte.
ARM SMMUv2 spec says

The SMMU architecture supports atomic register access at the size of the register. Whether atomic register accesses of other sizes are supported is IMPLEMENTATION DEFINED

So it must use 32bit/64bit read or write.