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