PageManager.cpp 仮想メモリ 真のコンストラクタ(笑)パラメータにVRAMの大きさを与える。 何をしているんだか? 1)とりあえず、0から8MB分のページを確保している。ひとつのテーブルで1024エントリあって、 1エントリ4キロバイトだから、ひとつのテーブル当たり4メガバイト。よって、 2つ分のテーブルを確保している。しかし、テーブル用に確保される領域は2倍になっている。 その理由はMemoryManagerクラスのallocate関数にアライメント機能がないからである。 よって、2倍の大きさをとって(プラス4キロバイトで十分だと思うが)4キロバイトで アライメントできるところを起点としている。 void PageManager::setup(PhysicalAddress vram) { PageEntry* table1 = allocatePageTable(); PageEntry* table2 = allocatePageTable(); g_page_directory = allocatePageTable(); 2)次に確保したエントリを使用していることを示すビットマップを設定して、 エントリが指し示す物理アドレスと属性をsetAttribute関数で決めている。 パラメータは1番目から、エントリへのポインタ、存在、書き込み可、ユーザー使用、 になっている。(・・・全部ユーザー領域かよ・・・) /* allocate page to physical address 0-4MB */ for (int i = 0; i < ARCH_PAGE_TABLE_NUM; i++) { memoryMap_->mark(i); setAttribute(&(table1[i]), true, true, true, 4096 * i); } /* allocate page to physical address 4-8MB */ for (int i = 0; i < ARCH_PAGE_TABLE_NUM; i++) { memoryMap_->mark(i + 4096); setAttribute(&(table2[i]), true, true, true, 4096 * 1024 + 4096 * i); } 3)ページディレクトリを設定している。ディレクトリはページテーブルと同じ構造をしていて、 一つ一つのエントリはページテーブルのベースアドレスを指し示している。 /* Map 0-8MB */ memset(g_page_directory, 0, sizeof(PageEntry) * ARCH_PAGE_TABLE_NUM); setAttribute(&(g_page_directory[0]), true, true, true, (PhysicalAddress)table1); setAttribute(&(g_page_directory[1]), true, true, true, (PhysicalAddress)table2); 4)VRAM領域のページング設定。VRAM領域のそれぞれのページについて、そのページが 記録されているページテーブルが存在するかどうかを調べる。存在すれば、 g_page_directory[directoryIndex]の上位20ビットが目的のページテーブルの ベースアドレスになる。存在しない場合、仕方がないのでページテーブルを確保して ページディレクトリに登録して目的のページアドレスを得る。そして、VRAMのページを 登録する。 /* VRAM */ vram_ = vram; /* find 4KB align */ for (; vram % 4096; vram--); /* MAP VRAM 2MB */ for (int i = 0; i < 512; i++, vram += 4096) { PageEntry* table; dword directoryIndex = getDirectoryIndex(vram); dword tableIndex = getTableIndex(vram); if (isPresent(&(g_page_directory[directoryIndex]))) { table = (PageEntry*)(g_page_directory[directoryIndex] & 0xfffff000); } else { table = allocatePageTable(); memset(table, 0, sizeof(PageEntry) * ARCH_PAGE_TABLE_NUM); setAttribute(&(g_page_directory[directoryIndex]), true, true, true, (PhysicalAddress)table); } setAttribute(&(table[tableIndex]), true, true, true, vram); } 4)最後にページディレクトリのペースをCR3レジスタに登録して、 CR0レジスタの31ビット目をセットしてページングを開始する。 setPageDirectory((PhysicalAddress)g_page_directory); startPaging(); }