Linux v6.18.37 · 개념과 코드 읽기

ARM SMMUv3·IOMMU·DMA 소스 분석

이 코드는 어떤 문제를 푸나요?

장치용 페이지 표를 고친 뒤에도 SMMU가 옛 번역을 기억할 수 있습니다. CPU TLB를 지웠다는 사실만으로 장치의 IOTLB가 갱신되는 것은 아닙니다. v6.18.37의 arm_smmu_iotlb_sync를 읽어 모아 둔 무효화 범위를 SMMU 경로에 전달하는 과정을 설명합니다.

읽을 범위: v6.18.37 · drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c · arm_smmu_iotlb_sync 3458–3469행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

IOVA

장치가 DMA 요청에 사용하는 주소입니다. CPU VA와 별개 주소 공간입니다.

iotlb_gather

여러 unmap 등에서 무효화할 범위를 모으는 구조입니다. start와 end, pgsize를 함께 관리합니다.

SID와 SSID

장치와 하위 주소 공간을 선택하는 식별자입니다. PCI BDF 숫자와 항상 일치한다고 가정하지 않습니다.

처음 읽을 때

CPU MMU와 SMMU를 병렬로 그려 각자 표와 번역 캐시를 가진다는 점을 설명하십시오.

더 깊이 살펴볼 때

inclusive end 때문에 길이에 1을 더하는 이유와 하위 CMDQ 동기화의 완료 조건을 추적하십시오.

그림으로 보는 변화

ARM SMMUv3·IOMMU·DMA 소스 분석의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 변경 범위 모으기

IOMMU 공통 계층이 무효화할 범위를 gather에 담습니다.

화살표는 여러 변경을 하나의 요청 범위로 모으는 과정입니다.

2. 빈 요청 제외

pgsize가 없으면 추가 무효화 없이 반환합니다.

아무 주소나 전체 flush로 해석하지 않도록 하는 조건입니다.

3. SMMU 무효화 요청

시작·길이·granule과 domain을 하위 함수에 넘깁니다.

CPU TLBI가 아니라 장치 변환기의 갱신 경로입니다.

arm_smmu_iotlb_sync를 한 줄씩 읽기

줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
				struct iommu_iotlb_gather *gather)
{
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);

	if (!gather->pgsize)
		return;

	arm_smmu_tlb_inv_range_domain(gather->start,
				      gather->end - gather->start + 1,
				      gather->pgsize, true, smmu_domain);
}
static void arm_smmu_iotlb_sync(struct iommu_domain *domain,

IOMMU domain에 모아 둔 무효화 작업을 반영하는 드라이버 콜백입니다.

				struct iommu_iotlb_gather *gather)

gather에는 여러 변경에서 수집한 시작·끝 주소와 page size가 들어 있습니다.

	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);

일반 iommu_domain을 SMMU 드라이버의 확장 자료구조로 바꿔 하드웨어별 정보를 얻습니다.

	if (!gather->pgsize)

수집된 페이지 크기가 없으면 유효한 무효화 범위가 없는 경우로 처리합니다.

		return;

빈 요청은 추가 SMMU 명령 없이 종료합니다.

	arm_smmu_tlb_inv_range_domain(gather->start,

수집한 시작 주소부터 domain의 TLB 범위를 무효화하는 하위 경로에 넘깁니다.

				      gather->end - gather->start + 1,

end가 포함형 끝 주소이므로 길이는 end-start+1입니다. 예를 들어 0x1000~0x1fff는 설명용으로 0x1000바이트 범위입니다.

				      gather->pgsize, true, smmu_domain);

페이지 크기와 leaf 무효화 조건, 해당 SMMU domain을 전달합니다. 실제 CMDQ 명령 구성·완료는 호출된 함수 아래에서 진행합니다.

함께 생각해 볼 질문

IOTLB와 CPU TLB는 같은 캐시입니까?

아닙니다. 서로 다른 접근 주체의 번역 상태입니다.

end-start에 왜 1을 더합니까?

이 gather의 end는 마지막 주소를 포함하는 범위이기 때문입니다.

이 helper 자체가 DMA 데이터를 복사합니까?

아닙니다. 주소 변환 무효화 범위를 전달합니다.

출처와 읽은 범위

Linux stable v6.18.37 · drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