CHAPTER 05
5. Linux enumeration과 BAR sizing을 함수 경계로 따라간다
pci_host_probe() 이후 PCI core는 Vendor ID를 읽어 pci_dev를 만들고 header/capability/BAR를 조사하며 bridge를 재귀적으로 scan합니다. BAR size probe와 resource assignment는 driver probe보다 앞에서 일어나므로 'driver가 BAR 주소를 정한다'고 쓰면 안 됩니다.
Linux PCI scan의 핵심 함수 흐름
| 순서 | 함수/단계 | 입력 | 출력/소유권 | 실패 증상 |
|---|---|---|---|---|
| 1 | pci_host_probe | host bridge/windows/ops | root bus scan 시작 | root bus 생성 실패 |
| 2 | pci_scan_root_bus_bridge | root bus number/resources | struct pci_bus | window/resource 불일치 |
| 3 | pci_scan_child_bus | bus | 발견한 max bus | bridge 뒤 topology 누락 |
| 4 | pci_scan_slot | device number | function scan | multifunction/ARI 누락 |
| 5 | pci_scan_device | bus/devfn | 임시 pci_dev | Vendor ID 0xffff |
| 6 | pci_setup_device | config header | class/header/resource 정보 | unknown header/class |
| 7 | pci_read_bases | BAR registers | resource size/flags | BAR size/type 오류 |
| 8 | pci_scan_bridge | Type-1 bridge | secondary bus tree | bus number/CFG1 실패 |
| 9 | resource assignment | host/bridge windows | BAR assigned address | no space/collision |
| 10 | pci_bus_add_devices | configured pci_dev | driver core 등록 | driver match/probe 안 됨 |
BAR bit와 sizing 해석
| 항목 | 32-bit Memory BAR | 64-bit Memory BAR | I/O BAR | 주의점 |
|---|---|---|---|---|
| type bit | bit0=0 | bit0=0, type bits=10b | bit0=1 | raw low bits는 address가 아님 |
| prefetchable | bit3 | bit3 | 해당 없음 | CPU cacheable 의미와 다름 |
| address mask | ~0xf | low ~0xf + upper dword | ~0x3 | type bit 제거 후 계산 |
| size probe | all ones write/read | low/high를 한 resource로 | all ones write/read | decode 끄고 원값 복원 |
| size 식 | ~mask + 1 | 64bit mask에 적용 | ~mask + 1 | 0 또는 미구현 BAR 처리 |
| alignment | size와 동일 | size와 동일 | size와 동일 | bridge/host window도 포함해야 함 |
resource window의 포함 관계
| 레벨 | 예 | 반드시 포함해야 하는 것 | 검증 위치 |
|---|---|---|---|
| Host MEM window | CPU PA↔PCI MEM | 모든 downstream non-prefetchable BAR | DT ranges/_CRS, root bus resource |
| Host PREF window | 64-bit prefetchable | prefetchable BAR와 child bridge window | root resource tree |
| Bridge MEM window | bus 1 bridge | 그 bridge 아래 non-pref BAR | Type-1 header 0x20.. |
| Bridge PREF window | bus 1 bridge | 그 아래 prefetchable BAR | Type-1 header 0x24.. |
| Endpoint BAR | 03:00.0 BAR0 | device register aperture | sysfs resource/lspci |
| DWC outbound iATU | CPU aperture→PCI window | host resource가 실제 transaction으로 변환되는 범위 | iATU raw dump |
실제 검증 절차
| 순서 | 실행 | 남길 증거 | 판정 목적 |
|---|---|---|---|
| 1 | `lspci -tv`와 모든 bridge의 Primary/Secondary/Subordinate를 저장합니다. | tree와 bus number가 일치 | CFG1 routing 전제 확인 |
| 2 | 각 BAR의 raw 값, size, flags, assigned bus address와 CPU resource를 한 행에 둡니다. | 64-bit BAR pair와 window 포함 관계 | BAR 종류/주소 혼동 방지 |
| 3 | host/bridge/DWC iATU window를 interval로 그려 겹침과 누락을 검사합니다. | parent가 child 전체를 포함 | 일부 offset만 실패하는 문제 탐지 |
| 4 | driver bind 전 `resource`와 bind 후 request owner를 비교합니다. | PCI core 할당과 driver 소유 전환 | driver가 주소를 할당했다는 오해 제거 |
주의BAR에 all-ones를 쓰는 size probe는 PCI core가 decode와 동시 접근을 제어하는 문맥에서 수행합니다. 실행 중인 device에 devmem으로 그대로 따라 하면 안 됩니다.
공개적으로 다시 확인할 수 있는 자료
공개되지 않은 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 연결