vm_try_handle_fault() - sihyun10/pintos-lab-vm GitHub Wiki
vm_try_handle_fault() ํจ์ ๊ตฌํ
์ด ํจ์๋ Page Fault
๊ฐ ๋ฐ์ํ์ ๋, ํด๋น ํ์ด์ง๊ฐ ์ ์์ ์ธ ์ ๊ทผ์ธ์ง ํ๋จํ๊ณ ,
ํ์ํ ๊ฒฝ์ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ฉ๊น์ง ์ํํ๋ค.
์ฆ, ๋ณต๊ตฌ ๊ฐ๋ฅํ ํ์ด์ง ํดํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์์ด๋ค.
์ฑ๊ณต ์ true
, ์คํจ์ false
๋ฅผ ๋ฐํํ๋ค.
/* Return true on success */
bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED,
bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
{
struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
struct page *page = NULL;
/* TODO: Validate the fault */
/* TODO: Your code goes here */
return vm_do_claim_page(page);
}
๐ To do
- ์์ธ์ ์ธ ์ฃผ์ ํ์ธ
- ์ ๊ทผํ ์ฃผ์(
addr
)์ ๋ํด SPT(Supplemental Page Table
)์ ํ์ด์ง๊ฐ ๋ฑ๋ก๋์ด ์๋์ง ํ์ธ - ๋ง์ฝ ํด๋น ์ฃผ์์ ๋ํ ํ์ด์ง๊ฐ ์กด์ฌํ๋ค๋ฉด, ํ๋ ์์ ํ ๋นํ๊ณ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ฉ
- ์์ธ์ ์ธ ์ ๊ทผ(
์ฝ๊ธฐ ์ ์ฉ ํ์ด์ง์ ์ฐ๊ธฐ ์๋
)์ ๋ง์์ผํจ. - ์ฌ๋ฐ๋ฅธ ์ ๊ทผ์ธ ๊ฒฝ์ฐ, ํ์ด์ง๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋งคํํด์ฃผ๊ณ , ์ฑ๊ณต ์ฌ๋ถ ๋ฐํ
์์ธ์ ์ธ ์ฃผ์ ํ์ธ
์ ๊ทผํ ์ฃผ์๊ฐ ์๋ชป๋ ์ฃผ์์ธ์ง ๊ฒ์ฌํ๋ค.
if (addr == NULL || is_kernel_vaddr(addr))
return false;
์์ธ ์กฐ๊ฑด : NULL
ํฌ์ธํฐ, ์ปค๋ ์ฃผ์ ๊ณต๊ฐ์ ์ ๊ทผํ ์ฌ์ฉ์ ์ ๊ทผ
์ด๋ฌํ ๊ฒฝ์ฐ๋ ๋ณต๊ตฌํ ์ ์๋ ์ ๊ทผ์ด๋ฏ๋ก false
๋ฅผ ๋ฐํํ์ฌ
์ดํ page_fault()
์์ exit(-1)
๋ก ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃ์ํจ๋ค.
userprog/exception.c
[์ฐธ๊ณ ] - #ifdef VM
/* For project 3 and later. */
if (vm_try_handle_fault(f, fault_addr, user, write, not_present))
return;
#endif
/* Count page faults. */
page_fault_cnt++;
/* If the fault is true fault, show info and exit. */
printf("Page fault at %p: %s error %s page in %s context.\n",
fault_addr,
not_present ? "not present" : "rights violation",
write ? "writing" : "reading",
user ? "user" : "kernel");
exit(-1); // ์ฌ๊ธฐ์ ์ฒ๋ฆฌ!!!
kill(f);
}
not_present == true
)
์ ๊ทผํ ํ์ด์ง๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์์ ๊ฒฝ์ฐ (not_present == true
์ธ ๊ฒฝ์ฐ๋ ํด๋น ํ์ด์ง๋ ํ์ฌ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ์๋ค๋ ๋ป์ด๋ค.
์ด ๊ฒฝ์ฐ SPT๋ฅผ ํตํด ์ ๋ณด๋ฅผ ์ฐพ์ ๋ณต๊ตฌ ๊ฐ๋ฅํ๋ฉด ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ๋งคํํด์ค๋ค.
if (not_present)
{
struct page *page = spt_find_page(spt, addr);
if (page == NULL)
return false;
if (write && !page->writable)
return false;
return vm_do_claim_page(page);
}
[์ฃผ์์ ํด๋นํ๋ ํ์ด์ง ํ์]
๋จผ์ , ์ฃผ์์ ํด๋นํ๋ ํ์ด์ง ํ์์ ํ๋ค.
โ ํ์ฌ ์ค๋ ๋์ SPT์์ ํด๋น ์ฃผ์์ ํ์ด์ง ์ ๋ณด๋ฅผ ์ฐพ๋๋ค.
SPT์ ๋ฑ๋ก๋์ง ์์ ์ฃผ์๋ผ๋ฉด ๋ณต๊ตฌ ๋ถ๊ฐ๋ฅํ๋ฏ๋ก false
๋ฐํํ๋ค.
[์ฐ๊ธฐ ๊ถํ ๊ฒ์ฌ]
์ฐ๊ธฐ ์ ๊ทผ(write == true
)์ธ๋ฐ, ํด๋น ํ์ด์ง๊ฐ writable == false
๋ผ๋ฉด
์๋ชป๋ ์ ๊ทผ์ด๋ฏ๋ก ํ์ด์ง ํดํธ๋ฅผ ๋ณต๊ตฌํ ์ ์๋ค๊ณ ํ๋จํ์ฌ false
๋ฅผ ๋ฐํํ๋ค.
[ํ์ด์ง ๋ฉ๋ชจ๋ฆฌ ๋งคํ ์์ฒญ]
ํด๋น ํ์ด์ง๊ฐ ์์ง ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ์ค์ง ์์๊ธฐ ๋๋ฌธ์,
vm_do_claim_page()
๋ฅผ ํตํด (๋ฌผ๋ฆฌ) ๋ฉ๋ชจ๋ฆฌ์ ์ฐ๊ฒฐํ๋ค.
vm_do_claim_page()
๊ฐ ์ฑ๊ณตํ๋ฉด ํด๋น ํ์ด์ง๊ฐ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ๋งคํ๋์์์ ์๋ฏธํ๋ฉฐ,
์ด๋ฒ ํ์ด์ง ํดํธ๋ ์ฑ๊ณต์ ์ผ๋ก ๋ณต๊ตฌ๋ ๊ฒ์ด๋ค.
vm/vm.c
๊ตฌํํ ์ฝ๋ - bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED,
bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
{
struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
// ์๋ชป๋ ์ฃผ์ ์์ธ ์ฒ๋ฆฌ
if (addr == NULL || is_kernel_vaddr(addr))
return false;
// ์ ๊ทผํ ํ์ด์ง๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์์ ๊ฒฝ์ฐ
if (not_present)
{
struct page *page = spt_find_page(spt, addr);
if (page == NULL)
return false;
// ์ฐ๊ธฐ ๋ถ๊ฐ๋ฅํ ํ์ด์ง์ write ์๋ํ ๊ฒฝ์ฐ
if (write && !page->writable)
return false;
// ํ์ด์ง๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋งคํ
return vm_do_claim_page(page);
}
return false;
}
test
๋๋ ค๋ณธ ๊ฒฐ๊ณผ - 59 of 141 tests failed.
์ฌ๊ธฐ๊น์ง ๊ตฌํ ํ, pass tests/userprog/args-none
pass tests/userprog/args-single
pass tests/userprog/args-multiple
pass tests/userprog/args-many
pass tests/userprog/args-dbl-space
pass tests/userprog/halt
pass tests/userprog/exit
pass tests/userprog/create-normal
pass tests/userprog/create-empty
pass tests/userprog/create-null
pass tests/userprog/create-bad-ptr
pass tests/userprog/create-long
pass tests/userprog/create-exists
pass tests/userprog/create-bound
pass tests/userprog/open-normal
pass tests/userprog/open-missing
pass tests/userprog/open-boundary
pass tests/userprog/open-empty
pass tests/userprog/open-null
pass tests/userprog/open-bad-ptr
pass tests/userprog/open-twice
pass tests/userprog/close-normal
pass tests/userprog/close-twice
pass tests/userprog/close-bad-fd
pass tests/userprog/read-normal
pass tests/userprog/read-bad-ptr
pass tests/userprog/read-boundary
pass tests/userprog/read-zero
pass tests/userprog/read-stdout
pass tests/userprog/read-bad-fd
pass tests/userprog/write-normal
pass tests/userprog/write-bad-ptr
pass tests/userprog/write-boundary
pass tests/userprog/write-zero
pass tests/userprog/write-stdin
pass tests/userprog/write-bad-fd
FAIL tests/userprog/fork-once
FAIL tests/userprog/fork-multiple
FAIL tests/userprog/fork-recursive
FAIL tests/userprog/fork-read
FAIL tests/userprog/fork-close
FAIL tests/userprog/fork-boundary
FAIL tests/userprog/exec-once
FAIL tests/userprog/exec-arg
FAIL tests/userprog/exec-boundary
pass tests/userprog/exec-missing
pass tests/userprog/exec-bad-ptr
FAIL tests/userprog/exec-read
FAIL tests/userprog/wait-simple
FAIL tests/userprog/wait-twice
FAIL tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
FAIL tests/userprog/multi-recurse
FAIL tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
FAIL tests/userprog/rox-child
FAIL tests/userprog/rox-multichild
pass tests/userprog/bad-read
pass tests/userprog/bad-write
pass tests/userprog/bad-read2
pass tests/userprog/bad-write2
pass tests/userprog/bad-jump
pass tests/userprog/bad-jump2
FAIL tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
FAIL tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
pass tests/vm/pt-write-code
FAIL tests/vm/pt-write-code2
FAIL tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
FAIL tests/vm/page-parallel
FAIL tests/vm/page-merge-seq
FAIL tests/vm/page-merge-par
FAIL tests/vm/page-merge-stk
FAIL tests/vm/page-merge-mm
pass tests/vm/page-shuffle
FAIL tests/vm/mmap-read
FAIL tests/vm/mmap-close
FAIL tests/vm/mmap-unmap
FAIL tests/vm/mmap-overlap
FAIL tests/vm/mmap-twice
FAIL tests/vm/mmap-write
FAIL tests/vm/mmap-ro
FAIL tests/vm/mmap-exit
FAIL tests/vm/mmap-shuffle
FAIL tests/vm/mmap-bad-fd
FAIL tests/vm/mmap-clean
FAIL tests/vm/mmap-inherit
FAIL tests/vm/mmap-misalign
FAIL tests/vm/mmap-null
FAIL tests/vm/mmap-over-code
FAIL tests/vm/mmap-over-data
FAIL tests/vm/mmap-over-stk
FAIL tests/vm/mmap-remove
FAIL tests/vm/mmap-zero
FAIL tests/vm/mmap-bad-fd2
FAIL tests/vm/mmap-bad-fd3
FAIL tests/vm/mmap-zero-len
FAIL tests/vm/mmap-off
FAIL tests/vm/mmap-bad-off
FAIL tests/vm/mmap-kernel
FAIL tests/vm/lazy-file
pass tests/vm/lazy-anon
FAIL tests/vm/swap-file
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
FAIL tests/vm/swap-fork
pass tests/filesys/base/lg-create
pass tests/filesys/base/lg-full
pass tests/filesys/base/lg-random
pass tests/filesys/base/lg-seq-block
pass tests/filesys/base/lg-seq-random
pass tests/filesys/base/sm-create
pass tests/filesys/base/sm-full
pass tests/filesys/base/sm-random
pass tests/filesys/base/sm-seq-block
pass tests/filesys/base/sm-seq-random
FAIL tests/filesys/base/syn-read
pass tests/filesys/base/syn-remove
FAIL tests/filesys/base/syn-write
pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
pass tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
pass tests/threads/priority-change
pass tests/threads/priority-donate-one
pass tests/threads/priority-donate-multiple
pass tests/threads/priority-donate-multiple2
pass tests/threads/priority-donate-nest
pass tests/threads/priority-donate-sema
pass tests/threads/priority-donate-lower
pass tests/threads/priority-fifo
pass tests/threads/priority-preempt
pass tests/threads/priority-sema
pass tests/threads/priority-condvar
pass tests/threads/priority-donate-chain
FAIL tests/vm/cow/cow-simple
59 of 141 tests failed.
../../tests/Make.tests:28: recipe for target 'check' failed
make: *** [check] Error 1