Stack Growth {pintos} {gitbook}

- week09 - Virtual Memory {pintos} {swjungle}

Stack Growth

Allocate additional pages only if they "appear" to be stack accesses. Devise a heuristic that attempts to distinguish stack accesses from other accesses.

x86-64 아키텍처는 PUSH 명령으로 함수호출시 항상 스택 포인터 아래 8바이트의 공간을 먼저 참조를 시도하여 해당 주소가 접근 가능한지 여부를 검사한다고. 

다음 문단이 엄청 중요한 것 같은데 이해가 잘 되지 않는다.

You will need to be able to obtain the current value of the user program's stack pointer. Within a system call or a page fault generated by a user program, you can retrieve it from the rsp member of the struct intr_frame passed to syscall_handler() or page_fault(), respectively. If you depend on page faults to detect invalid memory access, you will need to handle another case, where a page fault occurs in the kernel. Since the processor only saves the stack pointer when an exception causes a switch from user to kernel mode, reading rsp out of the struct intr_frame passed to page_fault() would yield an undefined value, not the user stack pointer. You will need to arrange another way, such as saving rsp into struct thread on the initial transition from user to kernel mode.

시스템 콜, 유저 프로그램에서 발생한 page fault에서 intr_frame::rsp에서 스택 포인터를 가져올 수 있다는 점을 설명하고 있다. 그런데 유효하지 않은 메모리 접근을 감지하기 위해 page fault에만 의존하게 된다면 커널 안에서 발생하는 page fault를 처리해야 한다고 한다. 프로세서는 rsp를 유저모드에서 커널모드로 넘어갈 때에만 저장하기 때문에 page_fault 인자 f를 통해 rsp를 읽는다면 정의되지 않은 값을 읽을 수도 있게된다.

아, 이런 케이스가 있을 수도 있겠구나, 유저가 시스템 콜 함수의 인자로 유효하지 않은 주소를 전달한다. ⟶ 커널모드로 전환이 된 후에 주소값을 참조하려다 page fault가 발생한다. ⟶ 당연하겠지만 rsp는 커널 스레드의 스택일 것이다.

Implement stack growth functionalities.

vm_try_handle_fault 안에서 stack growth 상황을 식별한 뒤 vm_stack_growth 함수를 호출하라.

For this project, you should limit the stack size to be 1MB at maximum.
PintOS는 스택 최대크기를 1MB로 만들어야 한다.