I wrote a very simple test program in the application layer. First, I open the PCIe device, then mmap the starting space of the PCIe BAR. Finally, I use the address returned by mmap, apply an offset, and pass it to memset for zeroing. I found that regardless of how the address is aligned, the maximum size passed to memset is only 240 bytes. When the address alignment is less than 16 bytes, the maximum size passed to memset is reduced to less than 8 bytes. I don’t know why this is happening.
There are no AER errors when the bus error occurs.
Using memset_io/memcpy_toio in the driver does not cause errors, regardless of the size, but these require specific I/O interfaces. I am unsure what happens after using memset in user space because it does not use the specific I/O interfaces.
// driver
static int pci_rc_mmap(struct file *file, struct vm_area_struct *vma)
{
resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
resource_size_t start = 0;
start = bar2_start_addr; // bar2_start_addr = pci_resource_start(pdev, BAR_2); bar2_start_addr = 0x1B70000
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return io_remap_pfn_range(vma, vma->vm_start, ((start + offset) >> PAGE_SHIFT), vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
// user
int main(int argc, char **argv)
{
int fd;
void *bar = NULL;
fd = open("/dev/pcie-dev", O_RDWR);
if (fd < 0)
{
perror("open");
return -1;
}
bar = mmap(0, 65536, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
memset(bar, 0, 241); // Bus error
munmap(bar, 65536);
close(fd);
return 0;
}
Qiang.xu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.