reserved_mem 분석 노트
2020 2 29 스터디 내용
Last updated
2020 2 29 스터디 내용
Last updated
Have to read reserved-memory.txt carefully.
Reserved-memory 노드에 기술된 프로퍼티는 다음과 같다.
Reserved-memory의 자식 노드들은 1개 이상의 예약 메모리 영역을 가진다. 예약 메모리 영역은
reg 프로퍼티를 사용하여 예약된 메모리의 특정 범위(base, size)를 지정하거나,
size 프로퍼티를 사용하여 동적으로 예약받을 수 있다. (이 옵션에 더불어 alignment, alloc-ranges 프로퍼티를 같이 사용할 수 있다.)
자식 노드는 반드시 둘 중 하나(reg, size)의 프로퍼티는 가져야 한다.
나머지 프로퍼티는 문서를 참고하라.
Line 24: Reserved memory child node일 경우에 해당 루틴이 실행된다.
Line 28: 해당 노드로부터 reg 프로퍼티 값을 읽는다.
__reserved_mem_reserve_reg 진입
Line 7: 루트로부터 어드레스의 크기, 사이즈의 크기를 넘겨 받는다.
Line 13~14: reg 프로퍼티를 읽는다. 만약 프로퍼티가 존재하지 않으면, ENOENT를 리턴한다. reg 프로퍼티가 있다는 말은, 정적 예약 메모리라는 말이고, 프로퍼티가 없다면 동적 예약 메모리이란 말이다. 해당 함수는 정적 예약 메모리만 처리한다.
Line 17~21: 프로퍼티의 길이를 검증한다.
Line 24: 선택 프로퍼티 no-map이 있는지 확인한다.
Line 26~37: base와 size를 읽어오고, nomap 프로퍼티가 존재한다면, 해당 영역을 memblock_remove, 존재하지 않으면 memblock_reserve한다.
Line 38~41: 첫 번째의 경우(오류와 상관없이?), fdt_reserved_mem_save_node를 호출한다.
Line 29~30: 동적 예약 메모리를 사용하는 노드라면, fdt_reserved_mem_save_node를 호출한다. (단 base, size는 모두 0으로 삽입된다.)
fdt_reserved_mem_save_node는 정적/동적 예약 메모리 영역 모두 호출하게 된다. 이 함수는 동적 예약 메모리를 지원하기 위한 패치에 등장했다.
Line 6: 등록된 정적 예약 메모리 영역 중 겹치는 부분이 있다면, 경고를 띄운다.
내부 구현은 간단하다. 정렬을 하고, 순회하면서 겹치는 영역을 찾는다.
Line 8~19: 예약 메모리 영역을 순회하면 노드에 핸들 프로퍼티가 있다면, 값을 저장한다.
Line 21~22: size가 0이라면, 동적 예약 메모리 영역이므로, 적절한 영역을 할당해주어야 한다. 따라서 __reserved_mem_alloc_size를 호출한다.
__reserved_mem_alloc_size로 진입.
동적 예약 메모리 할당의 핵심인 __reserved_mem_alloc_size으로 진입.
Line 12~20: size 프로퍼티의 값을 읽는다. 해당 프로퍼티는 필수이므로, 프로퍼티를 못찾으면 바로 리턴한다.
Line 22~32: no-map 프로퍼티가 설정되어 있는지 확인, align 프로퍼티가 존재한다면 값을 읽는다.
Line 35~42: cma 영역이라면, align을 조정할 필요가 있다, 조정되지 않는다면, cma 셋업에 실패하게 된다. 해당 패치를 참고하라.
Line 46~59: alloc-range 프로퍼티의 값이 존재하면, 그 값을 읽는다.
Line 61~69: 읽은 range를 대상으로 memblock_find_in_range을 호출하여 빈 영역을 찾는다. 만약 no-map이라면 해당 영역을 memblock_remove를 하고, 아니라면 memblock_reserve한다.
Line 73~77: alloc-range 프로퍼티가 존재하지 않으므로, 모든 영역에 대해서 빈 영역을 찾고, 해당 영역을 memblock_remove/reserve 한다.
Line 80~88: 메모리 할당에 실패시 에러 코드를 리턴, 성공시 인자로 들어온 base, size에 할당받은 주소와 사이즈를 대입한다.
Line 24~25: 오류가 없다면, __reserved_mem_init_node 함수를 호출한다. 해당 함수는 예약 메모리 드라이버 지원 추가를 위한 패치에 도입되었다.
Line 8: RESERVEDMEM_OF_DECLARE로 추가되는 테이블을 순회하며, 지원하는 노드에 대해 초기화 함수를 실행한다.
<200229_Memblock 발췌>
Line 6~10: 각 예약 메모리 영역을 순회하면서, of_flat_dt_is_compatible 함수를 호출해서 compatible이 일치하는지 확인한다. 일치하지 않으면 스킵한다.
Line 13~17: initfn 함수를 실행하는데 이 함수는 아래의 열거된 함수와 대응된다.
rmem_dma_setup
rmem_cma_setup
rmem_cma_setup 함수를 훑어보면
Line 9~16: 노드가 reusable하고 no-map이 아닌지 확인한다. 또한 base와 size의 align을 검증한다. 앞서 봤던 복잡한 조건문이 해당 셋업 함수를 위한 것이다.
Line 18: cma 테이블에서 정적인 cma struct를 받아 초기화 한다.(내용 추가 필요!)
Line 24: fixup 함수를 호출(내용은 비어있다)
Line 26~27: linux,cma-default 프로퍼티가 존재한다면(해당 예약 메모리 영역이 cma-default 영역이라면), dma_continguos_set_default함수를 호출한다.
Reserved-memory 노드의 property
value
#address-cells, #size-cells (필수 속성)
루트 노드의 값과 동일해야 한다.
ranges (필수 속성)
값은 비어 있어야 한다.(empty)