Search code examples
clinux-kernellinux-device-driverembedded-linuxxilinx-edk

Unhandled fault when accessing AXIS FIFO registers through device driver


I am using a Zynq SoC with Petalinux 2016.2 I originally accessed my AXIS Fifo by opening it with

open("/dev/mem", O_RDWR | O_SYNC)

and using mmap to access it. I could access the registers of the AXIS device and interface successfully with the device through my C application.

I then created a platform device driver, and misc device node to access the device. The device is succesfully recognized by the driver, and I then

fd = open("/dev/devname, O_RDWR | O_SYNC)

and then mmap the device again with:

info->mapped_base = mmap(0, AXIFIFO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)

I can read the registers and it seems to be the correct memory region. But when I start writing to some of the registers I start getting the following error:

Unhandled fault: imprecise external abort (0x1406) at 0x36e42000
pgd = 40ab4000
[36e42000] *pgd=3bff0831, *pte=43c0075f, *ppte=43c00c7f
Bus error

At first it seemed only to be when I write to the SRR reset register, but there's still a few other places as well.

Is there something obvious I am missing? I am suspecting it's to do with specific flags relating to the way the memory is mapped and can be accessed.

I currently have my own mmap function in the device driver where I do the following operation where start and length denotes the size of the mapped region of the AXIS FIFO's registers.

vm_iomap_memory(vma, start, length)

Solution

  • It seems the memory was marked as cached in the vma_area_struct:

    So simply:

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    

    before

    vm_iomap_memory(vma, start, length)
    

    did the trick.