[커널 17차] 103주차

2022.08.28 21:52

ㅇㅇㅇ 조회 수:35

page_lock_anon_vma_read()
- 인자로 page를 받는다
- L535 : rcu read lock을 잡는다. anon_vma 슬랩 캐시는 RCU TYPESAFE 형태로 slab cache를 만들었기 때문에 slab cache page는 rcu의 보호를 받는다. 그러나 slab cache 내부의 object도 rcu에 의해 보호 받는 것은 아니다
- L536 : page->mapping에서 anon mapping를 가져온다
- L537 : page->mapping이 anon mapping이 아니면 out으로 가서 NULL 리턴
- L539 : page가 mapping이 안되어 있으면 out으로 NULL 리턴. 함수 page_mapped()로 판정한다
- L542 : anon mapping에서 하위 2개 비트를 버리고 anon vma 구조체를 가져온다
- L543 : anon_vma의 root anon vma를 가져온다
- L544 : down_read_trylock()으로 root anon vma의 rw semaphore를 잡는다
- L550 : read semaphore를 잡았는데 page가 mapping이 없으면 다시 up read를 하고 NULL을 리턴한다
- L554 : page가 mapping이 있으면 out으로 가서 anon vma를 리턴한다
- L558 : fastpath가 실패한 경우로 semaphore read lock으로 sleep 들어갈 준비
- L558 : anon vma의 refcount가 0이면 그냥 NULL 리턴하고 아니면 recount를 1 증가시킨다. 이는 sleep하기 전에 해당 anon vma를 사용 중이니 죽이지 말라고 표시하는 것임
- L563 : page가 mapping되어 있지 않으면 rcu read unlock하고 put_anon_vma()로 refcount 1 감소시키고 NULL 리턴
- L570 : rcu read unlock
- L571 : anon_vma_lock_read()로 root anon vma의 semaphore read down해서 sleep
- L573 : wake up이후 recount를 1 감소시킨다. 그런데 감소시키고 나서 0이 되어버리면 쓰는 곳이 없으므로 semaphore read up, __put_anon_vma()로 anon vma free 수행하고 NULL을 리턴한다
- L584 : anon_vma를 리턴한다
- L587 : out 지점. rcu read unlock
- L588 : anon_vma를 리턴한다

 

page_mapped()
- page를 인자로 받아서 page->_mapcount가 0 이상이면 true, 아니면 false를 리턴한다
- 기준이 0인 이유는 map count가 -1로 초기화되기 때문이다
- compound page의 경우 page[1].compound_mapcount를 볼 수도 있고 tail page들의 mapcount를 볼 수도 있다
- hugetlbfs page인 경우 page[1].compound_mapcount로만 판정한다
- 아니면 tail page들의 mapcount 중 하나라도 0 이상이면 true이다

 

put_anon_vma()
- anon_vma를 인자로 받아 refcount를 1 감소시킨다
- 그 결과 0이 되면 __put_anon_vma()를 수행해서 anon_vma를 free 한다

 

__put_anon_vma()
- 함수 anon_vma_free()로 인자 anon_vma를 free
- anon_vma의 root anon_vma의 recount도 1 감소시킨다
- 그 결과 root의 refcount도 0이 되면 root도 anon_vma_free()로 free 시킨다

 

anon_vma_free()
- anon_vma를 인자로 받아 free 시킨다
- L107 : anon_vma의 refcount가 0이 아니면 버그
- L126 : might_sleep()으로 양보
- L127 : anon_vma의 root anon vma의 rw semaphore가 lock이 걸려있으면 write down —> write up 순서대로 수행해서 unlock 될 때까지 기다린다
- L132 : kmem_cache_free()로 anon_vma 메모리를 해제한다

 

page_referenced()
- 인자로 page, bool is_locked, memcg를 받는다. vm_flags 인자는 출력값
- L861 : page_referenced_arg 구조체 pra 선언
- L865 : rmap_walk_control 구조체 rwc 선언
- L872 : 인자 page의 mapcount == 0이면 0 리턴
- L875 : page->mapping이 rmap인데 이게 NULL이면 리턴
- L878 : is_locked == false이면서 page가 anon이 아니거나 ksm이면 page에 대해 trylock_page()를 시도하고 실패하면 1을 리턴한다
- L889 : 특정 memcg로 요청한 경우 rwc.invalid 함수 포인터에 invalid_page_referenced_vma() 함수를 달아준다
- L893 : 함수 rmap_walk() 수행. 출력값은 rwc에 남는다
- L894 : rmap walk의 결과를 vm_flags 인자에 전달한다
- L896 : page lock을 잡았었으면 unlock_page()로 푼다
- L899 : rmap 결과로 리턴된 pra.referenced를 반환한다

 

