이 코드는 어떤 문제를 푸나요?
장치가 메모리에 쓴 새 데이터보다 CPU 캐시에 남은 옛 데이터가 먼저 보이면 드라이버는 틀린 결과를 읽습니다. DMA 주소 변환과 캐시 소유권 전환은 별개 문제입니다. arm64의 캐시 관리, x86의 플랫폼 DMA/IOMMU 경로, RISC-V의 비일관성 처리 여부를 비교하고 대표로 arm64 CPU 재접근 함수를 읽습니다.
읽을 범위: v6.18.37 · arch/arm64/mm/dma-mapping.c · arch_sync_dma_for_cpu 23–32행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
DMA 주소
장치에 주는 주소입니다. CPU 가상 주소와 다르며 IOMMU가 있으면 물리 주소와도 다를 수 있습니다.
비일관성 DMA
장치 쓰기가 CPU 캐시에 자동 반영되지 않는 환경입니다. CPU와 장치가 버퍼를 넘겨받을 때 DMA API의 동기화가 필요합니다.
IOMMU
장치가 보는 주소를 물리 메모리에 연결하고 접근 권한을 제한합니다. 이 기능이 CPU 캐시 동기화를 모두 대신하지는 않습니다.
처음 읽을 때
CPU 캐시·RAM·장치를 세 칸으로 그리고 장치가 쓴 뒤 CPU가 읽는 순서를 따라가십시오.
더 깊이 살펴볼 때
DMA_TO_DEVICE에서 CPU 측 invalidate를 생략하는 이유와 버퍼 정렬·거짓 공유 문제를 검토해 보십시오.
그림으로 보는 변화

1. 장치가 사용
장치가 허용된 DMA 주소로 버퍼에 접근합니다.
화살표는 장치의 읽기 또는 쓰기이며 CPU 포인터 역참조가 아닙니다.
2. CPU 소유권 회수
방향이 DMA_TO_DEVICE인지 확인합니다.
전송 방향은 필요한 캐시 작업을 고르는 조건입니다.
3. CPU가 다시 읽기
필요한 경우 CPU 캐시를 무효화해 새 데이터를 가져오게 합니다.
무효화는 버퍼 데이터를 0으로 지우는 작업이 아닙니다.
arch_sync_dma_for_cpu를 한 줄씩 읽기
줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
enum dma_data_direction dir)
{
unsigned long start = (unsigned long)phys_to_virt(paddr);
if (dir == DMA_TO_DEVICE)
return;
dcache_inval_poc(start, start + size);
}void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,장치가 사용한 버퍼를 CPU가 다시 접근할 때 필요한 아키텍처 캐시 작업을 받습니다. paddr는 물리 주소, size는 바이트 범위입니다.
enum dma_data_direction dir)dir는 전송 방향입니다. 장치가 읽었는지 썼는지에 따라 CPU에 낡은 캐시가 남을 가능성이 다릅니다.
unsigned long start = (unsigned long)phys_to_virt(paddr);캐시 유지보수 함수에 전달할 CPU 가상 주소를 물리 주소에서 구합니다. 이 값을 장치 DMA 주소와 혼동하지 않습니다.
if (dir == DMA_TO_DEVICE)장치로 보내기만 한 방향인지 확인합니다. DMA_TO_DEVICE에서는 장치가 버퍼의 새 내용을 작성하는 방향이 아닙니다.
return;이 경우 CPU 쪽 invalidate가 필요 없으므로 돌아갑니다.
dcache_inval_poc(start, start + size);그 외 방향은 해당 주소 구간의 CPU 캐시를 PoC 기준으로 무효화합니다. 장치가 갱신한 RAM 대신 낡은 CPU 사본을 읽지 않도록 하는 작업입니다.
함께 생각해 볼 질문
dma_map_single의 결과를 CPU가 역참조해도 됩니까?
아닙니다. 반환값은 장치에 전달할 DMA 주소입니다.
IOMMU가 있으면 cache sync는 없어도 됩니까?
아닙니다. 주소 보호와 캐시 일관성은 별도 성질입니다.
DMA_TO_DEVICE는 누가 읽는 방향입니까?
장치가 CPU 측에서 준비한 데이터를 읽는 방향입니다.
출처와 읽은 범위
Linux stable v6.18.37 · arch/arm64/mm/dma-mapping.c
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
