SMMU는 device가 내는 주소 앞에 놓인 MMU다
CPU program은 VA를 내고 CPU MMU가 번역한다. DMA device는 IOVA를 내며 SMMU가 허용된 PA로 번역한다. SMMU가 없거나 bypass면 잘못된 device가 다른 process·VM memory를 덮을 수 있다.
device마다 접근 가능한 physical memory 범위를 제한한다.
device가 사용하는 주소 공간으로 contiguous PA일 필요가 없다.
여러 device가 공유할 수 있는 translation·protection 정책 단위다.
잘못된 DMA를 memory corruption 전에 event로 보고한다.
StreamID와 SubstreamID가 어느 translation을 쓸지 고른다
| ID | 출처 | 선택 대상 |
|---|---|---|
| StreamID (SID) | SoC interconnect 또는 PCIe Requester ID | Stream Table Entry. |
| SubstreamID (SSID) | PASID 같은 process context ID | Context Descriptor. |
| ASID | Stage-1 address space | SMMU TLB의 S1 번역 식별. |
| VMID | Stage-2 domain | VM별 S2 번역 식별. |
PCI BDF와 SID가 항상 같은 숫자는 아니다. firmware의 iommu-map, ACPI IORT와 root-complex wiring이 실제 변환을 정한다.
STE가 큰 경로를, CD가 process별 Stage-1을 정한다
| 구조 | Index | 핵심 내용 |
|---|---|---|
| STE | SID | abort/bypass/S1/S2/nested mode, CD table pointer, VMID·VTTBR·VTCR. |
| CD | SSID/PASID | ASID, TTBR0, TCR, MAIR와 Stage-1 permission. |
| I/O page table | IOVA | output PA, read/write permission, memory attribute. |
| IOTLB | SID/SSID/ASID/VMID와 IOVA | 최근 번역 cache. |
arm-smmu-v3.h의 STRTAB_STE_*와 CTXDESC_CD_* mask는 architecture descriptor를 Linux가 어떻게 encoding하는지 보여 준다.
Device probe에서 SID와 SMMU master를 묶는다
장치 발견
PCI/Platform device 발견
→ IOMMU firmware specifier 해석
→ arm_smmu_probe_device(dev)
→ SID 목록과 SMMU instance 확인
→ struct arm_smmu_master 생성
→ feature: ATS/PRI/PASID/stall 검사
→ IOMMU group 결정arm_smmu_probe_device()가 device와 SMMU의 software 관계를 만든다.
IOMMU group은 서로 독립 격리가 가능한 최소 device 집합이다. 같은 group의 device 일부만 VM에 넘기면 peer DMA나 shared reset 때문에 격리가 깨질 수 있다.
Domain attach가 STE를 실제 translation mode로 바꾼다
- IOMMU core가 paging domain을 할당한다.
arm_smmu_domain_finalise()가 Stage-1 또는 Stage-2 page-table config, ASID/VMID를 준비한다.arm_smmu_attach_dev()가 device의 master와 domain 호환성을 검사한다.- 새 target STE를 만들어 SID별 Stream Table에 설치한다.
- CFGI_STE command와 sync로 SMMU가 옛 STE cache를 사용하지 않게 한다.
- ATS가 켜졌다면 device ATC 상태와 ordering도 맞춘다.
핵심 함수는 arm_smmu_domain_finalise()와 arm_smmu_attach_dev()이다.
DMA API가 IOVA→PA page table을 만든다
Mapping path
driver dma_map_*()
→ DMA/IOMMU layer가 IOVA 할당
→ iommu_map_pages()
→ arm_smmu_map_pages()
→ io_pgtable_ops.map_pages()
→ page-table descriptor write
→ device DMA 시작arm_smmu_map_pages()는 architecture-independent io-pgtable backend에 mapping을 맡긴다.
unmap은 PTE를 지우는 것에서 끝나지 않는다. outstanding DMA가 끝났는지, SMMU IOTLB와 device ATC가 옛 번역을 갖고 있지 않은지 확인해야 한다.
CMDQ는 SMMU에게 configuration·TLB 변경을 명령한다
| Command | 목적 | 언제 필요한가 |
|---|---|---|
| CFGI_STE/CD | cached descriptor 무효화 | STE·CD를 변경한 뒤. |
| TLBI_NH_ASID/VA | Stage-1 IOTLB 무효화 | ASID 또는 IOVA mapping 변경. |
| TLBI_S2_IPA/VMALL | Stage-2 IOTLB 무효화 | VM IPA mapping 변경. |
| ATC_INV | device Address Translation Cache 무효화 | ATS device의 mapping 변경. |
| CMD_SYNC | 앞선 command 완료 확인 | 새 mapping을 안전하게 사용하기 전. |
arm_smmu_cmdq_issue_cmdlist()과 range invalidation helper가 queue producer/consumer와 sync를 관리한다.
EVTQ는 잘못된 DMA를 SID·주소·원인과 함께 보고한다
SMMU가 STE fetch, CD fetch, translation, permission, address-size fault를 발견하면 Event Queue에 record를 쓰고 interrupt를 발생시킨다. arm_smmu_evtq_thread()이 record를 소비한다.
Fault 분석 순서
event type 확인
→ SID로 device/master 역추적
→ SSID/PASID와 IOVA 확인
→ 현재 domain과 STE/CD mode 확인
→ IOVA page table walk
→ DMA direction·length·lifetime 확인
→ ATS/PRI 사용 시 device cache·response 확인“Unhandled context fault”만 보고 page table bug라 단정하지 않는다. stale DMA, 잘못된 firmware SID, early unmap, missing permission과 device reset race가 모두 후보다.
SVA·ATS·PRI는 process 주소 공간을 device와 공유한다
| 기능 | 역할 | 추가 위험 |
|---|---|---|
| SVA | CPU process VA와 device IOVA 모델을 공유 | mm lifetime, PASID bind와 process exit 동기화. |
| PASID/SSID | 한 device의 여러 address space 식별 | 잘못된 PASID가 다른 process CD를 선택하지 않게 검증. |
| ATS | device가 translation을 cache | SMMU TLBI 외에 ATC invalidation 필요. |
| PRI | device page request와 fault recovery | stall queue, timeout과 process fault 처리. |
VM device assignment에서는 CPU Stage-2와 SMMU Stage-2를 맞춘다
VFIO로 device를 VM에 할당하면 guest의 IOVA/IPA 계약과 host memory pinning, SMMU domain이 일치해야 한다. CPU가 guest RAM을 접근할 수 있다고 device도 자동 접근 가능한 것은 아니다.
Realm device assignment는 여기에 PAS/GPT와 device security state가 추가된다. 이 Linux v6.18.37의 일반 SMMUv3 driver 경로만으로 Realm private DMA가 자동 안전해진다고 결론 내리면 안 된다.
Linux v6.18.37 소스 지도
| 파일 | 심볼·구조체 | 책임 |
|---|---|---|
| arm-smmu-v3.c | arm_smmu_probe_device, arm_smmu_attach_dev | device 발견과 domain 연결 |
| arm-smmu-v3.c | arm_smmu_map_pages, unmap_pages | I/O page-table mapping |
| arm-smmu-v3.c | arm_smmu_cmdq_issue_cmdlist | configuration·TLBI command |
| arm-smmu-v3.c | arm_smmu_evtq_thread | hardware event 처리 |
| arm-smmu-v3.h | arm_smmu_ste, arm_smmu_cd | hardware descriptor layout |
| arm-smmu-v3.h | arm_smmu_master, arm_smmu_domain | Linux software ownership |
DMA fault를 장치까지 역추적한다
기본 자료 수집
dmesg | grep -Ei 'smmu|iommu|fault|sid|stream'
find /sys/kernel/iommu_groups -maxdepth 2 -type l
lspci -nnvv
cat /proc/iomem
sudo trace-cmd record -e iommu -e dma_fence
grep . /sys/kernel/debug/iommu/* 2>/dev/nullevent의 SID, IOVA, access type과 device BDF를 먼저 고정한다. 그다음 mapping lifetime과 driver DMA API 사용을 검사하고 마지막에 SMMU descriptor를 의심한다.
근거 자료
- Local sourceLinux v6.18.37 commit
0c503cf3dde2 - SMMUv3Arm System Memory Management Unit Architecture Specification
- Linux DMA APILinux DMA API 사용 지침
- OverviewARMv9 가상화·플랫폼 해설