Linux v6.18.37 구현 · dt-schema 공식 정의

reserved-memory와 CMA: 예약한 RAM은 누가 사용합니까?

DTS의 메모리 범위, CMA 할당, 장치가 쓰는 DMA 주소를 분리해 확인합니다.

주소 범위와 사용 방식은 별도입니다

구성정하는 것
/memory운영체제에 전달할 물리 RAM 범위를 기술합니다.
/reserved-memory의 자식 노드일반 사용에서 제외하거나 정해진 조건으로 사용할 영역을 기술합니다.
CMA필요할 때 연속된 물리 페이지 범위를 확보하는 관리 방식입니다. 모든 예약 영역이 CMA는 아닙니다.
DMA mapping해당 장치가 buffer를 접근할 때 쓸 DMA 주소와 접근 조건을 마련합니다.
하드웨어 접근 제어CPU·장치·보안 상태별 접근 권한을 제한합니다. DT의 예약 선언만으로 대신되지 않습니다.

기존 펌웨어 연동 글은 메모리 예약과 보안 접근 제어의 차이를 다룹니다. 여기서는 reserved-memory 속성이 Linux의 CMA 설정으로 어떻게 이어지고, 예약했는데도 할당이 실패할 수 있는 이유를 더 살펴봅니다.

속성 이름 옆에 동작 조건을 함께 읽습니다

속성뜻과 확인할 조건
reg물리 범위의 시작과 크기를 정합니다. 값의 cell 개수는 부모 노드의 #address-cells와 #size-cells를 따릅니다.
size / alignment / alloc-ranges주소를 고정하는 대신 크기와 배치 제약을 제시할 때 사용합니다. 실제 배치 가능 RAM과 커널 조건이 맞아야 합니다.
no-map일반 RAM의 표준 가상 매핑에 포함하지 않도록 합니다. 사용하는 driver의 통제를 벗어난 추측 접근도 허용하지 않는다는 조건입니다.
reusable소유자가 회수할 수 있는 범위에서 운영체제의 임시 사용을 허용합니다. no-map과 함께 지정하지 않습니다.
compatible = "shared-dma-pool"DMA buffer용 공유 pool이라는 용도를 표시합니다. 이 문자열만으로 모든 pool이 CMA가 되지는 않습니다.
linux,cma-defaultLinux의 기본 CMA pool로 사용할 영역임을 표시합니다. 각 장치가 반드시 이 영역만 사용한다는 뜻은 아닙니다.
memory-region장치 노드에서 예약 영역을 참조합니다. 해당 binding과 driver·subsystem이 참조를 실제로 처리해야 합니다.

no-map을 붙였다는 이유로 Secure World 전용 영역이 되지는 않습니다. 보안 하드웨어 설정과 펌웨어의 실제 메모리 사용 범위는 별도로 맞춰야 합니다. reserved-memory 공통 속성 DMA pool 속성

64 MiB CMA 영역을 읽는 예

아래는 DTS 일부를 읽기 위한 예제입니다. 상위 root도 address/size에 각각 2 cell을 쓰고, 0x90000000부터 64 MiB가 실제 RAM이며 다른 용도와 겹치지 않는다고 가정합니다. 이 주소와 크기를 실제 보드에 그대로 적용하지 않습니다.

reserved-memory {
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;

    camera_pool: dma-pool@90000000 {
        compatible = "shared-dma-pool";
        reg = <0x0 0x90000000 0x0 0x04000000>;
        reusable;
    };
};

/* memory-region을 지원하는 실제 장치 노드 내부 */
memory-region = <&camera_pool>;
코드개념적으로 읽기
#address-cells = <2>주소 하나를 32비트 cell 두 개로 표현합니다. CPU register 두 개라는 뜻이 아닙니다.
#size-cells = <2>크기 하나도 cell 두 개로 표현합니다.
ranges;이 예에서는 주소 변환을 추가하지 않는 빈 ranges입니다. 부모의 cell 구성과 함께 봅니다.
camera_pool:DTS 안에서 참조하기 위한 label입니다. C 변수나 실행 중 register가 아닙니다.
reg의 앞 두 cell0x0000000090000000이라는 시작 주소입니다.
reg의 뒤 두 cell0x0000000004000000 byte, 즉 64 MiB입니다. 끝 주소는 포함하지 않는 표기로 0x94000000입니다.
reusable;소유자가 다시 회수할 수 있는 메모리 사용을 허용합니다.
<&camera_pool>빌드 시 phandle 참조로 표현됩니다. 물리 주소 0x90000000을 그대로 넣은 표현이 아닙니다.

이 예에는 linux,cma-default가 없으므로 기본 pool로 지정한 예가 아닙니다. 특정 device와 pool의 연결을 보여 줍니다. 커널 설정, 페이지 크기와 CMA 정렬 제약, DT와 driver 지원 여부까지 만족해야 실제로 사용됩니다. 기본 CMA pool과 장치별 pool 정의

Linux v6.18.37은 어떤 조건을 검사합니까?

kernel/dma/contiguous.c의 rmem_cma_setup()은 shared-dma-pool에 대한 CMA 초기화 경로입니다. 이 버전의 실제 조건문은 다음과 같습니다.

if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
    of_get_flat_dt_prop(node, "no-map", NULL))
    return -EINVAL;

reusable이 없거나 no-map이 있으면 이 CMA 경로가 -EINVAL을 돌려줍니다. 예약 메모리 자체의 모든 용도가 잘못됐다는 뜻은 아닙니다. 다른 용도의 예약 영역과 CMA가 요구하는 조건을 구분해야 합니다.

