[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
vm.c File Reference
#include "threads/malloc.h"
#include "vm/vm.h"
#include "vm/inspect.h"
#include "threads/vaddr.h"
#include "threads/mmu.h"
#include "userprog/process.h"
Include dependency graph for vm.c:

Functions

static unsigned hash_func (const struct hash_elem *e, void *aux UNUSED)
 
static unsigned less_func (const struct hash_elem *a, const struct hash_elem *b, void *aux)
 
static bool insert_page (struct hash *h, struct page *p)
 
static bool delete_page (struct hash *h, struct page *p)
 
static void spt_destroy (struct hash_elem *e, void *aux)
 
void vm_init (void)
 
enum vm_type page_get_type (struct page *page)
 
static struct framevm_get_victim (void)
 
static bool vm_do_claim_page (struct page *page)
 
static struct framevm_evict_frame (void)
 
bool vm_alloc_page_with_initializer (enum vm_type type, void *upage, bool writable, vm_initializer *init, void *aux)
 
struct pagespt_find_page (struct supplemental_page_table *spt UNUSED, void *va UNUSED)
 
bool spt_insert_page (struct supplemental_page_table *spt UNUSED, struct page *page UNUSED)
 
void spt_remove_page (struct supplemental_page_table *spt, struct page *page)
 
static struct framevm_get_frame (void)
 
static void vm_stack_growth (void *addr UNUSED)
 
static bool vm_handle_wp (struct page *page UNUSED)
 
bool vm_try_handle_fault (struct intr_frame *f UNUSED, void *addr UNUSED, bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
 
void vm_dealloc_page (struct page *page)
 
bool vm_claim_page (void *va UNUSED)
 
void supplemental_page_table_init (struct supplemental_page_table *spt UNUSED)
 
bool supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED, struct supplemental_page_table *src UNUSED)
 
void supplemental_page_table_kill (struct supplemental_page_table *spt UNUSED)
 

Variables

static struct list frame_table
 

Function Documentation

◆ delete_page()

static bool delete_page ( struct hash h,
struct page p 
)
static
474 {
475 if(!hash_delete(h, &p->hash_elem))
476 return true;
477 else
478 return false;
479}
struct hash_elem * hash_delete(struct hash *, struct hash_elem *)
Definition: hash.c:137
struct hash_elem hash_elem
Definition: vm.h:58
Here is the call graph for this function:

◆ hash_func()

static unsigned hash_func ( const struct hash_elem e,
void *aux  UNUSED 
)
static
439 {
440 const struct page *p = hash_entry(e, struct page, hash_elem); // hash 테이블이 hash_elem을 원소로 가지고 있으므로 페이지 자체에 대한 정보를 가져온다.
441 return hash_bytes(&p->va, sizeof(p->va)); // 인덱스를 리턴해야하므로 hash_bytes를 리턴한다.
442}
#define hash_entry(HASH_ELEM, STRUCT, MEMBER)
Definition: hash.h:38
uint64_t hash_bytes(const void *, size_t)
Definition: hash.c:246
Definition: hash.h:29
Definition: vm.h:51
void * va
Definition: vm.h:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert_page()

static bool insert_page ( struct hash h,
struct page p 
)
static
462 {
463 if(!hash_insert(h, &p->hash_elem))
464 return true;
465 else
466 return false;
467}
struct hash_elem * hash_insert(struct hash *, struct hash_elem *)
Definition: hash.c:94
Here is the call graph for this function:
Here is the caller graph for this function:

◆ less_func()

static unsigned less_func ( const struct hash_elem a,
const struct hash_elem b,
void *  aux 
)
static
452 {
453 const struct page *a_p = hash_entry(a, struct page, hash_elem);
454 const struct page *b_p = hash_entry(b, struct page, hash_elem);
455 return a_p->va < b_p->va; // b_p가 크면 true 반환
456}
Here is the caller graph for this function:

◆ page_get_type()

enum vm_type page_get_type ( struct page page)
43 {
44 int ty = VM_TYPE (page->operations->type);
45 switch (ty) {
46 case VM_UNINIT:
47 return VM_TYPE (page->uninit.type);
48 default:
49 return ty;
50 }
51}
enum vm_type type
Definition: vm.h:103
const struct page_operations * operations
Definition: vm.h:52
struct uninit_page uninit
Definition: vm.h:67
enum vm_type type
Definition: uninit.h:15
#define VM_TYPE(type)
Definition: vm.h:43
@ VM_UNINIT
Definition: vm.h:11
Here is the caller graph for this function:

◆ spt_destroy()

static void spt_destroy ( struct hash_elem e,
void *  aux 
)
static
482 {
483 const struct page *p = hash_entry(e, struct page, hash_elem);
484 free(p);
485}
void free(void *)
Definition: malloc.c:202
Here is the call graph for this function:
Here is the caller graph for this function:

◆ spt_find_page()

struct page * spt_find_page ( struct supplemental_page_table *spt  UNUSED,
void *va  UNUSED 
)
117 {
118 // struct page *page = NULL;
119 /* TODO: Fill this function. */
120 /*
121 * va를 통해 page를 찾아야하는데, hash_find의 인자는 hash_elem이므로 이에 해당하는 hash_elem을 만들어준다.
122 *
123 * 1. dummy page 생성(hash_elem 포함)
124 * 2. va 매핑
125 * 3. 해당 페이지와 같은 해시 값을 갖는 hash_elem을 찾는다.
126 */
127 /*-------------------------[P3]hash table---------------------------------*/
128 // 인자로 받은 va에 해당하는 vm_entry를 검색 후 반환
129 // 가상 메모리 주소에 해당하는 페이지 번호 추출 (pg_round_down())
130 // hash_find() 함수를 이용하여 vm_entry 검색 후 반환
131
132 struct page *page = (struct page*)malloc(sizeof(struct page)); // 임의의 페이지 만들어주기
133 // ↳ page를 새로 만들어주는 이유? : 해당 가상 주소에 대응하는 해시 값 도출을 위함
134 // page 생성 시, hash_elem도 생성된다.
135 struct hash_elem *e;
136
137 // 인자로 받은 spt내에서 va를 키로 전달해 이를 갖는 page 리턴
138 // hash_find로 부터 해당 page를 찾을 수 있음 (p->value : key, struct page: value)
139 // spt의 hash 테이블 구조체를 인자로 넣어야 하는데 va만 인자로 받아왔기 때문에,
140 // dummy 페이지를 만들고 해당 페이지의 가상주소를 va로 만듦
141 // va가 속해있는 페이지 시작 주소를 갖는 page를 만듦(pg_round_down)
142 page->va = pg_round_down(va);
143 /* e와 같은 해시값을 갖는 page를 spt에서 찾은 다음 해당 hash_elem을 리턴 */
144 e = hash_find(&spt->spt_hash, &page->hash_elem);
145 free(page);
146
147 if (e == NULL)
148 return NULL;
149 else
150 return hash_entry(e, struct page, hash_elem); // e에 해당하는 page 리턴
151 /*-------------------------[P3]hash table---------------------------------*/
152}
struct hash_elem * hash_find(struct hash *, struct hash_elem *)
Definition: hash.c:125
void * malloc(size_t) __attribute__((malloc))
Definition: malloc.c:85
#define NULL
Definition: stddef.h:4
#define pg_round_down(va)
Definition: vaddr.h:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ spt_insert_page()

bool spt_insert_page ( struct supplemental_page_table *spt  UNUSED,
struct page *page  UNUSED 
)
158 {
159 return insert_page(&spt -> spt_hash, page);
160}
static bool insert_page(struct hash *h, struct page *p)
Definition: vm.c:462
Here is the call graph for this function:
Here is the caller graph for this function:

◆ spt_remove_page()

void spt_remove_page ( struct supplemental_page_table spt,
struct page page 
)
163 {
165 return true;
166}
void vm_dealloc_page(struct page *page)
Definition: vm.c:309
Here is the call graph for this function:

◆ supplemental_page_table_copy()

bool supplemental_page_table_copy ( struct supplemental_page_table *dst  UNUSED,
struct supplemental_page_table *src  UNUSED 
)
358 {
359 struct thread *curr = thread_current(); // (현재 실행중인)자식 프로세스
360
361 struct hash_iterator i; // 부모의 해쉬 테이블을 순회하기 위한 iterator
362 hash_first (&i, &src->spt_hash);
363 while (hash_next (&i)) {
364 struct page *parent_page = hash_entry (hash_cur (&i), struct page, hash_elem); // 복사하려는 부모 페이지
365 enum vm_type parent_type = parent_page->operations->type; // 부모 페이지의 타입에 따라 조건문을 분기한다.
366
367 // CASE 1. UNINIT 페이지인 경우 -> ANON 또는 FILE로 페이지 타입 결정
368 // ↳ 페이지만
369 if(parent_type == VM_UNINIT){
370 if(!vm_alloc_page_with_initializer(parent_page->uninit.type, parent_page->va, \
371 parent_page->writable, parent_page->uninit.init, parent_page->uninit.aux))
372 return false;
373 }
374 // CASE 2. UNINIT 페이지가 아닌 경우
375 // ↳ 페이지 + 프레임
376 else {
377 // CASE 2-1. 스택 페이지인 경우, 자식 프로세스에게도 스택 설정을 해줌
378 // setup_stack : 페이지 할당 + 프레임 할당 + stack_bottom 설정
379 if (parent_type & VM_MARKER_0)
380 setup_stack(&thread_current()->tf); // setup_stack's param : intr_frame
381 // CASE 2-2. 스택 페이지 이외의 경우
382 // 페이지 할당 + 프레임 할당
383 else
384 if(!vm_alloc_page(parent_type, parent_page->va, parent_page->writable)) // 페이지 할당
385 return false;
386 if(!vm_claim_page(parent_page->va)) // 프레임 할당
387 return false;
388
389 // 부모의 프레임을 자식 프레임으로 복사한다.
390 struct page* child_page = spt_find_page(dst, parent_page->va);
391 memcpy(child_page->frame->kva, parent_page->frame->kva, PGSIZE); // 부모 프레임 그대로 복사
392 }
393 }
394 return true;
395}
void hash_first(struct hash_iterator *, struct hash *)
Definition: hash.c:187
struct hash_elem * hash_cur(struct hash_iterator *)
Definition: hash.c:224
struct hash_elem * hash_next(struct hash_iterator *)
Definition: hash.c:205
bool setup_stack(struct intr_frame *if_)
Definition: process.c:673
void * memcpy(void *, const void *, size_t)
Definition: string.c:7
void * kva
Definition: vm.h:78
Definition: hash.h:68
bool writable
Definition: vm.h:60
struct frame * frame
Definition: vm.h:54
Definition: thread.h:100
void * aux
Definition: uninit.h:16
vm_initializer * init
Definition: uninit.h:14
struct thread * thread_current(void)
Definition: thread.c:301
#define PGSIZE
Definition: vaddr.h:20
struct page * spt_find_page(struct supplemental_page_table *spt UNUSED, void *va UNUSED)
Definition: vm.c:117
bool vm_alloc_page_with_initializer(enum vm_type type, void *upage, bool writable, vm_initializer *init, void *aux)
Definition: vm.c:74
bool vm_claim_page(void *va UNUSED)
Definition: vm.c:316
#define vm_alloc_page(type, upage, writable)
Definition: vm.h:135
vm_type
Definition: vm.h:8
@ VM_MARKER_0
Definition: vm.h:26
Here is the call graph for this function:

◆ supplemental_page_table_init()

void supplemental_page_table_init ( struct supplemental_page_table *spt  UNUSED)
348 {
349 /*-------------------------[P3]hash table---------------------------------*/
350 hash_init(&spt->spt_hash, hash_func, less_func, NULL);
351 /*-------------------------[P3]hash table---------------------------------*/
352}
bool hash_init(struct hash *, hash_hash_func *, hash_less_func *, void *aux)
Definition: hash.c:25
static unsigned less_func(const struct hash_elem *a, const struct hash_elem *b, void *aux)
Definition: vm.c:452
static unsigned hash_func(const struct hash_elem *e, void *aux UNUSED)
Definition: vm.c:439
Here is the call graph for this function:

◆ supplemental_page_table_kill()

void supplemental_page_table_kill ( struct supplemental_page_table *spt  UNUSED)
399 {
400 /* TODO: Destroy all the supplemental_page_table hold by thread and
401 * TODO: writeback all the modified contents to the storage. */
402 /* TODO: 스레드별로 소유하고 있는 모든 spt를 삭제하고 수정된 모든 내용을 저장소에 다시 기록
403 */
404 /*-------------------------[P3]Anonymous---------------------------------*/
405 // hash 엔트리 각각에 대해 메모리를 해제한다.
406 // if (&spt->spt_hash == NULL)
407 // return;
408 // hash_destroy(&spt->spt_hash, spt_destroy);
409 /*-------------------------[P3]Anonymous---------------------------------*/
410
411 /*-------------------------[P3]mmf---------------------------------*/
412 // VM_FILE 타입 추가에 따른 exit -> 'mmap va'제거 수행
413 struct hash_iterator i;
414
415 if (&spt->spt_hash == NULL)
416 return;
417
418 hash_first (&i, &spt->spt_hash);
419 while (hash_next (&i)) {
420 struct page *page = hash_entry (hash_cur (&i), struct page, hash_elem);
421
422 if (page_get_type(page) == VM_FILE)
423 do_munmap(page->va);
424
425 }
426 hash_destroy(&spt->spt_hash, spt_destroy);
427 /*-------------------------[P3]mmf---------------------------------*/
428
429}
void hash_destroy(struct hash *, hash_action_func *)
Definition: hash.c:81
void do_munmap(void *va)
Definition: file.c:124
static void spt_destroy(struct hash_elem *e, void *aux)
Definition: vm.c:482
enum vm_type page_get_type(struct page *page)
Definition: vm.c:43
@ VM_FILE
Definition: vm.h:17
Here is the call graph for this function:

◆ vm_alloc_page_with_initializer()

bool vm_alloc_page_with_initializer ( enum vm_type  type,
void *  upage,
bool  writable,
vm_initializer init,
void *  aux 
)
76{
77 ASSERT (VM_TYPE(type) != VM_UNINIT) // vm_type은 VM_ANON과 VM_FILE만 가능하다.
78
80
81 /* Check wheter the upage is already occupied or not. */
82 if (spt_find_page (spt, upage) == NULL) {
83 // ↳ upage라는 가상 메모리에 매핑되는 페이지 존재 x -> 새로 만들어야함
84 /* TODO: Create the page, fetch the initialier according to the VM type,
85 * TODO: and then create "uninit" page struct by calling uninit_new. You
86 * TODO: should modify the field after calling the uninit_new.
87 * 페이지를 만들고 vm유형에 따라 이니셜을 가져온 다음 uninit_new를 호출하여 uninit 페이지 구조를 만듦
88 * uninit_new를 호출한 후 필드를 수정해야 함*/
89 /*-------------------------[P3]Anonoymous page---------------------------------*/
90 struct page* pg = calloc(1, sizeof(struct page)); // ! malloc -> calloc
91
92 // 페이지 타입에 따라 initializer가 될 초기화 함수를 매칭해준다.
93 typedef bool (*initializer_by_type)(struct page *, enum vm_type, void *);
94 initializer_by_type initializer = NULL;
95
96 if(VM_TYPE(type) == VM_ANON)
97 initializer = anon_initializer;
98 else if(VM_TYPE(type) == VM_FILE)
99 initializer = file_backed_initializer;
100
101 uninit_new(pg, upage, init, type, aux, initializer); // UNINIT 페이지 생성
102 // ↳ page를 uninit으로 만들어서 spt에 올려두는 과정(실제 type을 올림)
103 // page 구조체의 pg,upage: 주소, init: lazy_load, type: 타입, initializer: 타입에 따른 함수(anon_initializer 또는 file_backed_initializer)
104
105 /* TODO: Insert the page into the spt. */
106 pg->writable = writable;
107 spt_insert_page(spt, pg);
108 return true;
109 /*-------------------------[P3]Anonoymous page---------------------------------*/
110 }
111err:
112 return false;
113}
bool anon_initializer(struct page *page, enum vm_type type, void *kva)
Definition: anon.c:37
#define ASSERT(CONDITION)
Definition: debug.h:30
void * calloc(size_t, size_t) __attribute__((malloc))
Definition: malloc.c:149
#define bool
Definition: stdbool.h:4
Definition: vm.h:115
struct supplemental_page_table spt
Definition: thread.h:143
void uninit_new(struct page *page, void *va, vm_initializer *init, enum vm_type type, void *aux, bool(*initializer)(struct page *, enum vm_type, void *kva))
static void init(void)
Definition: vga.c:36
bool file_backed_initializer(struct page *page, enum vm_type type, void *kva)
Definition: file.c:26
bool spt_insert_page(struct supplemental_page_table *spt UNUSED, struct page *page UNUSED)
Definition: vm.c:157
@ VM_ANON
Definition: vm.h:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_claim_page()

bool vm_claim_page ( void *va  UNUSED)
316 {
317 struct thread *curr = thread_current();
318 /* TODO: Fill this function */
319 struct page *page = spt_find_page(&curr -> spt, va); // va에 해당하는 페이지가 존재하는지 확인한다.
320 if (page == NULL)
321 return false;
322
323 return vm_do_claim_page (page); // 해당 페이지에 프레임을 할당한다.
324}
static bool vm_do_claim_page(struct page *page)
Definition: vm.c:328
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_dealloc_page()

void vm_dealloc_page ( struct page page)
309 {
310 destroy (page);
311 free (page);
312}
#define destroy(page)
Definition: vm.h:108
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_do_claim_page()

static bool vm_do_claim_page ( struct page page)
static
328 {
329 struct frame *frame = vm_get_frame (); // 프레임 하나를 얻는다.
330
331 /* Set links */
332 frame->page = page; // 프레임의 페이지(가상)로 얻은 페이지를 연결해준다.
333 page->frame = frame; // 페이지의 물리적 주소로 얻은 프레임을 연결해준다.
334
335 /* TODO: Insert page table entry to map page's VA to frame's PA. */
336 struct thread *curr = thread_current();
337 bool writable = page -> writable; // 해당 페이지의 R/W 여부
338 pml4_set_page(curr->pml4, page->va, frame->kva, writable); // 현재 페이지 테이블에 가상 주소에 따른 frame 매핑
339
340 return swap_in (page, frame->kva);
341}
bool pml4_set_page(uint64_t *pml4, void *upage, void *kpage, bool rw)
Definition: mmu.c:240
Definition: vm.h:77
struct page * page
Definition: vm.h:79
uint64_t * pml4
Definition: thread.h:121
static struct frame * vm_get_frame(void)
Definition: vm.c:218
#define swap_in(page, v)
Definition: vm.h:106
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_evict_frame()

static struct frame * vm_evict_frame ( void  )
static
196 {
197 struct frame *victim UNUSED = vm_get_victim ();
198 /* TODO: swap out the victim and return the evicted frame. */
199 /*-------------------------[P3]frame table---------------------------------*/
200 if(victim->page != NULL){
201 swap_out(victim -> page);
202 return victim;
203 }
204 /*-------------------------[P3]frame table---------------------------------*/
205
206 return NULL;
207}
#define UNUSED
Definition: debug.h:7
static struct frame * vm_get_victim(void)
Definition: vm.c:170
#define swap_out(page)
Definition: vm.h:107
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_get_frame()

static struct frame * vm_get_frame ( void  )
static
218 { //프레임 할당
219 /* TODO: Fill this function. */
220 /*-------------------------[P3]frame table---------------------------------*/
221 // struct frame *frame = NULL;
222
223 struct frame *frame = (struct frame*)malloc(sizeof(struct frame));
224 // frame 구조체를 위한 공간 할당한다.(작으므로 malloc으로 _Gitbook Memory Allocation 참조)
225
227 // 사용 가능한 단일 페이지(물리적 페이지)를 가져온다.
228 // ↳ 사용 가능한 페이지가 없을 경우, NULL 리턴
229 if(frame->kva == NULL) { // 사용 가능한 페이지가 없는 경우
230 frame = vm_evict_frame(); // swap out 수행 (frame을 내쫓고 해당 공간을 가져온다.)
231 frame->page = NULL;
232
233 return frame; // 무조건 유효한 주소만 리턴한다는 말이 통하는 이유 : swap out을 통해 공간 확보후, 리턴하기 떄문
234 }
235 list_push_back (&frame_table, &frame->frame_elem); // 새로 frame을 생성한 경우
236 frame->page = NULL;
237 /*-------------------------[P3]frame table---------------------------------*/
238 ASSERT (frame != NULL);
239 ASSERT (frame->page == NULL);
240 return frame;
241}
void list_push_back(struct list *, struct list_elem *)
Definition: list.c:202
@ PAL_USER
Definition: palloc.h:11
void * palloc_get_page(enum palloc_flags)
Definition: palloc.c:301
struct list_elem frame_elem
Definition: vm.h:81
static struct frame * vm_evict_frame(void)
Definition: vm.c:196
static struct list frame_table
Definition: vm.c:12
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_get_victim()

static struct frame * vm_get_victim ( void  )
static
170 {
171 struct frame *victim = NULL;
172 /* TODO: The policy for eviction is up to you. */
173 /*-------------------------[P3]frame table---------------------------------*/
174 // victim = list_entry(list_pop_front(&frame_table), struct frame, frame_elem);
175
176 struct thread *curr = thread_current();
177 struct list_elem *frame_e;
178
179 // LRU 방식
180 // frame table의 처음과 끝을 순회하면서 access bit가 0인 프레임을 찾는다.
181 for (frame_e = list_begin(&frame_table); frame_e != list_end(&frame_table); frame_e = list_next(frame_e)) {
182 victim = list_entry(frame_e, struct frame, frame_elem);
183 if (pml4_is_accessed(curr->pml4, victim->page->va)) // access bit가 1이라면 true
184 pml4_set_accessed (curr->pml4, victim->page->va, 0); // access bit를 초기화 해준다.
185 else
186 return victim;
187 }
188 /*-------------------------[P3]frame table---------------------------------*/
189
190 return victim;
191}
struct list_elem * list_begin(struct list *)
Definition: list.c:68
struct list_elem * list_next(struct list_elem *)
Definition: list.c:77
struct list_elem * list_end(struct list *)
Definition: list.c:88
#define list_entry(LIST_ELEM, STRUCT, MEMBER)
Definition: list.h:103
void pml4_set_accessed(uint64_t *pml4, const void *upage, bool accessed)
Definition: mmu.c:311
bool pml4_is_accessed(uint64_t *pml4, const void *upage)
Definition: mmu.c:303
Definition: list.h:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_handle_wp()

static bool vm_handle_wp ( struct page *page  UNUSED)
static
261 {
262}

◆ vm_init()

void vm_init ( void  )
25 {
26 vm_anon_init ();
27 vm_file_init ();
28#ifdef EFILESYS /* For project 4 */
30#endif
32 /* DO NOT MODIFY UPPER LINES. */
33 /* TODO: Your code goes here. */
34 list_init(&frame_table); // frame_table에 대한 초기화
35}
void vm_anon_init(void)
Definition: anon.c:28
void register_inspect_intr(void)
Definition: inspect.c:21
void list_init(struct list *)
Definition: list.c:58
void pagecache_init(void)
Definition: page_cache.c:20
void vm_file_init(void)
Definition: file.c:21
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_stack_growth()

static void vm_stack_growth ( void *addr  UNUSED)
static
245 {
246 /* vm_try_handler 수정해서 stack growth인 경우 함수를 호출하도록 처리
247 0. 증가 시점 : 할당해주지 않은 페이지에 rsp가 접근했을 때 : stack growth에 대한 page_fault 발생시
248 1. stack_bottom 설정
249 2. 확장 요청한 스택 사이즈 확인
250 3. 스택 확장시, page 크기 단위로 해주기
251 4. 확장한 페이지 할당 받기
252 * 커널에서 페이지 폴트 발생시, intr_frame 내의 rsp는 유저스택 포인터가 아닌 쓰레기 값을 가짐 -> 커널에서 발생시 유저 스택 포인터를 thread 구조체에 저장*/
253 if(vm_alloc_page(VM_ANON | VM_MARKER_0, addr, 1)) { // 스택 마커 다시 표시
254 vm_claim_page(addr); // 페이지, 프레임 연결
255 thread_current()->stack_bottom -= PGSIZE; // 증가된 스택 사이즈 만큼 stack_bottom 옮겨주기
256 }
257}
void * stack_bottom
Definition: thread.h:144
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vm_try_handle_fault()

bool vm_try_handle_fault ( struct intr_frame *f  UNUSED,
void *addr  UNUSED,
bool user  UNUSED,
bool write  UNUSED,
bool not_present  UNUSED 
)
267 {
268
270 static void *STACK_MINIMUM_ADDR = USER_STACK - (1 << 20); // 스택 최대 크기(주소 하한선) -> 1MB
271 // ↳ 스택은 아래로 증가하기 때문 (Ref. Gitbook)
272 // struct page *page = NULL;
273 /* TODO: Validate the fault */
274 /* TODO: Your code goes here */
275
276 /* page_fault로 부터 넘어온 인자
277 * f : 페이지 폴트 발생 순간의 레지스터 값들을 담고 있는 구조체
278 * addr : 페이지 폴트를 일으킨 가상주소
279 * not_present : 페이지 존재 x (bogus fault), false인 경우 read-only페이지에 write하려는 상황
280 * user : 유저에 의한 접근(true), 커널에 의한 접근(false) - rsp 값이 유저 영역인지 커널영역인지
281 * write : 쓰기 목적 접근(true), 읽기 목적 접근(false)
282 */
283 // page fault 주소에 대한 유효성 검증
284 // 커널 가상 주소 공간에 대한 폴트 처리 불가, 사용자 요청에 대한 폴트 처리 불가
285 if (is_kernel_vaddr (addr) && user) // real fault
286 return false;
287
288 // f->rsp가 커널 주소라면 rsp_stack, 아니면 f->rsp
289 // 페이지 폴트가 발생한 스택 포인터 유저 스택인지, 커널 스택인지 확인하는 과정
290 // CHECK origin_code : is_kernel_vaddr(f->rsp) ? thread_current()->rsp_stack : f->rsp;
291 void *rsp_stack = f->rsp;
292 if (not_present){
293 if (!vm_claim_page(addr)){ // 스택을 증가 시켜야하는 경우, 즉 spt에 현재 할당된 스택 영역을 넘거가는 경우
294 if (rsp_stack - sizeof(void*) == addr && STACK_MINIMUM_ADDR <= addr && addr <= USER_STACK) {
295 vm_stack_growth(thread_current()->stack_bottom - PGSIZE);
296 return true;
297 }
298 return false;
299 }
300 else
301 return true;
302 }
303 return false;
304}
#define is_kernel_vaddr(vaddr)
Definition: vaddr.h:44
#define USER_STACK
Definition: vaddr.h:38
static void vm_stack_growth(void *addr UNUSED)
Definition: vm.c:245
Here is the call graph for this function:

Variable Documentation

◆ frame_table

struct list frame_table
static