본문 바로가기

PINTOS 4주차 Stack Growth

Pintos 마지막 주차에서는 저번 주차에 이어서 VM을 구현하는 과제들이 있었다.
이 중에서 첫 번째 topic이었던 stack growth에 대해서 정리하려고 한다.
 
현재 핀토스의 사용자 스택 크기는 페이지 1개 크기, 즉 4KB이다.
이렇게 고정된 스택 크기를, 이제는 페이지 폴트 핸들링을 통해 필요한 만큼 증가시킬 것이다. 단, 최대 스택 크기는 1M까지만 가능하다는 조건이 있었다.
 
페이지 폴트 핸들링을 할 때 stack growth를 처리하기 위해서는 두 가지가 중요했다.
 
첫째, 페이지 폴트 함수에서 해당 fault가 stack growth로 해결될 수 있는 것인지를 확인하는 것이다.
 
이를 위해 다음 두 가지를 확인해야 한다.
(1) 현재 페이지가 물리 메모리에 없는지 확인
(2) faulted address가 사용자 스택 영역 주소 주변인지 확인
 

 
코드로 살펴보면 다음과 같다.
(1) intr_frame의 error code를 파싱하면 해당 페이지가 물리 메모리에 로드되었는지 여부를 확인할 수 있다. 0번째 비트가 0인지 확인하면 된다.
(2) faulted address는 cr2 레지스터에 있어서 rcr2()라는 함수를 통해 그 값을 가져오면 된다. 이 값, 즉 faulted address가 스택의 상단인 USER_STACK과 스택 최대 크기일 때의 스택 하단인 USER_STACK - 1M 사이에 있다면 해당 폴트가 스택 확장을 통해 해결될 수 있는 폴트임을 확인할 수 있다.
 

 
둘째, 페이지 폴트가 발생한 주소인 faulted address가 rsp-8인지 확인한다.
이때 중요한 것은 사용자 프로세스에서 폴트가 발생한 경우에는 page fault에서 바로 t->rsp를 구해도 되지만, 커널 프로세스에서 폴트가 발생한 경우에는 그렇게 하면 커널 스택의 포인터를 구하게 되기 때문에 사용자 모드에서 커널 모드로 context switching이 되는 순간, 즉 syscall_handler에서 t->rsp를 구한 뒤에 이를 스레드 구조체에 별도로 추가한 멤버 변수인 rsp에 백업해두어서 이것을 사용해야 한다는 점이다.

 
코드로 살펴보면 다음과 같다.

'정글' 카테고리의 다른 글

OpenSSL와 자체 서명 인증서  (0) 2024.12.18
Nginx  (1) 2024.12.18
PINTOS 3주차 가상 메모리 관리 시스템  (0) 2024.10.15
PINTOS 2주차 Argument Parsing  (0) 2024.10.08
PINTOS 1주차 Blocked List, Scheduling  (0) 2024.10.01