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 특정 버그일 수 있나요? QEMU 구성으로 x86_softmmu를 실행하고 있으며 커널은 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 )

드라이버의 버퍼 포인터에 더미 쓰기를 수행한 다음 사용자 공간 응용 프로그램에서 읽기 및 쓰기를 수행하여 작동한다는 것을 확인했습니다.

관련 정보