2
votes

I have a PCI device, its Linux driver, and a user-space application. The application mmap's the first BAR of the PCI device through the driver. All the access are done through 32-bits integers, and this is important since reading/writing to a register may have side effects (starting an operation etc.).

On x86 platforms, this works very well. However, I just moved to an ARM platform, and I have a strange behaviour :

  • Reads/Writes from the driver behave correctly
  • Reads from the user-space triggers a 64 bytes PCI read request, which cannot be fulfilled by my device since it accepts only 32-bits accesses (+ I don't want that because of side effects).

I think the problem is that the mmap wants to prefetch some data and issues this 64 bytes read. Am I missing a flag or something that could disable some sort of mmap prefetching ?

My current mmap implementation on the driver's side is simply

vma->vm_flags |= VM_RESERVED;
remap_pfn_range(vma,vma->vm_start,  pfn, Size_UL, vma->vm_page_prot)
1
Does your PCI device advertise itself as prefetchable? (Bit 3 in the Memory BAR.)myron-semack
No, the PCI flag is 0x0040200, (PREFETCHABLE flag is 0x2000 according to my headers)Julien

1 Answers

3
votes

I found the solution !

As a colleague suggested, 64 bytes is a cache line, this might be a caching mechanism ignoring my "non-prefetchable" information, because it is lost during the mmap() (although is was preserved on x86 ...), so I had to add those flags to the vma to prevent caching :

vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot) | L_PTE_PRESENT |
                         L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY;

Not actually sure that all flags are needed but, hey, it works !