
include/vm/vm.h 및 vm/vm.c에 위치VM_UNINIT / vm/uninit.c / include/vm/uninit.hVM_ANON / vm/anon.c / /include/vm/anon.hVM_FILE / vm/file.c / /include/vm/file.hPGSIZE)의 연속된 영역의 가상 메모리 영역 +---------- +
.--------------->|페이지 테이블|------------.
/ +---------- + |
| 12 11 0 V 12 11 0
+---------+----+ +---------+-----+
| 페이지번호 | 오프셋 | |프레임번호 | 오프셋|
+---------+----+ +---------+----+
가상주소 | 물리주소 ^
\_______________________________________/
63 48 47 39 38 30 29 21 20 12 11 0
+-------------+----------------+----------------+----------------+-------------+------------+
| Sign Extend | PML4 Offset | PDPT Offset | PD Offset | PT Offset | Page Offset|
+-------------+----------------+----------------+----------------+-------------+------------+
| 9 bits | 9 bits | 9 bits | 9 bits | 12 bits |
Page Offset을 더해 최종 물리 주소 계산PML4 Offset ~ Page-Table Offset: 4개의 필드를 합쳐 가상 페이지 번호라고도 함Page Offset 12 11 0
+-----------------------+-----------+
| Frame Number | Offset |
+-----------------------+-----------+
| 필드명 | 비트 범위 | 값 |
|---|---|---|
| Sign Extend | 16비트 | 0x0000 |
| PML4 Offset | 9비트 | 0x1FF (=511) |
| PDP Offset | 9비트 | 0x1FF (=511) |
| PD Offset | 9비트 | 0x1FF (=511) |
| PT Offset | 9비트 | 0x1FF (=511) |
| Page Offset | 12비트 | 0xFFF (=4095) |
0xFFF)을 붙여 최종 물리 주소 계산0인 경우 Page Faultis_writable(pte)로 확인is_user_pte(pte), is_kern_pte(pte)로 확인KERN_BASE (0x8004000000) 미만KERN_BASE (0x8004000000) 이상is_user_vaddr(vaddr), is_kern_vaddr(vaddr) 사용paging_init)물리 주소 + KERN_BASE = 커널 가상주소가 됨에 유의ptov(paddr), vtop(vaddr)로 계산 가능palloc_get_page() 역시 물리 메모리에서 페이지를 할당하지만, 실제론 이에 대응되는 커널 가상주소 반환palloc, 즉 page allocator는 물리 메모리에서 page(4096바이트)만큼의 물리 프레임을 할당pml4_set_page 등 사용해 페이지 테이블에서 user 영역의 가상 주소와 매핑되며, supervisor 비트는 1이 됨void *palloc_get_page(enum palloc_flags flags): 할당된 프레임(의 커널 가상) 주소 반환PAL_ZERO: 물리 프레임의 모든 바이트를 0 처리PAL_USER: USER POOL에서 할당. 없을 시 KERNEL POOL에서 할당됨.malloc(), calloc() 등 함수도 핀토스 커널에서 사용 가능 -> 무조건 kernel pool에서 할당매개변수 pml4는 pml4 테이블의 포인터.
매개변수 uaddr, upage, vpage는 가상 주소로, 페이지 테이블에 의해 물리 주소와 매핑됨
uaddr은 아무런 주소든 상관없지만, upage/vpage는 무조건 페이지의 시작주소여야 함void * pml4_get_page(uint64_t *pml4, const void *uaddr)
pml4에서 가상 주소 uaddr에 매핑된 물리 프레임(의 커널 가상)주소 반환KERN_BASE)uaddr이 속한 페이지에 물리 프레임이 매핑되지 않은 경우, NULL 반환 (present bit로 확인)bool pml4_set_page(uint64_t *pml4, void *upage, void *kpage, bool rw)
pml4 테이블에 가상 페이지 upage와 믈리 프레임 kpage의 매핑 추가kpage는 물리 주소가 아닌, 이에 대응하는 커널가상주소 (물리주소 + KERN_BASE)upage는 이미 매핑된 페이지여선 안됨 (valid bit로 확인)kpage는 palloc_get_page()로 user pool에서 할당된 커널 가상 주소여야 함rw가 true면 쓰기 가능, false면 읽기 전용 (writable bit 수정)void pml4_clear_page(uint64_t *pml4, void *upage)
upage에 대응하는 페이지 테이블 엔트리의 present 비트를 0으로 설정 -> 매핑을 해제하는 용도bool pml4_is_dirty(uint64_t *pml4, const void *vpage)
vpage에 대응하는 페이지 테이블 엔트리의 dirty 비트 확인void pml4_set_dirty(uint64_t *pml4, const void *vpage, bool dirty)로 재설정bool pml4_is_accessed(uint64_t *pml4, const void *vpage)
vpage에 해당하는 페이지 테이블 엔트리의 accessed 비트 확인void pml4_set_accessed(uint64_t *pml4, const void *vpage, bool dirty)로 재설정[구현] vm/vm.c의 vm_try_handle_fault() 수정해야 함
(1) Supplemental P.T.에서 page fault가 발생한 가상 주소를 확인
(2) 물리 메모리에서 프레임 할당
(3) 할당된 프레임에 데이터 로딩
(4) 페이지테이블 엔트리 갱신
threads/mmu.c 사용하기mmap 시스템 콜을 구현하게 됨