6.828: Operating System Engineering (29)
今日は休日 mtg の日なのですが、現実トウヒ。check_boot_pgdir 手続きの確認。
とりあえず以下から確認。
// check pages array n = ROUNDUP(npage*sizeof(struct Page), PGSIZE); for (i = 0; i < n; i += PGSIZE) assert(check_va2pa(pgdir, UPAGES + i) == PADDR(pages) + i);
UPAGES は inc/memlayout.h で定義されてる模様。コメントによれば以下。
* | RO PAGES | R-/R- PTSIZE * UPAGES ----> +------------------------------+ 0xef000000
む、pages って何だろ。定義はされてます。
struct Page* pages; // Virtual address of physical page array
これ、初期設定されてないな。でも pages って extern 宣言されてるな。ちなみに struct Page 型は inc/memlayout.h で定義されている模様。
/* * Page descriptor structures, mapped at UPAGES. * Read/write to the kernel, read-only to user programs. * * Each Page describes one physical page. * You can map a Page * to the corresponding physical address * with page2pa() in kern/pmap.h. */ LIST_HEAD(Page_list, Page); typedef LIST_ENTRY(Page) Page_LIST_entry_t; struct Page { Page_LIST_entry_t pp_link; /* free list link */ // pp_ref is the count of pointers (usually in page table entries) // to this page, for pages allocated using page_alloc. // Pages allocated at boot time using pmap.c's // boot_alloc do not have valid reference count fields. uint16_t pp_ref; };
ええと LIST_HEAD マクロを展開されたら
struct Page_list { struct Page *lh_first; /* first element */ };
になるのかな。あるいは LIST_ENTRY もマクロな模様。以下?
typedef struct { struct Page *le_next; /* next element */ struct Page **le_prev; /* ptr to ptr to this element */ } Page_LIST_entry_t;
双方向リンクになってるのか。pages はやはり i386_vm_init 手続きで初期設定する模様。
////////////////////////////////////////////////////////////////////// // Allocate an array of npage 'struct Page's and store it in 'pages'. // The kernel uses this array to keep track of physical pages: for // each physical page, there is a corresponding struct Page in this // array. 'npage' is the number of physical pages in memory. // User-level programs will get read-only access to the array as well.
ええと、UPAGES な領域ですが 0x400000 って 4096*1024 になるのか。PTSIZE は mmu.h にて以下な定義か。
// Page directory and page table constants. #define NPDENTRIES 1024 // page directory entries per page directory #define NPTENTRIES 1024 // page table entries per page table #define PGSIZE 4096 // bytes mapped by a page #define PGSHIFT 12 // log2(PGSIZE) #define PTSIZE (PGSIZE*NPTENTRIES) // bytes mapped by a page directory entry
ちょっとまだイメージが微妙です。もう少し周辺の確認を。
ええと、check_va2pa という手続きが多用されてるので見てみます。コメントのあたりが以下。
// This function returns the physical address of the page containing 'va', // defined by the page directory 'pgdir'. The hardware normally performs // this functionality for us! We define our own version to help check // the check_boot_pgdir() function; it shouldn't be used elsewhere. static physaddr_t check_va2pa(pde_t *pgdir, uintptr_t va) {
pde_t は unsigned int なのか。てゆーか、ページング回路って何でしたっけ。ええと、詳解 Linux カーネルな記述が以下。
メモリ管理回路(MMU)は、セグメンテーション回路というハードウェアを用いて、論理アドレスをリニアアドレスに変換します。そのあと、ページング回路を用いて、リニアアドレスを物理アドレスに変換します。
詳解 Linux カーネル第3版より引用
中身を見てみます。
static physaddr_t check_va2pa(pde_t *pgdir, uintptr_t va) { pte_t *p; pgdir = &pgdir[PDX(va)]; if (!(*pgdir & PTE_P)) return ~0; p = (pte_t*) KADDR(PTE_ADDR(*pgdir)); if (!(p[PTX(va)] & PTE_P)) return ~0; return PTE_ADDR(p[PTX(va)]); }
PDX とか PTX あたりのマクロは mmu.h で定義されてて以下な考え方。
// A linear address 'la' has a three-part structure as follows: // // +--------10------+-------10-------+---------12----------+ // | Page Directory | Page Table | Offset within Page | // | Index | Index | | // +----------------+----------------+---------------------+ // \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/ // \----------- PPN(la) -----------/
linear address、という表現になってますね。PTE_P なマクロも mmu.h で以下。
// Page table/directory entry flags. #define PTE_P 0x001 // Present
フラグは 9 bits 分の領域なのかな、ちなみに PTE_ADDR も同様で定義が以下。
// Address in page table or page directory entry #define PTE_ADDR(pte) ((physaddr_t) (pte) & ~0xFFF)
あー、なんとなくそのまんまなカンジですね。ざっくり理解ですが
- Page Directory Index を取り出して Page table/directory entry であることを確認
- そうでなければ ~0 を戻す
- Offset を取り出して VA に変換
- 変換した VA は Page table/directory entry かどうか
- そうでなければ ~0 を戻す
- 変換した VA は Page table/directory entry かどうか
- Page Table Index な Offset を戻す
- これは PA って理解で良いのかな
うう
なんつーか、明快にイメージできてない。pages って何だ。もう少し pmap.c をがっつり読んだ方が良いみたいな会議中。