DT 예약 영역을 CMA에 연결하는 경로
  1. 예약 영역 확인

    base와 size, 겹침 여부 등 예약 정보를 마련합니다.

    CMA용 속성과 정렬 조건을 검사합니다.

  2. rmem_cma_setup

    cma_init_reserved_mem으로 CMA 관리 정보를 준비하고 reserved_mem에 연결합니다.

    후속 초기화에서 CMA 영역을 활성화합니다.

  3. 영역 활성화와 장치 연결

    CMA 관리 상태를 활성화하고 지원 경로에서 장치의 cma_area를 연결합니다.

    장치의 할당 경로가 사용할 pool을 선택합니다.

  4. 실제 buffer 할당

    요청 크기·정렬·사용 중 페이지에 따라 성공 또는 실패합니다.

화살표는 초기화와 사용의 의존 관계입니다. 한 함수 안에서 모든 단계가 연속 실행되거나 DT 선언만으로 장치 DMA가 시작된다는 뜻은 아닙니다.

rmem_cma_device_init()에서 dev->cma_area에 pool을 연결하는 것과 실제 buffer를 할당하는 것은 다른 작업입니다. memory-region 문자열이 보인다는 이유만으로 장치가 그 pool을 이미 사용 중이라고 판단하지 않습니다. v6.18.37 CMA 예약·장치 연결 v6.18.37 CMA 활성화와 할당

예약 영역이 항상 비어 있는 것은 아닙니다

CMA 영역 일부를 연속 buffer로 확보하는 과정

1. 평상시

CMA 영역의 일부는 일반적인 이동 가능한 페이지 용도로 쓰일 수 있습니다. “CMA로 예약”과 “아무도 사용하지 않음”은 같은 상태가 아닙니다.

2. 연속 범위를 요청합니다

CMA가 요청 페이지 수와 정렬에 맞는 후보 범위를 찾습니다. CMA bitmap에서 비어 보이는 후보라도 일반 메모리 용도의 페이지가 남아 있을 수 있습니다.

3. 후보 범위를 비웁니다

연속 할당 경로가 필요한 페이지의 격리·이동 등을 시도합니다. 이동할 수 없거나 다른 사용으로 바쁜 페이지가 남으면 이 후보에서 실패할 수 있습니다. v6.18.37은 -EBUSY에 대해 다른 후보를 시도하는 경로가 있습니다.

4. 성공한 범위를 장치 용도로 사용합니다

확보한 범위의 수명과 DMA 접근 규칙을 지킵니다. 반환할 때에도 장치의 접근이 끝났는지를 먼저 보장해야 합니다. CMA가 할당했다는 사실만으로 전송이 완료되지는 않습니다.

단계는 한 연속 할당 요청의 상태 변화입니다. 모든 요청이 페이지 이동을 수행하거나 반드시 성공한다는 뜻은 아닙니다. 실제 페이지 크기와 주소는 실행 환경에 따라 달라집니다.

v6.18.37의 page allocator는 조건에 따라 CMA 영역을 movable 할당에 사용합니다. CMA 할당 코드는 후보 bitmap을 표시한 뒤 alloc_contig_range()를 호출하고, 실패 시 표시를 되돌립니다. 따라서 pool 총량 하나만 보고 성공을 보장할 수 없습니다. movable 할당과 CMA fallback 후보 범위 선택·이동 실패·재시도

CMA 할당 실패에서 확인할 값

관찰해석과 다음 확인
부팅 로그에 CMA 초기화 실패RAM 범위·정렬·예약 충돌·커널 설정을 먼저 확인합니다.
free memory는 많지만 요청 실패물리 연속 범위, pool 선택, 정렬, 사용 중 buffer와 이동 실패를 구분합니다.
CmaFree가 작습니다.이 값 하나로 driver 누수라고 결론 내리지 않습니다. 어떤 pool에서 어떤 할당이 유지되는지 확인합니다.
반복할 때 사용량이 늘어납니다.성공한 할당과 해제를 짝지어 기록하고, 실패·timeout·장치 종료 경로도 따라갑니다.
DMA 주소와 물리 주소가 다릅니다.IOMMU·DMA mapping 경로를 확인합니다. 주소 차이 자체가 CMA 오류라는 뜻은 아닙니다.

CONFIG_CMA_DEBUGFS가 켜지고 debugfs를 사용할 수 있다면 CMA 영역의 상태를 더 볼 수 있습니다. alloc/free 같은 debugfs 쓰기는 실제 할당 상태를 바꾸는 시험 기능이므로 단순 조회와 구분합니다. trace와 할당·해제 기록을 실제 실패 시점에 맞춰 보는 편이 원인을 좁히기 좋습니다. CMA debugfs 항목 CMA 할당·해제 trace와 반환 경로

오래된 DTS 예제를 옮길 때

구형 Android 3.4 계열 자료의 linux,contiguous-region과 linux,default-contiguous-region을 현재 공통 문법으로 옮기지 않습니다. 다른 구형 vendor branch에 보이는 no-map-fixup·removed-dma-pool도 사용하는 커널의 binding과 구현을 확인해야 합니다. 이름이 비슷해도 현대 reserved-memory·shared-dma-pool 설정과 자동으로 호환되지는 않습니다.

현재 설명은 Linux v6.18.37 코드와 2026-09-24에 확인한 dt-schema 정의를 대조했습니다. schema의 main은 이후 바뀔 수 있으므로 작업 기록에 저장한 응답과 확인 날짜를 함께 남겼습니다. 특정 보드에서 DTS를 빌드·부팅해 검증한 결과는 아닙니다. 확인한 공통 schema