<div align="center">
<img src="https://raw.githubusercontent.com/cakehonolulu/pciem/HEAD/resources/icon.svg" width="300" height="300">
<br>
<h2>PCIem</h2>
</div>
<div align="center">
Linux 커널 프레임워크로, 합성(synthetic) 사용자 공간 PCIe 장치 에뮬레이션을 가능하게 합니다. | <a href="https://cakehonolulu.github.io/docs/pciem">문서 (Documentation)</a>
</div>
PCIem이란 무엇인가?
PCIem은 몇 가지 새로운 기술을 활용하여 합성 카드를 호스트 OS에 실제 PCI 장치처럼 보이게 함으로써 Linux 커널에서 가상 PCIe 장치를 생성하는 프레임워크입니다.
간단히 말해, PCIem은 실제 하드웨어가 없는 상태에서도 (제한적이지는 않지만) PCIe 장치 드라이버를 개발하고 테스트하기 위한 프레임워크입니다.
libfvio-user와의 비교
PCIem과 libfvio-user는 서로 다른 목적을 가진 두 가지 솔루션이므로, 둘을 비교할 때 혼동될 수 있습니다. 따라서 여기에서 그 차이점을 설명합니다 (더 자세한 내용은 figure 1을 참조하세요).
주요 차이점은 libvfio-user가 일반적으로 클라이언트(즉, vfio-user 프로토콜을 구현하는 프로그램)에 의존하며, 보통 QEMU(KVM을 통해 VM exit 사용)를 사용하여 에뮬레이션된 PCIe 장치를 게스트에게 노출한다는 것입니다. 사용자는 콜백 메커니즘이 있는 자신의 vfio 서버를 작성하고, 이 서버가 클라이언트와 상호 작용합니다.
반면 PCIem은 장치를 KVM도 없고, 게스트도 없고, 가상 머신도 없이 직접 호스트에 노출한다는 점입니다. 이 장치는 마치 물리적으로 연결된 것처럼 호스트의 PCIe 버스에 나타납니다.
<div align="center" id="figure1">
| 기능 (Feature) | PCIem | libfvio-user |
|---|
| 연결 (Connection) | 장치 파일 (/dev/pciem) | UNIX 소켓 (vfio-user 프로토콜) |
| ... | | |
| Figure 1: 프레임워크 비교 | | |
</div>
아키텍처
graph LR
subgraph Kernel [호스트 Linux 커널]
direction TB
...
현재 기능 (Current Features)
- BAR 생성: BAR 영역을 프로그래밍 방식으로 생성하고 모니터링합니다.
- BAR MMIO 트레이싱: 메모리 매핑 입출력(MMIO) 읽기/쓰기를 감지하고 알림으로써 접근에 대한 폴링(polling)을 방지합니다.
- 인터럽트 지원: 레거시/MSI/MSI-X 인터럽트 주입 기능을 제공합니다.
- PCI 기능 프레임워크: PCI 기능 시스템(내부적으로 연결 리스트 사용).
- DMA 시스템: 사용자 공간 장치로부터/로 IOMMU를 인식하는 DMA 접근을 지원합니다.
- P2P 지원 (예비!): 화이트리스트 기반 접근 제어 기능을 갖춘 장치 간 피어 투 피어(Peer-to-peer) DMA를 지원합니다.
- 사용자 공간: PCIe 장치를 사용자 공간에서 전체적으로 구현할 수 있습니다.
최소 지원 환경
- Linux 커널 버전:
6.6
- C 컴파일러:
gcc-12
- 아키텍처:
amd64/i386, aarch64, riscv
aarch64 참고: Raspberry Pi 4b, 디바이스 트리(ACPI 미사용)에서 테스트됨
riscv 참고: VisionFive 2 (디바이스 트리) 및 Muse Pi Pro (디바이스 트리 및 ACPI)에서 테스트됨
CI 상태
| 배포판 | <img src="https://img.shields.io/badge/-amd64-ED1C24?style=flat-square&logo=amd&logoColor=white"/><img src="https://img.shields.io/badge/-i386-0071C5?style=flat-square&logo=intel&logoColor=white"/> | <img src="https://img.shields.io/badge/-aarch64-0091BD?style=flat-square&logo=arm&logoColor=white"/> | <img src="https://img.shields.io/badge/-riscv-283272?style=flat-square&logo=riscv&logoColor=white"/> |
|---|
| Ubuntu Latest | <img src="https://img.shields.io/github/actions/workflow/status/cakehonolulu/pciem/ci.yml?job=amd64%20build%20(Ubuntu%20latest)&style=flat-square&logo=ubuntu&logoColor=white&label=build&labelColor=E95420"/><img src="https://img.shields.io/github/actions/workflow/status/cakehonolulu/pciem/ci.yml?job=amd64%20QEMU%20Test%20(Ubuntu%20Latest)&style=flat-square&logo=qemu&logoColor=white&label=qemu&labelColor=E95420"/> | - | - |
| ... | | | |
예시
Bochs BGA (drm) 카드
Weston과 같은 사용자 공간 유틸리티에서 구동할 수 있는 Bochs BGA 호환(bochs-drm) 카드입니다. SDL3을 사용합니다.
NVME 컨트롤러
NVME 컨트롤러에 1GB의 스토리지가 연결되어 있습니다. 사용자는 메모리에서 파일을 자유롭게 포맷, 마운트, 생성 및 제거할 수 있습니다.
Intel HDA 카드
pipwire와 함께 샘플을 재생할 수 있는 ICH6 호환 에뮬레이션 모델입니다.
참고: 녹음 시에만 약간의 오디오 잡음이 들리며, 그 외에는 정상적으로 작동합니다.
Intel E1000 카드
E1000 카드의 상당히 단순한 구현체입니다. 실제 NIC(네트워크 인터페이스 카드)로의 통신 리디렉션을 지원합니다. Wi-Fi도 사용할 수 있지만 안정성은 떨어집니다.
<details>
<summary>레거시 예제</summary>
<h2>ProtoPCIem 카드</h2>
이 카드는 QEMU(기본적으로 카드의 상태 머신)에서 완전히 프로그래밍되었으며, 호스트의 실제 드라이버에서 실행되는 모든 사용자 공간 초기화 및 명령어 처리를 담당합니다.
소프트웨어 렌더링된 DOOM(완료된 프레임을 DMA를 통해 카드에 제출하고 QEMU가 표시함)과 간단한 OpenGL 1.X 게임도 실행할 수 있습니다(스크린샷에서 볼 수 있듯이, QEMU 내에서 완전히 구현된 사용자 지정 OpenGL 상태 머신 덕분에 명령어 목록을 소프트웨어 렌더링하고 내부 상태를 그에 따라 업데이트합니다).
<details>
<summary>스크린샷</summary>
<p align="center">
<img width="1903" height="1029" alt="imagen" src="https://github.com/user-attachments/assets/16f64475-ee51-4f79-ae17-b06363f0b12a" />
</p>
<p align="center">
<img width="1757" height="893" alt="imagen" src="https://github.com/user-attachments/assets/4ad00e14-83e5-4e1f-b374-fbaa92def4e3" />
</p>
<p align="center">
<img width="1227" height="846" alt="imagen" src="https://github.com/user-attachments/assets/d21a7d84-f857-4790-bdc6-7bf2714e9eda" />
</p>
</details>
</details>
라이선스
- PCIem 커널 컴포넌트: GPLv2
- 예제: dual MIT/GPLv2.
참고 자료