[SW_Jungle] PintOS project 3 - Stack Growth

Jin Lee·2022년 1월 24일
0

PintOS

목록 보기
15/16
post-thumbnail

프로젝트 2까지는 스택이 USER_STACK위치를 시작 주소로 하는 고정된 단일 페이지였고 프로그램의 실행인 이 안에서 해결 가능한 사이즈로 한정 지어졌다. 본 프로젝트에서는 지금의 스택 사이즈를 넘어가면 필요한 만큼 추가 페이지를 할당해준다.

스택 접근으로 나타내는 경우에만 추가 페이지를 할당하고 스택 접근과 다른 access를 구분하기 위한 시도를 하는 휴리스틱한 방법을 고안할 것

유저 프로그램은 이 프로그램이 스택 포인터 밑으로 스택에 write 할 때 버그가 생긴다. 왜냐하면 전형적인 real OS는 시그널을 보내는 순간에 프로세스에 인터럽트를 거는데, 이는 스택에 데이터를 수정하는 시그널이다. 하지만, x86-64에서 PUSH 인스트럭션은 access permission을 체크한다. 그러고 나면 스택 포인터를 조정하는데, 이는 스택 포인터 아래 8바이트 위치에서 page fault를 일으킨다.

우리는 유저 프로그램의 스택 포인터의 현재 값을 확보할 필요가 있다. 시스템 콜 혹은 유저 프로그램에 의해 발생한 page fault 안에서, 우리는 스택 포인터를 syscall_handler()나 page_fault()를 통해 넘겨받은 struct intr_frame 의 rsp 멤버로부터 다시 회수할 수 있다.만약 우리가 유효하지 않은 메모리 접근을 탐지하기 위해 page fault에 의존한다면, 우리는 또다른 케이스를 다룰 필요가 있는데, page fault가 커널에서 일어났을 때이다.(초기) 프로세서는 exception이 발생해 유저 모드에서 커널 모드로 스위치를 일으켰을 때만 스택 포인터를 저장하기 때문에, page_fault()로 전달받은 struct intr_frame 에서 rsp를 읽으면 유저 스택 포인터가 아니라 정의되지 않은 값이 생성될 것이다. 우리는 다른 방식으로 접근할 필요가 있는데, 예를 들어 유저 모드에서 커널 모드로 최초의 transition이 일어났을 때 rsp를 struct thread 구조체에 저장한다던지 등.

stack growth functionalities를 구현해라. 이를 구현하기 위해, 우리는 첫번째로 stack growth를 구분하기 위해 vm_try_handle_fault를 수정해야 한다. stack growth를 구분한 뒤, 우리는 vm/vm.c에 있는 vm_stack_growth를 호출해서 stack을 키운다. vm_stack_growth를 구현해라.

profile
깃허브 : https://github.com/jinlee9270

0개의 댓글