page_rmapping()
- 인자로 page를 받아서 page->mapping을 리턴한다
- page가 tail page이면 head의 mapping을 리턴
- page->mapping에서 매핑 플래그는 제거하고 리턴함

 

trylock_page()
- page의 compound head page를 구한뒤, 해당 page에 대해 test and set bit lock으로 page->flags의 PG_locked를 set한다.
- 자신이 set하는데 성공하면 1 리턴, 원래 set되어 있었으면 0 리턴한다

 

invalid_page_referenced_vma()
- 인자로 vma, arg를 받는다
- arg로부터 memcg를 구해서 vma->vm_mm과 memcg가 일치하는지 확인한다
- 일치 안하면 true, 일치하면 false 리턴

 

unlock_page()
- page를 인자로 받아 PG_locked 비트를 클리어한다
- 동시에 PG_waiters 값이 1이면 wait_on_page_locked()에서 sleep했던 task들을 wake_up_page_bit() 함수로 깨운다

 

arch_clear_bit_unlock_is_negative_byte()
- 특정 bit를 clear하고 원래 값의 7번째 비트가 0인지 리턴한다
- 0이었으면 0, 아니면 1 리턴

 

wait_on_page_locked()
- 인자로 page를 받아 PG_locked이 풀릴 때까지 sleep한다

 

rmap_walk()
- 인자로 page, rmap walk control rwc를 받는다
- L2367 : page가 anon이면 rmap_walk_anon()을 locked = false로 호출

 

rmap_walk_anon()
- 인자로 page, rmap walk control rwc, locked를 받는다
- L2279 : 현재 locked = false이므로 rmap_walk_anon_lock()을 호출하고 결과를 anon_vma로 받는다
- L2281 : anon_vma == NULL이면 그냥 리턴
- L2284 : 함수 page_to_pgoff()으로 page의 가상 시작 주소와 끝 주소를 계산한다
- L2286 : anon_vma_interval_tree_foreach() 매크로로 anon_vma의 interval tree로 달려 있는 anon vma chain 자료구조 중 page 주소와 겹치는 것들을 순서대로 가져온다. 순서는 (a, b) interval에서 a가 작은 순서이다
- L2288 : avc->vma (vm_area_struct)를 가져온다
- L2289 : vma_address() 함수로 avc->vma에서의 page 시작 주소 address를 구한다
- L2292 : cond_resched()는 CONFIG_PREEMPTION = y이고 CONFIG_PREEMPT_DYNAMIC = n이므로 ___might_sleep()과 같다
- L2294 : 현재 rwc->invalid_vma는 없으므로 패스. 있는 경우 memcg 영역이 vma 영역에 해당 안되면 continue로 다음 avc를 검색한다
- L2297 : rwc->rmap_one()으로 rmap walk를 수행하고 그 결과 0이면 루프를 중단한다. 현재 rmap_one()은 함수 page_referenced_one()로 설정되어 있음
- L2299 : rwc->done() 함수가 있으면 수행하고 그 결과 1이면 루프 중단
- L2303 : 루프가 끝난 경우 locked == false이면 함수 anon_vma_unlock_read()로 page의 root anon vma의 semaphore read lock을 풀어준다 (read up)

 

page_to_pgoff()
- page가 hugetlbfs가 아니면 page_to_index()로 page->index를 리턴한다
- page->index는 __page_set_anon_rmap()에서 anon page 생성시 rmap 만들때 같이 만들어준다
- __page_set_anon_rmap()에서 linear_page_index(vma, address)로 생성함

 

linear_page_index()
- vma, address를 인자로 받는다
- pgoff = vma->vm_pgoff + (address - vma->vm_start) >> PAGE_SHIFT 로 만들어 리턴
- vm_pgoff는 함수 do_mmap()에서 anon mapping 만들때 addr >> PAGE_SHIFT로 만들어줌
- vm_start는 함수 mmap_region()에서 addr로 만들어준다
- 따라서 pgoff = address >> PAGE_SHIFT와 같다

 

