
해당 페이지 폴트는 Pintos x86_64 기준으로 설명합니다.
Page fault는 프로세스가 참조하려는 가상 메모리 페이지가 현재 물리적 메모리에 로드되어 있지 않을때 발생합니다. 이것은 메모리 접근 시도 중에 발생하는 인터럽트나 예외 상황입니다.
즉, CPU가 아직 메모리에 존재하지 않는 가상 주소를 접근하려고 할 때 발생하는 예외(Exception)입니다.

VM 구현 전에는 즉시 프로세스를 종료했으나 VM 구현한 후에는 vm_try_handle_fault() 을 호출합니다.
→ 접근 주소가 user, kernel, write 중 어떤 상황인지 판단하여 넘깁니다.

spt_find_page 를 통해 유효한 사용자 주소인지 확인하고, spt에서 faulting address에 대한 struct page 를 찾습니다.
찾았으면, lazy load 또는 swap-in 을 하고,
없으면, 프로그램의 인자나 주소등을 저장하기 위한 스택 증가를 위해 vm_stack_growth 를 실행합니다.
커널 영역 접근, 읽기 전용 페이지 쓰기, 할당되지 않은 주소 등 유효하지 않으면 프로세스를 kill 종료

palloc을 통해 페이지 프레임을 할당하고 mmu를 설정합니다.
만약, 백업 데이터가 있으면 swap_in 을 통해 load를 호출합니다.
pml4_set_page를 통해 물리 프레임과 가상 주소를 매핑해줍니다.

마지막 코드인 return swap_in 을 통해 uninit_initialize 함수 실행을 합니다. 해당 함수는 lazy loading 방식으로 초기화된 uninitialized page를 실제 anon, file, cache 등의 구체적인 페이지로 전환(변환) 하는 함수입니다.
이후에는 lazy_load_segment를 진행하게 됩니다.

lazy_load_segment 함수를 통해 프로세스가 실제로 페이지에 접근할 때까지 해당 페이지의 데이터를 로딩하지 않고 기다리는 방식 (lazy loading)을 구현합니다. 내부에 있는 load_segment 함수에서 vm_alloc_page_with_initializer 함수를 통해 프레임에 데이터를 채우기도 합니다.

피그마를 통해 그려본 Pintos의 Page Fault 흐름도 입니다. 대략적인 흐름 파악을 해보시면 좋을 것 같습니다.

그러면, 프레임에는 어떻게 데이터를 채울까?
vm_alloc_page_with_initializer 라는 함수를 통해 채웁니다.
데이터를 채우는 방식에는 4가지 방식이 있습니다.
→ 위의 적절한 방식에따라 프레임에 데이터를 처리하게 됩니다.

pml4_set_page() 함수를 사용해 가상주소를 물리 주소로 매핑
