
PTE는 위의 사진과 같은 구조를 가지고 있다.
하위 12bit 에는 가리키고 있는 프레임의 정보를 나타내는 다양한 종류의 flag 들이 기록되며
가상 주소 공간을 관리하는데 중요한 역할을 하고 있다.
그중 이번에 공부한 flag는 바로 write flag이다.


write flag는 운영체제의 virtual address 변환을 도와주는 하드웨어인 MMU에서 체크된다.
MMU는 유저 프로세스가 가상 주소를 이용하여 메모리에 접근을 요청하면 페이지 테이블을 읽어
물리주소로 변환하는 작업을 수행하며 동시에 PTE의 write bit를 확인하여 만약 write bit가 0인 공간
에 쓰기 목적으로 접근하면 page fault를 발생시키며 이에 대한 결과를 위의 두 사진에서 확인할 수 있다.
첫번째 사진은 write 권한이 true 로 세팅되어 있어 정상적으로 메모리에 100을 쓰고 읽어 출력
에 성공하지면 두번째 사진을 보면 false 세팅되어 있고 의도치 않는 page fault가 발생하는것을
볼 수 있다.


다음은 커널 모드에서의 write 비트에 의한 MMU의 동작을 검증해 보고자 read를
활용하여 특정 버퍼 공간의 write bit를 바꾸어 가며 테스트해 보았다. read는 시스템 콜중
하나로 유저가 커널에게 특정 작업을 요청하는 함수로 시스템 콜에 대한 핸들링을 수행하는
동안은 유저모드가 아닌 커널모드에 일련의 작업이 처리되고 다시 유저모드로 돌아온다.
따라서 read가 호출되어 버퍼에 값을 읽고 저장하는 동안은 커널모드라 가정할 수 있다.
결과적으로 보면 커널 모드에서는 write bit의 상태와 상관없이 쓰기 접근에 대해 page fault가
발생하지 않았다. 이는 MMU가 유저모드와 같이 write 권한 체크를 해줄 것이란 예상과 벗어나
당황했었지만 이에 대한 이유를 pintos의 소스코드를 좀 더 상세히 분석하다 찾을 수 있었다.
/* Flags in control register 0. */
#define CR0_PE 0x00000001 /* Protection Enable. */
#define CR0_EM 0x00000004 /* (Floating-point) Emulation. */
#define CR0_PG 0x80000000 /* Paging. */
#define CR0_WP 0x00010000 /* Write-Protect enable in kernel mode. */
#### Enable paging
mov %cr0, %eax
or $(CR0_PE|CR0_PG), %eax
mov %eax, %cr0
위의 코드는 pintos가 부팅될때 수행하는 코드를 일부 가져온 것이다.
위의 매크로를 보면 #define CR0_WP 0x00010000 커널 모드에서의 write-protect
를 수행할지 말지 설정하는 플레그가 있음을 알 수 있다.
그리고 kernel write 관련 플레그는 CR0(0번 컨트롤 레지스터)에 세팅된다는 것을
조사를 통해 알 수 있었고 좀더 코드를 분석해본 결과 os 부팅시 CR0 레지스터를
세팅하는 부분을 찾을 수 있었고 CR0_WP 플레그를 활성화 하지 않고 있는것을 확인할
수 있었고 추가로 테스트 진행하여 공부한것을 직접 실행시켜 보았다.


위의 테스트를 통해서 CR0_WP 플레그의 설정에 따라 MMU가 커널 모드에서 write bit를
검사할지 안할지 결정된다는 것을 확인할 수 있었다.