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