我的 PCI 设备驱动程序如何将 PCI 内存重新映射到用户空间?

我的 PCI 设备驱动程序如何将 PCI 内存重新映射到用户空间?

我正在尝试为 QEMU 上的虚拟 PCI 设备实现 PCI 设备驱动程序。设备将 BAR 区域定义为 RAM,驱动程序可以执行 ioremap() 该区域并毫无问题地访问它。下一步是将该区域(或其一部分)分配给用户应用程序。为此,我还实现了 .mmap 函数作为驱动程序文件操作的一部分。这个mmap只是使用了remap_pfn_range,但它还传递了之前由ioremap()返回的内存指针的pfn。

但是,在运行用户空间应用程序时,mmap 成功,但是当应用程序尝试访问内存时,它被终止,并且出现以下 dmesg 错误。

[ 1502.402970] a.out: Corrupted page table at address 7f911b79f000
[ 1502.404085] PGD 13926d067 P4D 13926d067 PUD 1317aa067 PMD 1326d9067 PTE 800026d901000227
[ 1502.404085] Bad pagetable: 000f [#1] SMP NOPTI
[ 1502.404085] Modules linked in: edu_driver(OE) ppdev kvm_amd kvm irqbypass input_leds parport_pc serio_raw parport mac_hid qemu_fw_cfg sch_fq_codel ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables x_tables autofs4 btrfs zstd_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c raid1 raid0 multipath linear psmouse pata_acpi floppy e1000 i2c_piix4
[ 1502.404085] CPU: 0 PID: 1988 Comm: a.out Tainted: G           OE    4.15.0-55-generic #60-Ubuntu
[ 1502.404085] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[ 1502.404085] RIP: 0033:0x55d687642811
[ 1502.404085] RSP: 002b:00007ffe16c38da0 EFLAGS: 00000213
[ 1502.404085] RAX: 00007f911b79f000 RBX: 0000000000000000 RCX: 00007f911b2a1813
[ 1502.404085] RDX: 0000000000000003 RSI: 0000000000001000 RDI: 0000000000000000
[ 1502.404085] RBP: 00007ffe16c38dc0 R08: 0000000000000003 R09: 0000000000000000
[ 1502.404085] R10: 0000000000008001 R11: 0000000000000246 R12: 000055d687642660
[ 1502.404085] R13: 00007ffe16c38ea0 R14: 0000000000000000 R15: 0000000000000000
[ 1502.404085] FS:  00007f911b7984c0(0000) GS:ffff97237fc00000(0000) knlGS:0000000000000000
[ 1502.404085] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1502.404085] CR2: 00007f911b79f000 CR3: 0000000132cd8000 CR4: 00000000000006f0
[ 1502.404085] RIP: 0x55d687642811 RSP: 00007ffe16c38da0
[ 1502.404085] ---[ end trace 6b088b58eb816baf ]---

有谁知道我做错了什么?我是不是漏掉了一步?或者它可能是 QEMU 特有的错误?我正在运行 x86_softmmu 作为我的 QEMU 配置,我的内核是 4.14

答案1

我已经解决了这个问题并设法通过驱动程序将 PCI 内存映射到用户空间。我更改了remap_pfn_range在自定义 .mmap 中使用的函数的 pfn 输入

原文是:

io_remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot ))

其中 pfn 是从 ) 返回的缓冲区指针的结果ioremap(。我将 pfn 更改为:

pfn = pci_resource_start(pdev, BAR) >> PAGE_SHIFT .

这基本上指向 BAR 所指向的实际起始地址。

我现在的工作remap_pfn_range功能是:

io_remap_pfn_range(vma, vma->vm_start, pci_resource_start(pdev, BAR) >> PAGE_SHIFT, vma->vm_end - vma->vm_start,vma->vm_page_prot )

我通过对驱动程序中的缓冲区指针进行一些虚拟写入来确认它的工作原理,然后在我的用户空间应用程序中进行读取并执行一些写入操作。

相关内容