LoginSignup
2
1

More than 3 years have passed since last update.

PageTableの簡略メモ

Last updated at Posted at 2021-03-16

page tableの構造

https://os.phil-opp.com/paging-introduction/#example-translation
image.png
x86_64だと4-level page tableが採用されている

Page Tableの主要な要素は、Index, frame, flagsの3つ
frameにはアドレス値が入っている

4-level page tableはこのPage Tableが4階層で構成されている.
構造としては以下の通り
image.png
48-39の部分がlevel 4のindexにそのまま当てはまる.
例: 0000000000000000 000001111 110000000 100000001 000110000 000000000000
1ブロック9bitなので、2^9=512で512entryで、1つのentryのサイズが8バイトであるため、1つのpage tableのサイズは512 * 8B = 4KiBである. なので、Page Tableが必要になる度に4KiBのメモリが必要になる.

CR3 <= lv4 page tableの仮想アドレス値が格納されている
lv4[0xb000001111] <= frameに格納されている数値をlv3 page tableの仮想アドレス値として扱う
lv3[110000000] <= frameに格納されている数値をlv2 page tableの仮想アドレス値として扱う
lv2[100000001] <= frameに格納されている数値をlv1 page tableの仮想アドレス値として扱う
lv1[000110000] <= frameに格納されている数値を物理アドレス値をして扱う (Identity Mappingだとこの値がそのまま解決された物理アドレスとして扱う. Map at a Fixed Offsetだと上の図のPage Offset分をこの物理アドレスに加算した値を解決された物理アドレスとして扱う

仮想アドレスと物理アドレスのmapping方法

Identity Mapping

仮想アドレスが物理アドレスと同じ値でmapされる
例: Identity Mappingで仮想アドレス0xb8000を物理アドレスに翻訳すると0xb8000になる

Map at a Fixed Offset

Identity Mappingの次にパフォーマンスが良い
linuxはこれを使ってるらしい

仮想アドレスが仮想アドレス+offset値でmapされる
例: Identity Mappingで仮想アドレス0xb8000を物理アドレスに翻訳すると0xb8000になる

  • 仮想アドレスにoffsetを足して使われる

その他

  • Map the Complete Physical Memory
  • Temporary Mapping
  • Recursive Page Tables
  • etc...

boot後

bootloaderがkernelを起動した時既にIdentity Mappingが施されている.
詳しくはここを参照: https://os.phil-opp.com/paging-introduction/#implementation

kernelが実装するpagingの用途

初めに私は勘違いしていました

  • kernelが動作するにはpagingが必要
  • pagingはkernelが実装する

あれ???循環依存してるので、これは何かおかしいぞ :thinking: と。

image.png
Frontend Architecture@2x (44).png

実際にはこうでした

  • kernelが動作するにはpagingが必要 <= bootloaderが設定してある
  • pagingはkernelが実装する <= user landのpagingはkernelが実装する

つまり、kernelのmemoryのmapping方法とuser landのmemoryのmapping方法は基本的に違います. (user landにIdentity Mappingを採用したら同じだけど
以下がその図です

image.png

kernelでpage tableをmapしてみる

create_example_mapping
// in src/memory.rs

use x86_64::{
    PhysAddr,
    structures::paging::{Page, PhysFrame, Mapper, Size4KiB, FrameAllocator}
};

/// Creates an example mapping for the given page to frame `0xb8000`.
pub fn create_example_mapping(
    page: Page,
    mapper: &mut OffsetPageTable,
    frame_allocator: &mut impl FrameAllocator<Size4KiB>,
) {
    use x86_64::structures::paging::PageTableFlags as Flags;

    let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
    let flags = Flags::PRESENT | Flags::WRITABLE;

    let map_to_result = unsafe {
        // FIXME: this is not safe, we do it only for testing
        mapper.map_to(page, frame, flags, frame_allocator)
    };
    map_to_result.expect("map_to failed").flush();
}

// in src/main.rs

fn kernel_main(boot_info: &'static BootInfo) -> ! {
    use blog_os::memory;
    use x86_64::{structures::paging::Page, VirtAddr}; // new import

    [] // hello world and blog_os::init

    let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
    let mut mapper = unsafe { memory::init(phys_mem_offset) };
    let mut frame_allocator = memory::EmptyFrameAllocator;

    // map an unused page
    let page = Page::containing_address(VirtAddr::new(0));
    memory::create_example_mapping(page, &mut mapper, &mut frame_allocator);

    // write the string `New!` to the screen through the new mapping
    let page_ptr: *mut u64 = page.start_address().as_mut_ptr();
    unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e)};

    [] // test_main(), "it did not crash" printing, and hlt_loop()
}

ここのPage::containing_address(VirtAddr::new(0));で取得したPageは未解決な仮想アドレスである.
このアドレスを上だとcreate_example_mappingに通すと、仮想アドレス0xb0は物理アドレス0xb8000にmapされる.
なので、下の2行でvga text bufferに書き込める.

    let page_ptr: *mut u64 = page.start_address().as_mut_ptr();
    unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e)};

補足

vga text bufferがbootloaderがkernelの為に設定したIdentity Mappingのtableで仮想アドレス0xb8000にアクセスすると、物理アドレス0xb8000にアクセスできる.
kernelがサンプルで用意したcreate_example_mappingを通したPageは物理アドレス0xb8000にmappingされる
その際に、複数のPage Tableのframeが同じ物理アドレスを指すことになるが、これは問題ない

参考文献

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1