vma_address()
- 인자로 page, vm_area_struct vma를 받는다
- L395 : page의 pgoff를 구한다
- L396 : page pgoff가 vma->vm_pgoff 보다 크면 vma 자체의 pgoff로부터 page index를 계산하여 pgoff에 해당하는 가상 시작 주소를 구한다
- L400 : 가상 시작 주소가 vma의 가상 주소 범위를 벗어나면 에러 리턴
- L402 : page pgoff가 vm->vm_pgoff 보다 작으면 page 끝 주소를 계산하여 끝 주소가 vma->vm_pgoff 보다 큰 경우 vma->vm_start 즉 vma 시작 주소를 가상 시작 주소로 선택
- L407 : page 끝 주소도 vma 범위에 안들어오면 에러 리턴
- L409 : 구한 가상 시작 주소를 리턴

 

rmap_walk_anon_lock()
- 현재는 rwc-.anon_lock이 존재하므로 콜백 함수 page_lock_anon_vma_read()를 실행하여 page의 root anon vma의 semaphore read lock을 잡고 anon vma을 읽어서 리턴한다


ARM64 Page Table Format
- https://wenboshen.org/posts/2018-09-09-page-table.html

 

문C블로그 PVMW
- http://jake.dothome.co.kr/rmap-3/

 

TLB Flush + DSB 문제
- https://patchwork.kernel.org/project/linux-arm-kernel/patch/1540805158-618-1-git-send-email-amhetre@nvidia.com/

 

TLB 명령
- https://developer.arm.com/documentation/101811/0102/Translation-Lookaside-Buffer-maintenance

 

Barrier
- https://tot0rokr.github.io/arm64/barrier/pipeline-barrier-isb-dmb-dsb-ordering/
- https://stackoverflow.com/questions/70635862/synchronizing-caches-for-jit-self-modifying-code-on-arm
- 결론적으로 self modifying code에 대해 다음과 같이 해야 함

 

dc cvau, Xn ; Clean cache to PoU, so the newly written code will be visible
dsb ish     ; Wait for cleaning to finish
ic ivau, Xn ; Invalidate cache to PoU, so the newly written code will be fetched
dsb ish     ; Wait for invalidation to finish
isb sy      ; Make sure new instructions are fetched from cache or memory

 

VIPT
- https://www.youtube.com/watch?v=mMHkIa6Lkek
- https://casionwoo.tistory.com/30

 

MMU notifier
- https://lwn.net/Articles/266320/
- 가상머신 시스템에서 메모리 관리할 때 page AF를 지우거나 page를 reclaim 등을 할 때 guest OS 등에 notify를 하는 시스템
- 가상머신 뿐만 아니라 sysmmu, iommu, GPU 등 device 메모리가 사용되는 경우에도 적용 가능

 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 626
» [커널 17차] 103주차 ㅇㅇㅇ 2022.08.28 35
147 [커널 18차] 66주차 kkr 2022.08.27 76
146 [커널 17차] 101~102주차 ㅇㅇㅇ 2022.08.21 47
145 [커널 18차] 65주차 kkr 2022.08.20 28
144 [커널 18차] 64주차 kkr 2022.08.13 75
143 [커널 17차] 100주차 [1] ㅇㅇㅇ 2022.08.06 100
142 [커널 18차] 63주차 kkr 2022.08.06 102
141 [커널 17차] 99주차 ㅇㅇㅇ 2022.07.31 35
140 [커널 18차] 62주차 kkr 2022.07.30 26
139 [커널 17차] 97~98주차 ㅇㅇㅇ 2022.07.24 52
138 [커널 18차] 61주차 kkr 2022.07.23 113
137 [커널 18차] 60주차 kkr 2022.07.16 129
136 [커널 17차] 95~96주차 ㅇㅇㅇ 2022.07.10 105
135 [커널 18차] 59주차 kkr 2022.07.09 126
134 [커널 19차] 8주차 kanlee 2022.07.02 160
133 [커널 19차] 7주차 kanlee 2022.07.02 95
132 [커널 19차] 6주차 kanlee 2022.07.02 42
131 [커널 19차] 5주차 kanlee 2022.07.02 38
130 [커널 19차] 4주차 kanlee 2022.07.02 106
129 [커널 18차] 57주차 kkr 2022.06.25 129
XE Login