Linux-Kernel

我的 PCI 設備驅動程序如何將 PCI 記憶體重新映射到使用者空間?

  • April 1, 2021

我正在嘗試為 QEMU 上的虛擬 PCI 設備實現 PCI 設備驅動程序。設備將 BAR 區域定義為 RAM,驅動程序可以執行 ioremap() 該區域並毫無問題地訪問它。下一步是將此區域(或其中的一部分)分配給使用者應用程序。為此,我還實現了一個 .mmap 函式作為我的驅動程序文件操作的一部分。這個 mmap 只是簡單地使用了 remap_pfn_range,但它也傳遞了之前 ioremap() 返回的記憶體指針的 pfn。

但是,在執行使用者空間應用程序時,mmap 是成功的,但是當應用程序嘗試訪問記憶體時,它被殺死並且我得到以下 dmesg 錯誤。

$$ 1502.402970 $$a.out:地址 7f911b79f000 處損壞的頁表 $$ 1502.404085 $$PGD​​ 13926d067 P4D 13926d067 PUD 1317aa067 PMD 1326d9067 PTE 800026d901000227 $$ 1502.404085 $$壞頁表:000f$$ #1 $$SMP 之夜 $$ 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 通訊:a.out 污染:G OE 4.15.0-55-generic #60-Ubuntu $$ 1502.404085 $$硬體名稱:QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 $$ 1502.404085 $$翻錄: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 IS: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

我已經解決了這個問題並設法通過驅動程序將 PCI 記憶體映射到使用者空間。我已經更改了我在自定義 .mmap 中使用的 remap_pfn_range 函式的 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)

. 我確認它可以通過對驅動程序中的緩衝區指針進行一些虛擬寫入,然後在我的使用者空間應用程序中讀取並執行一些寫入來確認它的工作原理。

引用自:https://unix.stackexchange.com/questions/643077