ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Pintos project3_Stack Growth
    OS/Pintos P.J_3 2022. 1. 21. 21:16

    project2까지 스택은 user_stack에서 시작하는 단일 페이지 였으며 프로그램의 실행은 이 크기로 제한되었다. 이제 스택공간이 증가함에 따라 필요한 페이지를 추가해 주도록 하자 

     

    추가 페이지의 할당은 오직 스택에 접근하려고 할때 할당한다.

     

    사용자 프로그램은 만약 스택 포인터 아래에 write를 하면 버그가 난다.

    이유는 실제  OS는 스택에 있는 데이터를 수정하기 위한 signal 을보내기위해 언제든 process를 interrupt한다 하지만 x86-64 PUSH 명령어는 학하기전 접근이 가능한 stack pointer인지 체크 한다 .

    따라서 스택 포인터 아래 8bytes에서 페이지 fault가 발생할 수 있다.

     

    먼저 현재 유저 프로그램의 스택포인터에서 현재 값을 획득해야 한다.

    시스템콜 혹은 사용자 프로그램에 의해 생성된 페이지 폴트 내에서 syscall_handler() 또는 page_fault()에 각각 전달된 intr_frame의 rsp 멤버에서 검색할 수 있다.

     

    만약

    페이지 폴트로

    잘못된 메모리 접근을 감지하려 한다면 page fault가 kernel에서 일어나고 있는지도 체크해야한다

    processor는 user 모드에서 kernel 모드로 바뀔때의 예외상황에서만 스택포인터를 저장하기 때문에 만약 inter_frame 밖에서 rsp를 읽어 page_fault()로 전달하면 user stack pointer가 아닌 비정상적인 값을 넘길 것이다. 

     

    이를 방지하려면 모드 변경시 rsp를 struct thread에 저장하는 것과 같은 방법이 필요하다. 

    Implement stack growth functionalities

    /*vm/vm.c -> vm_try_handle_fault*/

    vm_try_handle_fault 를 수정해 stack growth를 해야하는지 식별한다. stack growth가 필요함을 확인하면 vm_stack_growth를 호출해서 stack을 증가 시킨다. 

    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 */
    	if (is_kernel_vaddr(addr)) {
            return false;
    	}
    
        void *rsp_stack = is_kernel_vaddr(f->rsp) ? thread_current()->rsp_stack : f->rsp;
        if (not_present){
            if (!vm_claim_page(addr)) {
                if (rsp_stack - 8 <= addr && USER_STACK - 0x100000 <= addr && addr <= USER_STACK) {
                    vm_stack_growth(thread_current()->stack_bottom - PGSIZE);
                    return true;
                }
                return false;
            }
            else
                return true;
        }
        return false;
    }

    page fault가 stack gorwth로 해결가능하다면? vm_stack_growth를 호출한다.

    vm_stack_growth

     page fault가 발생하지 않도록 스택의 사이즈를 어나니머스 페이지를 할당해 증가시킨다. 최대 증가 가능한 스택 사이즈는 1MB이다. 

    /* Growing the stack. */
    static void
    vm_stack_growth (void *addr UNUSED) {
    	if (vm_alloc_page(VM_ANON | VM_MARKER_0, addr, 1)) //type:vm_anon, upage addr, writable True
    	{
    		vm_claim_page(addr);
    		thread_current()->stack_bottom -= PGSIZE; // 스택은 위에서부터 쌓기 때문에 주소값 위치를 페이지 사이즈씩 마이너스함
    	}
    }

    'OS > Pintos P.J_3' 카테고리의 다른 글

    Pintos project3_Swap In/Out  (0) 2022.01.25
    Pintos project3_Memory Mapped Files  (0) 2022.01.22
    Pintos project3_Anonymous Page  (0) 2022.01.21
    Pintos project3_Memory management  (0) 2022.01.19
    [Project 3_Virtual Memory]_Intro  (0) 2022.01.11

    댓글

Designed by Tistory.