가상 주소도 읽으라던데 안읽고 와서 지금 읽는다
솔직히 읽기 싫지만 할 건 해야지 ㅇㅇ
하기 싫은 거랑 해야 할 거 구분 짓기 ㅁㅌㅊ?
가상 주소 구조부터 나온다
63 48 47 39 38 30 29 21 20 12 11 0
+-------------+----------------+----------------+----------------+-------------+------------+
| Sign Extend | Page-Map | Page-Directory | Page-directory | Page-Table | Physical |
| | Level-4 Offset | Pointer | Offset | Offset | Offset |
+-------------+----------------+----------------+----------------+-------------+------------+
| | | | |
+------- 9 ------+------- 9 ------+------- 9 ------+----- 9 -----+---- 12 ----+
Virtual Address
가상 메모리는 두 영역으로 나뉜다
사용자 가상 메모리와 커널 가상 메모리
두 영역의 경계는 KERN_BASE
로 이보다 높으면 커널, 낮으면 사용자다
메인 코스다
가상 메모리 관련 매크로들 설명 나온다
잘 기억하거나 어디다 정리해놓은 뒤 애용해주자
#define PGSHIFT
#define PGBITS
가상 주소의 오프셋 부분의 비트 시작 인덱스(0)와 비트 수(12)를 각각 의미
#define PGMASK
페이지 오프셋 비트들만 1로, 나머지는 0으로 설정된 비트 마스크(0xfff)
#define PGSIZE
페이지 크기(바이트) — 4,096
#define pg_ofs(va)
가상 주소 va
에서 페이지 오프셋을 추출해 반환
#define pg_no(va)
가상 주소 va
에서 페이지 번호를 추출해 반환
#define pg_round_down(va)
va
가 속한 가상 페이지의 시작 주소(오프셋을 0으로 만든 값)를 반환
#define pg_round_up(va)
va
를 가장 가까운 페이지 경계까지 올림한 값을 반환
참고로 Omit details는 걍 생략했다는 뜻이다 (소곤소곤)
#define KERN_BASE
커널 가상 메모리의 기준(base) 주소
기본값은 0x8004000000
사용자 가상 메모리는 가상 주소 0부터 KERN_BASE
직전까지이며, 커널 가상 메모리는 그 나머지 전체를 차지
#define is_user_vaddr(vaddr)
#define is_kernel_vaddr(vaddr)
각각 va가 사용자/커널 가상 주소인지 여부를 true/false
로 반환
x86-64에선 물리 주소로 직접 가상메모리 접근하는 방법이 없어
커널 가상 메모리와 물리 메모리 1:1 매핑하는 방식으로 이를 해결
관련 함수:
#define ptov(paddr)
물리 주소 pa
(0 이상, 물리 메모리 크기 이하)에 대응하는 커널 가상 주소를 반환
#define vtop(vaddr)
커널 가상 주소 va
에 대응하는 물리 주소를 반환
#define is_user_pte(pte)
#define is_kern_pte(pte)
PTE(페이지 테이블 엔트리)가 각각 사용자/커널 소유인지 확인
#define is_writable(pte)
PTE가 가리키는 가상 주소가 쓰기 가능한지 확인
typedef bool pte_for_each_func (uint64_t *pte, void *va, void *aux);
bool pml4_for_each (uint64_t *pml4, pte_for_each_func *func, void *aux);
프로젝트 3까지는 가야 쓰인다고 하니 이번에는 스킵하겠다
프로젝트 3 가서 다시 보자