void
supplemental_page_table_init (struct supplemental_page_table *spt UNUSED) {
struct hash* page_table = malloc(sizeof (struct hash));
hash_init (page_table, page_hash, page_less, NULL);
spt -> page_table = page_table;
}
struct page *
spt_find_page (struct supplemental_page_table *spt, void *va) {
struct page page;
page.va = pg_round_down (va);
struct hash_elem *e = hash_find (spt -> page_table, &page.hash_elem);
if (e == NULL) return NULL;
struct page* result = hash_entry (e, struct page, hash_elem);
ASSERT((va < result -> va + PGSIZE) && va >= result -> va);
return result;
}
bool
spt_insert_page (struct supplemental_page_table *spt,
struct page *page) {
struct hash_elem *result= hash_insert (spt -> page_table, &page -> hash_elem);
return (result == NULL) ? true : false ;
}
1) frame 구조체 생성
2) frame -> kva = palloc 할당 받기
3) frame -> kva = NULL (할당 실패시)
--> vm_evict_frame() -> vm_get_victim() -> swap_out() -> return victim
--> 제거할 page를 제거한 상태의 frame 구조체(사용가능한 frame)
static struct frame *
vm_get_frame (void) {
struct frame * frame = malloc (sizeof (struct frame));
frame -> kva = palloc_get_page (PAL_USER);
frame -> page = NULL;
ASSERT (frame != NULL);
ASSERT (frame->page == NULL);
// Add swap case handling
if (frame->kva == NULL) {
free (frame);
frame = vm_evict_frame ();
}
ASSERT (frame->kva != NULL);
return frame;
}
1) vm_get_frame() 통해 frame 생성
2) frame <-> page 연결
3) insert page table entry to map page's VA to frmae's PA
static bool
vm_do_claim_page (struct page *page) {
struct frame *frame = vm_get_frame (); /*Physical address와의 connection*/
struct thread *curr = thread_current ();
ASSERT (frame != NULL);
ASSERT (page != NULL);
/* Set links */
frame->page = page;
page->frame = frame;
// Add to frame_list for eviction clock algorithm
if (clock_elem != NULL)
// Just before current clock
list_insert (clock_elem, &frame->elem);
else
list_push_back (&frame_list, &frame->elem);
/*Insert page table entry to map page's VA to frame's PA. */
if (!pml4_set_page (curr -> pml4, page -> va, frame->kva, page -> writable))
return false;
return swap_in (page, frame->kva);
}
1) page 구조체 선언
2) spt_find_page()로 함수 인자로 받은 va에 해당하는 페이지를 spt에서 찾아 반환
3) vm_do_claim_page() 호출
bool
vm_claim_page (void *va UNUSED) {
struct page *page = spt_find_page (&thread_current () ->spt, va);
if (page == NULL) return false;
return vm_do_claim_page (page);
}