CHAPTER 01
1. 주소를 하나로 부르지 말고 translation ledger를 만든다
MMIO 한 번과 DMA 한 번은 서로 반대 방향의 주소 변환을 사용합니다. 각 단계의 입력 주소, 출력 주소, 길이, 속성, requester ID와 소유자를 표로 적으면 iATU와 IOMMU가 뒤섞이지 않습니다.
CPU virtual address
ioremap/pci_iomap으로 만들어진 kernel VA입니다. page table을 지나 CPU physical address가 된 뒤 SoC interconnect로 나갑니다.
CPU physical/parent bus address
DWC AXI slave aperture가 decode하는 주소입니다. Linux DWC 코드의 parent_bus_addr가 이 공간을 뜻합니다.
PCI bus address
TLP header에 실리는 address입니다. endpoint BAR가 decode하는 주소이며 CPU physical address와 같을 필요가 없습니다.
BAR offset
Endpoint 내부 register/filed offset입니다. assigned BAR base에 더해 TLP address가 됩니다.
DMA address/IOVA
DMA API가 device에 제공하는 주소입니다. IOMMU가 있으면 PA가 아니라 IOVA일 수 있습니다.
System physical address
IOMMU와 interconnect translation 뒤 실제 DRAM page가 위치한 주소입니다. descriptor에 이 값을 직접 쓰는 것은 DMA API 계약을 깨뜨릴 수 있습니다.
주소 공간별 이름과 소유자
| 번호 공간 | 예시 | 누가 할당/변환하나 | 어디에 기록되나 | 수명 |
|---|---|---|---|---|
| Kernel VA | ffff800012340000 | ioremap/pci_iomap | driver pointer | map 해제까지 |
| CPU PA | 0x6000_0000 | firmware resource/host bridge | page table PTE와 resource | host window 유지 동안 |
| DWC AXI aperture | 0x6000_0000..0x6fff_ffff | SoC address decode | DT ranges와 iATU base/limit | controller 설정 동안 |
| PCI bus address | 0x8000_0000 | PCI resource allocator | BAR/bridge window | enumeration/resource assignment 동안 |
| BAR-relative offset | BAR0 + 0x1000 | endpoint specification | driver register definition | device lifetime |
| DMA address/IOVA | 0x1_2400_0000 | DMA/IOMMU API | descriptor | map/unmap 또는 coherent allocation lifetime |
| System PA | 0x9a40_0000 | memory allocator/IOMMU mapping | IOMMU PTE/physical page | page allocation lifetime |
| MSI doorbell address | platform별 address | MSI domain/remapper | MSI capability/table | IRQ vector allocation lifetime |
한 transaction을 기록하는 ledger
| 필드 | CPU→Endpoint MMIO 예 | Endpoint→Memory DMA 예 | 왜 필요한가 |
|---|---|---|---|
| Originator | CPU core | Endpoint function 03:00.0 | requester와 ordering 주체 |
| Input address | CPU PA 0x60001000 | DMA addr 0x124000000 | translation 입력 |
| Translator 1 | outbound iATU region 2 | Root Port inbound routing/SMMU | 첫 경계 |
| Output address 1 | PCI 0x80001000 | SMMU input IOVA | TLP/stream 관찰값 |
| Requester ID | Root Port | 03:00.0 RID | IOMMU/AER 연결 |
| Translator 2 | 없음 또는 bridge window | SMMU IOVA→PA | 최종 memory target |
| Length/attributes | 4B non-posted read | 4KiB posted write | completion/ordering 판정 |
| Completion evidence | CplD + MMIO value | device completion + memory visibility | 완료 정의 |
실제 검증 절차
| 순서 | 실행 | 남길 증거 | 판정 목적 |
|---|---|---|---|
| 1 | DT ranges 또는 ACPI _CRS를 CPU PA와 PCI bus address 두 열로 펼칩니다. | 각 window의 size/flags/offset | host aperture의 translation 식 확보 |
| 2 | DWC outbound iATU base/limit/target을 raw dump합니다. | firmware window와 1:1 대응 | software description과 hardware programming 대조 |
| 3 | sysfs resource와 driver pci_iomap 대상을 같은 BAR 행에 적습니다. | assigned bus address와 CPU PA 관계 | 잘못된 BAR mapping 배제 |
| 4 | DMA descriptor의 address를 dma_map 결과와 IOMMU fault의 IOVA에 대조합니다. | 동일 queue entry/RID/length | PA/IOVA 혼동 제거 |
주의driver가 출력한 0x12340000을 문맥 없이 '물리 주소'라고 기록하지 않습니다. 그 값이 CPU PA, PCI bus address, IOVA 중 무엇인지 반드시 열 이름에 적습니다.
공개적으로 다시 확인할 수 있는 자료
공개되지 않은 vendor register나 integration별 offset을 추측해서 채우지 않았습니다. 아래 제조사 자료, architecture 문서와 Linux v6.18.37 원본에서 다시 확인할 수 있는 범위만 사용했습니다.
Linux v6.18.37 DWC common source
iATU programming, version/capability와 eDMA detection
Linux v6.18.37 DWC host source
ECAM/CFG access, Root Port setup, MSI irqdomain와 host lifecycle
Linux v6.18.37 PCI probe
Vendor ID read, pci_dev 생성, BAR sizing와 bridge scan
Linux v6.18.37 PCI resource assignment
bridge window와 endpoint BAR resource 배치
Linux DWC Devicetree binding
reg/ranges, iATU window 수, lane/speed와 MSI/IOMMU 연결