[커널 17차] 36주차

2021.05.09 00:55

ㅇㅇㅇ 조회 수:133

paging init() 분석 중

 

alloc_init_pud()
- use_1G_block() 부터 진행
- use_1G_block()이 참이면서 flag에 NO_BLOCK_MAPPING이 아니면 pud_set_huge()로 1GB 단위 매핑
- 1G block이 아니면 pud entry 단위로 loop를 돌면서 alloc_init_cont_pmd() 수행한다
- 끝나면 fixmap 가상주소 pudp를 해제한다

 

use_1G_block()
- PAGE_SHIFT가 12가 아니거나
- 현재 pud 가상 주소 및 다음 pud 가상 주소, 현재 pud 물리주소가 PUD (1GB) 단위가 아니면 false
- 그 외엔 true 리턴

 

pud_set_huge()
- phys 물리주소와 prot attribute를 이용해서 새로운 pud entry를 만든 뒤 set_pud()로 매핑한다
- pgattr_change_is_safe()로 attribute 변경의 safety를 체크한다

 

set_pud(pudp, new_pud)
- pudp 가상주소에 new_pud 값을 쓴다

 

pgattr_change_is_safe()
- 새로운 page attribute가 PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG 외의 것을 건드리는 것이 있는지 보고 그 외의 것을 건드리면 false 리턴
- contiguous bit 및 non Global에서 Global로 가면 false이다
- Global/non-Global : https://developer.arm.com/documentation/101811/0101/Address-spaces-in-AArch64


Contiguous bit
- D5.5.6 Other fields in the VMSAv8-64 translation table format descriptors
- D5.3.3 Memory attribute fields in the VMSAv8-64 translation table format descriptors - Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors
- https://01.org/linuxgraphics/gfx-docs/drm/arm64/hugetlbpage.html
- 여러 page들을 묶어서 1개의 TLB로 lookup할 수 있도록 하는 기능
- 예로 4KB granule의 경우 16개씩 묶는다
- Contiguous bit을 1로 해도 TLB entry가 반드시 1개로 되는 것은 아님
- TLB invalidate 등 maintenance할 때는 contiguous bit과 무관하게 실행해야 한다


alloc_init_cont_pmd()
- pudp가 가리키는 물리주소에 값이 써있는지 보고 없으면 memblock으로 물리주소 page 한개를 할당받고 pudp가 해당 물리주소를 가리키게 한다
- pudp가 가리키는 contiguous pmd entry 단위로 루프를 돌면서 init_pmd()를 수행한다
- 만약 align이 잘 맞으면 contiguous mapping을 사용하도록 page attribute를 세팅한다 (32MB 연속 매핑)

 

init_pmd()
- pmd entry의 물리주소에 해당하는 임시 가상 주소를 fixmap으로 할당받는다 (pmdp)
- pmd 단위로 루프를 돌면서 각 pmd entry에 대해서 mapping 수행
- section mapping이 가능하면 pmd_set_huge()로 section mapping 수행 (2MB)
- 아니면 alloc_init_cont_pte()로 pte mapping 수행
- 끝나면 fixmap pmdp 가상주소를 해제한다

 

pmd_set_huge()
- pud_set_huge()과 유사하게 동작한다
- 2MB mapping

 

alloc_init_cont_pte()
- pmdp가 가리키는 물리주소에 아무것도 없으면 memblock으로 1 page 물리주소를 할당받아서 pmdp가 가리키게 한다
- continugous page단위로 루프를 돌면서 pte entry 단위로 init_pte()를 수행한다
- 이 때 우선적으로 가능하면 contiguous bit을 설정하도록 한다 (64KB 단위 연속 매핑)

 

init_pte()
- pte entry 물리주소에 fixmap을 사용하여 임시 가상주소를 할당받는다 (ptep)
- page 단위로 루프를 돌면서 ptep에 각 page에 매핑할 물리주소를 써 준다
- 끝나면 fixmap ptep 가상주소를 해제한다

 

정리
- swapper_pg_dir의 물리주소에 해당하는 가상주소 pgdp를 받고
- pgdp가 가리킬 pud 512개 물리주소를 memblock으로 할당받고
- 각 pud 물리주소 entry마다 fixmap으로 가상주소 pudp를 할당받고
- pudp가 가리킬 pmd 512개 물리주소를 memblock으로 할당받고 (또는 바로 pud section mapping하고)
- pudp가 할당받은 pmd 512개를 16개 단위로 contiguous mapping 시도
- pmd 16개의 시작주소를 fixmap으로 가상주소 pmdp를 할당받고
- pmdp가 가리킬 pte 512개 물리주소를 memblock으로 할당받고 (또는 바로 pmd section mapping하고)
- pmdp가 할당받은 pte 512개를 16개 단위로 contiguous mapping 시도
- pte 16개의 시작주소를 fixmap으로 가상주소 ptep를 할당받고
- 각 ptep에 mapping할 페이지의 물리주소를 써서 매핑한다


map_kernel_segment() 계속
- flag가 VM_NO_GUARD가 아니면 size를 PAGE_SIZE 만큼 증가
- vma의 addr/phys_addr/size/flags/caller를 설정
- flags는 VM_MAP | vm_flags로 설정
- caller는 map_kernel_segment()를 호출한 함수 map_kernel()로 설정
- 그 후 vm_area_add_early()로 만들어진 vma를 list에 추가한다


__builtin_return_address()
- http://rommance.net/blog/?p=739
- __builtin_return_address(0) : 현재 함수의 리턴 주소
- __builtin_return_address(1) : 나를 호출한 함수의 리턴 주소

 

ptrauth_clear_pac 매크로
- ptrauth를 제거한다
- TCR_EL1.TBI0 = 1이고(리눅스 커널에서는 항상 1로 설정), [55] = 0이면 [63:56]은 항상 0이기 때문에 ptrauth_user_pac_mask에서 54부터 vabits_actual까지만 mask하는 것 같음
- https://developer.arm.com/documentation/ddi0601/2021-03/AArch64-Registers/TCR-EL1--Translation-Control-Register--EL1-?lang=en#fieldset_0-37_37
- https://lwn.net/Articles/783380/


vm_area_add_early()
- vmap_initialized가 참이면 버그
- vm->addr 순서대로 오름차순으로 add한다
- *p = temp->next이므로
- vm->next = *p는 vm->next = tmp(previous)->next = tmp(current) 이고
- *p = vm은 tmp(previous)->next = vm 이다


====================================================

vma 개념 (vm_struct 구조체)
- 하나의 연속된 가상 주소 공간을 관리하는 자료 구조
- 이 연속된 가상 주소 공간은 공통의 특성을 가짐 (stack/heap/code 등)
- 간단한 코드를 짜서 돌린 후 /etc/map/PID로 보면 현재 돌아가고 있는 프로그램의 vma 구조가 나온다

=====================================================

 

Vmap study
- http://jake.dothome.co.kr/vmap/

 

Vmap update 되어서 다시 봐야 함 (커널 버전 v5.2-rc1부터, 2019년)
- https://github.com/torvalds/linux/commit/68ad4a3304335358f95a417f2a2b0c909e5119c4
- https://lkml.org/lkml/2018/10/19/786
- O(N) --> O(log N)

 

Red-Black Tree
- https://zeddios.tistory.com/237
- https://m.blog.naver.com/rlakk11/60159303809

- https://nesoy.github.io/articles/2018-08/Algorithm-RedblackTree
- https://velog.io/@keum0821/%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-%ED%8A%B8%EB%A6%ACBinary-Search-Tree-%EA%B5%AC%ED%98%84-%EC%82%AD%EC%A0%9C

XE Login