# DMA, cache coherency와 IOMMU translation

v6.18.37 / arch/arm64/mm/dma-mapping.c

장치가 메모리에 쓴 새 데이터보다 CPU 캐시에 남은 옛 데이터가 먼저 보이면 드라이버는 틀린 결과를 읽습니다. DMA 주소 변환과 캐시 소유권 전환은 별개 문제입니다. arm64의 캐시 관리, x86의 플랫폼 DMA/IOMMU 경로, RISC-V의 비일관성 처리 여부를 비교하고 대표로 arm64 CPU 재접근 함수를 읽습니다.

## arch_sync_dma_for_cpu

```c

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);
}

```

### 23행

```c

void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,

```

장치가 사용한 버퍼를 CPU가 다시 접근할 때 필요한 아키텍처 캐시 작업을 받습니다. paddr는 물리 주소, size는 바이트 범위입니다.

### 24행

```c

			   enum dma_data_direction dir)

```

dir는 전송 방향입니다. 장치가 읽었는지 썼는지에 따라 CPU에 낡은 캐시가 남을 가능성이 다릅니다.

### 26행

```c

	unsigned long start = (unsigned long)phys_to_virt(paddr);

```

캐시 유지보수 함수에 전달할 CPU 가상 주소를 물리 주소에서 구합니다. 이 값을 장치 DMA 주소와 혼동하지 않습니다.

### 28행

```c

	if (dir == DMA_TO_DEVICE)

```

장치로 보내기만 한 방향인지 확인합니다. DMA_TO_DEVICE에서는 장치가 버퍼의 새 내용을 작성하는 방향이 아닙니다.

### 29행

```c

		return;

```

이 경우 CPU 쪽 invalidate가 필요 없으므로 돌아갑니다.

### 31행

```c

	dcache_inval_poc(start, start + size);

```

그 외 방향은 해당 주소 구간의 CPU 캐시를 PoC 기준으로 무효화합니다. 장치가 갱신한 RAM 대신 낡은 CPU 사본을 읽지 않도록 하는 작업입니다.

