Krafton Jungle/5. PintOS
[PintOS 5주차] Day 1
munsik22
2025. 6. 5. 16:09
이번 5주차에서는 (지난 3주차와 마찬가지로) 4주차의 팀원들과 프로젝트가 그대로 진행된다.

Stack growth 구현
static bool
vm_stack_growth (void *addr UNUSED) {
/* Increases the stack size by allocating one or more anonymous pages
* so that addr is no longer a faulted address. Make sure you round down
* the addr to PGSIZE when handling the allocation. */
void *upage = pg_round_down(addr);
if (vm_alloc_page_with_initializer(VM_ANON, upage, true, NULL, NULL))
return vm_claim_page(upage);
}
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) || !not_present)
return false;
struct page *page = spt_find_page(spt, addr);
if (page == NULL) {
/* If you have confirmed that the fault can be handled with a stack growth,
* call vm_stack_growth with the faulted address. */
if (f->rsp - PGSIZE < addr) {
if (!vm_stack_growth(addr))
return false;
page = spt_find_page(spt, addr);
} else
return false;
}
if (write && !page->writable)
return false;
return vm_do_claim_page(page);
}
pt-write-code2 해결
$ make tests/vm/pt-write-code2.result
pintos -v -k -T 60 -m 20 --fs-disk=10 -p tests/vm/pt-write-code2:pt-write-code2 -p ../../tests/vm/sample.txt:sample.txt --swap-disk=4 -- -q -f run pt-write-code2 < /dev/null 2> tests/vm/pt-write-code2.errors > tests/vm/pt-write-code2.output
perl -I../.. ../../tests/vm/pt-write-code2.ck tests/vm/pt-write-code2 tests/vm/pt-write-code2.result
FAIL tests/vm/pt-write-code2
run: survived reading data into code segment: FAILED
"Try to write to the code segment using a system call. The process must be terminated with -1 exit code."
해당 함수는 시스템 콜 내부에서 코드 세그먼트에 write를 시도하면 exit(-1)을 하는지 확인한다.
void
test_main (void)
{
int handle;
CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
read (handle, (void *) test_main, 1);
fail ("survived reading data into code segment");
}
해당 테스트 코드는 실행 중인 test_main의 주소 ((void *) test_main)에 handle의 1바이트를 읽어들이려고 한다. 즉, read-only인 코드 세그먼트 (void *) test_main 입장에서는 write하려고 하는 것이기 때문에, read 시스템 콜에서 writable이 false인 경우에 exit(-1)을 하는 코드를 추가해야 한다.
int read (int fd, void *buffer, unsigned size) {
if (size == 0) return 0;
if (!check_address(buffer)) exit(-1);
#ifdef VM
struct page *page = spt_find_page(&thread_current()->spt, buffer);
if (page != NULL && !page->writable)
exit(-1);
#endif
…
}
pt-stack-stk-sc 해결
$ make tests/vm/pt-grow-stk-sc.result
pintos -v -k -T 60 -m 20 --fs-disk=10 -p tests/vm/pt-grow-stk-sc:pt-grow-stk-sc --swap-disk=4 -- -q -f run pt-grow-stk-sc < /dev/null 2> tests/vm/pt-grow-stk-sc.errors > tests/vm/pt-grow-stk-sc.output
perl -I../.. ../../tests/vm/pt-grow-stk-sc.ck tests/vm/pt-grow-stk-sc tests/vm/pt-grow-stk-sc.result
FAIL tests/vm/pt-grow-stk-sc
Test output failed to match any acceptable form.
Acceptable output:
(pt-grow-stk-sc) begin
(pt-grow-stk-sc) create "sample.txt"
(pt-grow-stk-sc) open "sample.txt"
(pt-grow-stk-sc) write "sample.txt"
(pt-grow-stk-sc) 2nd open "sample.txt"
(pt-grow-stk-sc) read "sample.txt"
(pt-grow-stk-sc) compare written data against read data
(pt-grow-stk-sc) end
Differences in 'diff -u' format:
(pt-grow-stk-sc) begin
(pt-grow-stk-sc) create "sample.txt"
(pt-grow-stk-sc) open "sample.txt"
(pt-grow-stk-sc) write "sample.txt"
(pt-grow-stk-sc) 2nd open "sample.txt"
(pt-grow-stk-sc) read "sample.txt"
- (pt-grow-stk-sc) compare written data against read data
- (pt-grow-stk-sc) end
+ pt-grow-stk-sc: exit(-1) # make check에서는 생략됨
"This test checks that the stack is properly extended even if the first access to a stack location occurs inside a system call."
해당 테스트는 시스템 콜에서 처음으로 스택 주소에 접근하더라도 스택이 적절히 확장되는지 확인한다. 테스트 중 프로그램이 read까지는 정상적으로 동작했지만, 그 이후 비교(compare) 및 정상 종료(end) 단계에 도달하지 못했다.
int read (int fd, void *buffer, unsigned size) {
if (size == 0) return 0;
struct thread *curr = thread_current();
#ifndef VM
if (!check_address(buffer)) exit(-1);
#else
if (buffer == NULL || !is_user_vaddr(buffer))
exit(-1);
struct page *page = spt_find_page(&curr->spt, buffer);
if (page == NULL) {
if (buffer < USER_STACK) {
int cnt = 0;
while (curr->stack_pointer - cnt * PGSIZE >= buffer)
cnt++;
if (curr->stack_pointer - cnt * PGSIZE < STACK_LIMIT) exit(-1);
for (int i = 0; i < cnt; i++) {
if (!vm_stack_growth(buffer + i * PGSIZE))
exit(-1);
}
page = spt_find_page(&curr->spt, buffer);
} else
exit(-1);
}
if (!page->writable)
exit(-1);
#endif
…
}
pt-stack-stk-sc는 pass되었지만, 기존에 통과했던 pt-bad-read가 fail되었다.
