CHAPTER 03
3. ring ownership과 memory barrier를 doorbell 순서로 증명한다
CPU가 buffer payload와 descriptor를 쓴 뒤 device에 보이는 순서, device completion 뒤 CPU가 status와 payload를 읽는 순서를 분리합니다. `writel()` 하나가 모든 coherent/streaming DMA 순서를 자동 보장한다고 가정하지 않습니다.
publish 순서
payload와 descriptor field가 먼저 보이고 OWN/tail이 마지막에 보여야 device가 완성되지 않은 entry를 읽지 않습니다.
consume 순서
CPU는 OWN 또는 completion을 확인한 뒤 적절한 DMA read barrier와 sync를 거쳐 status/payload를 읽습니다.
coherent의 범위
coherent allocation은 cache coherence를 제공해도 device register doorbell과 descriptor store 사이 ordering까지 모든 architecture에서 대신하지 않습니다.
tail semantics
DWMAC 세대에 따라 tail pointer가 마지막 유효 descriptor 주소 또는 poll demand 역할을 합니다. 현재 ops의 구현을 기준으로 봅니다.
레지스터와 관측값을 함께 읽는 표
| 항목 | 소유 블록 | 설정 또는 의미 | 정상 증거 | 실패 해석 |
|---|---|---|---|---|
| OWN/status | descriptor | publish/consume synchronization | field 준비 뒤 OWN 설정 | OWN을 먼저 세우면 부분 descriptor |
| TX/RX tail pointer | DMA channel | 새 work 공개 | barrier 뒤 write | doorbell이 data보다 먼저 도착 |
| current descriptor | DMA channel | hardware fetch 위치 | valid ring 범위 안 | stale base 또는 wrap 오류 |
| DMA status | DMA channel | stopped/suspended/fatal bus | 정상 running/interrupt | descriptor unavailable 또는 bus fault |
| IOMMU fault | SMMU/IOMMU | requester IOVA 접근 실패 | fault 0 | unmapped/stale mapping |
| cache maintenance | DMA API | streaming buffer 방향 sync | CPU/device 전환마다 맞는 API | non-coherent corruption |
증상에서 첫 실패 경계를 찾는 표
| 관측 증상 | 직전 통과 증거 | 우선 확인 | 반증 시험 | 판정 |
|---|---|---|---|---|
| 저부하 정상, SMP 부하 실패 | 주소와 format 정상 | barrier/ownership ordering | CPU pinning과 barrier instrumentation | memory ordering |
| doorbell 후 old descriptor 처리 | tail write 보임 | descriptor visibility | coherent/noncoherent 및 dma_wmb 확인 | publish 경계 |
| RX payload가 이전 packet | completion status 정상 | buffer sync/recycle | cache flush/invalidate trace | streaming DMA ownership |
| descriptor unavailable 반복 | DMA bus 정상 | producer와 tail 갱신 | index ledger와 ring dump | software publish 누락 |
| IOMMU fault가 재사용 주소 | 초기 map 성공 | unmap 후 device access | completion 전 unmap 여부 trace | lifetime/order |
| 특정 architecture만 실패 | 동일 driver와 device | implicit ordering 의존 | barrier를 명시한 build 비교 | architecture memory model |
실제 검증 절차
| 순서 | 실행 | 남길 증거 | 판정 목적 |
|---|---|---|---|
| 1 | descriptor index마다 map, OWN set, tail write, completion 시간을 기록합니다. | 단조 사건 ledger | 순서 확인 |
| 2 | IOMMU fault와 DMA channel status를 같은 timestamp로 합칩니다. | 주소/권한/시점 | mapping 문제 분리 |
| 3 | non-coherent 환경에서 sync API를 trace합니다. | buffer별 ownership 전환 | cache 계약 검증 |
| 4 | SMP와 ring wrap 부하로 수백만 회 handoff를 반복합니다. | stuck/중복/손실 0 | 희박한 ordering 오류 검출 |
주의debug 목적으로 OWN bit를 강제로 되돌리거나 tail pointer를 임의로 쓰면 원래 race를 파괴합니다. 관측 코드는 read-only로 시작합니다.
공개적으로 다시 확인할 수 있는 자료
공개되지 않은 vendor register나 integration별 offset을 추측해서 채우지 않았습니다. 아래 제조사 자료, architecture 문서와 Linux v6.18.37 원본에서 다시 확인할 수 있는 범위만 사용했습니다.
Linux stmmac driver
Synopsys GMAC/GMAC4/XGMAC, descriptor, NAPI, PTP와 offload 공개 설명
Linux NAPI
schedule, poll budget, completion과 IRQ 재활성화 계약
Linux v6.18.37 stmmac_main.c
open, xmit, RX, ISR와 NAPI poll 원본
Linux v6.18.37 dwmac4_dma.c
DMA channel, ring length, tail pointer와 interrupt enable
Linux v6.18.37 net/core/dev.c
NAPI core, NET_RX_SOFTIRQ와 receive stack 진입
Linux DMA API HOWTO
descriptor와 packet buffer의 CPU/device ownership, mapping과 barrier