PINTOS - Virtual Memory

JinJinJara·2023년 10월 3일
0

PINTOS

목록 보기
6/10

Virtual Memory

구조

/* 64-bit 가상 주소의 구조 */

63     48 47            39 38            30 29            21 20         12 11       0
+--------+----------------+----------------+----------------+-------------+----------+
|  Sign  |    Page-Map    | Page-Directory | Page-directory |  Page-Table | Physical |
| Extend | Level-4 Offset |    Pointer     |     Offset     |   Offset    |  Offset  |
+--------+----------------+----------------+----------------+-------------+----------+
         |                |                |                |             |          |
         +------- 9 ------+------- 9 ------+------- 9 ------+----- 9 -----+--- 12 ---+
                                     Virtual Address

헤더파일 include/threads/vaddr.hinclude/threads/mmu.h 는 가상 주소들을 다루기위한 이런 함수들과 매크로들을 정의


1. PGSHIFT / PGBITS

각각 가상 주소 오프셋 부분의 인덱스 (0) bit 와 bit의 수 (12)

#define PGSHIFT { /* Omit details */ }
#define PGBITS { /* Omit details */ }

2. PGMASK

“페이지 오프셋” 부분의 비트들에 1, 나머지는 0으로 설정되어 있는 비트마스킹 매크로

#define PGMASK { /* Omit details */ }

3. PGSIZE

바이트 단위에서 페이지 크기 (4,096)

#define PGSIZE { /* Omit details */ }

4. pg_ofs

가상 주소 va 의 페이지 오프셋을 뽑아내 반환

#define pg_ofs(va) { /* Omit details */ }

5. pg_no

가상 주소 va 의 페이지 번호를 뽑아내 반환

#define pg_no(va) { /* Omit details */ }

6. pg_round_down

내부에서 va가 가리키는 가상 페이지의 시작 (페이지 오프셋이 0으로 설정된 va)을 반환

#define pg_round_down(va) { /* Omit details */ }

7. pg_round_up

가장 근접한 페이지 경계 값으로 올림된 va를 반환

#define pg_round_up(va) { /* Omit details */ }

8. KERN_BASE

커널 가상 메모리의 기본 주소. 기본값은 0x8004000000.

#define KERN_BASE { /* Omit details */ }
  • 유저 가상 메모리 : 가상 주소 0부터 KERN_BASE까지

  • 커널 가상 메모리 : 가상 주소 공간의 나머지 부분을 차지

    • 핀토스에서 가상 메모리는 두 영역(유저/커널)으로 나뉨 ( 참고 Virtual Memory Layout )

    • 둘 사이의 경계 = KERN_BASE


9. is_user_vaddr / is_kernel_vaddr

va(가상주소)가 각각 유저 가상 주소 또는 커널 가상 주소 라면 True, 아니면 False 반환

#define is_user_vaddr(vaddr) { /* Omit details */ }
#define is_kernel_vaddr(vaddr) { /* Omit details */ }
x86-64에서는 주어진 물리 주소 메모리에 직접적으로 접근할 수 있는 방법을 제공하지 않는다.

이 기능은 os 커널에서 필요하며,
이를 위해 핀토스는 커널 가상 메모리를 물리 메모리와 11로 매핑(mapping)한다., 가상 주소가 KERN_BASE라면 물리 주소 0에 매핑되며,
가상 주소가  `KERN_BASE + 0x1234` 라면, 물리 주소 0x1234에 매핑된다.

따라서, 물리 주소에 `KERN_BASE` 를 더하면 커널 가상 주소를 얻을 수 있고,
커널 가상 주소에서 `KERN_BASE` 를 빼주면 물리 주소를 얻을 수 있다.

10. ptov

0 ~ (물리 주소의 크기) 내에 존재하는 물리 주소(pa)와 대응되는 커널 가상 주소를 반환

#define ptov(paddr) { /* Omit details */ }

11. vtop

커널 가상 주소(va)와 대응되는 물리 주소를 반환

#define vtop(vaddr) { /* Omit details */ }

헤더파일 include/threads/mmu.h 은 페이지 테이블 상에서의 활동을 제공

12. is_user_pte / is_kern_pte

페이지 테이블 엔트리(PTE)의 주인이 유저인지 커널인지 확인

#define is_user_pte(pte) { /* Omit details */ }
#define is_kern_pte(pte) { /* Omit details */ }
  • user pte 라면 유저/커널, kernel pte 라면 커널 only.

13. is_writable

PTE가 가리키는 가상주소가 작성 가능한 지(wriatable) 아닌 지 확인

#define is_writable(pte) { /* Omit details */ }

14. pte_for_each_func

각 PML4 아래에 있는 valid entry마다, 함수 FUNC에 보조값 AUX를 계산
= 각 pml4가 유효한 entry를 가지고 있는지 검사

typedef bool pte_for_each_func (uint64_t *pte, void *va, void *aux);
bool pml4_for_each (uint64_t *pml4, pte_for_each_func *func, void *aux);
  • 가상주소(VA)는 엔트리 가상주소에 해당함
  • pte_for_each_func 결과가 false라면, 반복을 멈추고 false를 반환
  • func 함수가  pml4_for_each 에서 구현되는 과정
static bool
stat_page (uint64_t *pte, void *va,  void *aux) {
        if (is_user_vaddr (va))
                printf ("user page: %llx\n", va);
        if (is_writable (va))
                printf ("writable page: %llx\n", va);
        return true;
}
  • pml4_for_each의 인자로 전달될 수 있는 func의 예시이다.

0개의 댓글