jun-wiki

View My GitHub Profile

Posts (Latest 10 updated) :
Read all
Contents:
  1. 스택 성장 (Stack Growth)
    1. 휴리스틱 힌트?
      1. Pintos에서 원하는 바
    2. 스택 포인터 얻기 (RSP)
    3. 스택 성장 구현

GitBOOK 정리다

스택 성장 (Stack Growth)

프로젝트 2까지는 스택이 USER_STACK 단일 페이지 였으니

이제 이를 추가 할당해줘야 한다는 내용이다

유의점은 추가 페이지 할당은 스택 접근일때에만 유효하다는 거다

즉, 이걸 구분할 휴리스틱(대강 구분법)을 고안하란다

휴리스틱 힌트?

기본적으로 스택 포인터 아래 쓰기는 버그다
그치만, PUSH 명령은 스택 포인터 아래 8바이트에서 페이지 폴트를 일으킬 수 있고 이게 정상동작이라고 한다

이게 무슨 말이냐?

기본적으로 스택은 아래로 성장하며 현재 스택 포인터 RSP는 스택 꼭대기를 가리킨다

프로그램은 스택을 쓸때 RSP를 줄여 공간을 만들고 그 영역에 값을 저장하기에
그 아래에 쓰면 OS가 언제든 인터럽트/시그널을 통해 그 자리(스택)에 커널/시그널 프레임을 써넣어 충돌 날 수 있기에 버그라고 본다

단, PUSH는 예외다

x86-64에서 push rax 같은 명령은

  • RSP-8로 접근 권한 체크

  • 접근 가능시 RSP := RSP - 8하고 값을 저장

이런식으로 진행되기에 메모리 접근 확인이 RSP를 줄이기 전에 RSP-8로 수행된다

그렇기에 RPS로부터 8바이트 아래의 페이지 폴트는 정상 동작으로 봐야 한다는 거다


Pintos에서 원하는 바

즉, 스택 성장 휴리스틱은 RSP 바로 아래 범위의 폴트를 정상적인 스택 접근으로 인정하기를 원한다는 것이다


스택 포인터 얻기 (RSP)

syscall_handler()page_fault()시 전달되는 struct intr_framersp 멤버에서 이를 가져올 수 있다

스택 성장을 위해 RSP와 폴트 난 주소 위치 관계를 파악해야 하는데 페이지 폴트가 커널모드에서 나버리면

RSP가 커널 스택 포인터가되는 불상사가 발생하기에 이를 관리하는 방법을 모색하라고한다

RSP를 struct thread에 저장하는 등 말이다

스택 성장 구현

먼저 vm/vm.cvm_try_handle_fault를 수정해 스택 성장을 식별해야 한다

스택 성장 식별 후 vm/vm.cvm_stack_growth를 호출해 스택 성장시켜야 한다

vm_stack_growth는 구현해야 한다


bool vm_try_handle_fault (struct intr_frame *f, void *addr,
    bool user, bool write, bool not_present);

페이지 폴트 예외 처리할 때 호출된다
함수에서 페이지 폴트가 스택 성장의 유효한 경우인지 확인한다
스택성장으로 처리가능할 경우 vm_stack_growth호출


void vm_stack_growth (void *addr);

addr이 더 이상 폴트 주소가 되지 않도록 익명 페이지 할당해 스택 크기 늘린다
할당 처리할 떄 addrPGSIZE로 내려야 한다(round down)


이거 다 하면 스택 성장 테스트 케이스 통과다