
Stack Growth
- 기존 Project 2의 스택 영역은 딱 한 페이지 (4KB)
- 이제 스택 영역이 꽉 차면, 추가로 페이지를 할당
- 스택 포인터의 값 확인하기
- 시스템 콜:
syscall_handler()로 전달된 struct intr_frame의 필드 rsp
- 페이지 폴트:
page_fault()로 전달된 struct intr_frame의 피드 rsp
- 커널 내에서 페이지 폴트가 발생할 시: 기본적으로
undefined. 사용자 -> 커널 전환 시 struct thread에 rsp를 저장한다거나 해야 함.
struct thread에 uintptr_t형 필드 하나 추가 후, 시스템 콜 발생시 호출되는 syscall_handler에서 저장하는 식으로 구현할 수 있을 듯
- 일단 테스트 케이스에선 system call 내부에서 stack growth가 잘 처리되는지만 확인하므로, 다른 경우는 일단 수정하지 않아도 될듯. 어셈블리어를 고치는 건 너무 빡세기도 하고.
vm_try_handle_fault
spt_find_page == NULL일 때, stack growth를 시도할 수 있는지 여부 확인
- 조건 1
스택 포인터 > page fault 발생 주소 >= 스택 포인터 - 8)인 경우
- 즉, 스택 포인터에서 8바이트 이내에 접근하는 경우.
- x86 PUSH 명령은, 스택 포인터(
rsp) 조정 전 접근 권한을 먼저 확인
rsp-8에 접근할 때, 아직 메모리가 존재하지 않으면 page fault
rsp: user mode인 경우 f -> rsp에서, kernel mode인 경우 앞서 struct thread에 저장한 필드에서 확인. user 변수가 1인지 0인지로 확인할 것.
- 조건 2
page fault 발생 주소 >= USER_STACK - 1 << 20
- 즉, 스택 최대크기를 초과하지 않는 경우.
- 스택의 최대크기는 1메가바이트, 이를 넘는 범위에서 페이지 폴트 발생 시 실패 처리
- 조건 1, 2 모두 만족하는 경우,
vm_stack_growth 호출
- 성공 시,
spt_find_page로 돌아가 재시도
vm_stack_growth
- 스택에 새로운 anonymous page를 할당해 크기 확장
static void vm_stack_growth(void *addr UNUSED)
vm_alloc_page_with_initializer
- 단, fault 발생한 주소를 페이지 정렬 맞게 내림한 뒤, 필요한 만큼 반복문으로 할당
rsp를 수동으로 낮춘 경우 1페이지 이상을 할당해야 할 수도 있음
- 초기값을
pg_round_down(addr)로 하고, 주소를 PGSIZE값만큼 증가
vm_alloc_page_with_initializer가 실패할 때까지 반복문 돌리기