mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Apply suggestions from code review
Co-authored-by: garasubo <garasubo@gmail.com>
This commit is contained in:
@@ -268,7 +268,7 @@ frame.map(|frame| frame.start_address() + u64::from(addr.page_offset()))
|
||||
|
||||
これらのアプローチはすべて、準備のためにページテーブルに対する修正が必要になります。例えば、物理メモリへの対応付けを作ったり、レベル4テーブルのエントリを再帰的に対応付けたりなどです。問題は、これらの必要な対応付けを作るためには、すでにページテーブルにアクセスできるようになっていなければいけないということです。
|
||||
|
||||
これが意味するのは、私達のカーネルが使うページテーブルを作っている、ブートローダの手助けが必要になるということです。ブートローダはページテーブルにアクセスできますから、私達の必要とするどんな対応付けも作れます。`bootloader`クレートは上の2つのアプローチをどちらもサポートしており、現在の実装においては[cargoのfeatures][cargo features]を使ってこれらをコントロールします。
|
||||
つまり、私達のカーネルが使うページテーブルを作っている、ブートローダの手助けが必要になるということです。ブートローダはページテーブルにアクセスできますから、私達の必要とするどんな対応付けも作れます。`bootloader`クレートは上の2つのアプローチをどちらもサポートしており、現在の実装においては[cargoのfeatures][cargo features]を使ってこれらをコントロールします。
|
||||
|
||||
[cargo features]: https://doc.rust-lang.org/cargo/reference/features.html#the-features-section
|
||||
|
||||
@@ -479,7 +479,7 @@ if !entry.is_unused() {
|
||||
|
||||
レベル2やレベル1のテーブルも、同じ手続きをレベル3とレベル2のエントリに対して繰り返すことで見ることができます。お察しの通りそれを書くとかなり長くなるので、コードの全てはここには示しません。
|
||||
|
||||
ページテーブルを手作業で辿ると、CPUが変換を行う様子を理解できて面白いです。しかし、多くの場合は与えられた仮想アドレスに対応する物理アドレスにのみ興味があるので、そのための関数を作りましょう。
|
||||
ページテーブルを手作業で辿ると、CPUが変換を行う仕組みを理解できて面白いです。しかし、多くの場合は与えられた仮想アドレスに対応する物理アドレスにのみ興味があるので、そのための関数を作りましょう。
|
||||
|
||||
### アドレスの変換
|
||||
|
||||
@@ -556,7 +556,7 @@ fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr)
|
||||
|
||||
`Virtaddr`構造体には、(仮想メモリの)インデクスから4つの階層のページテーブルを計算してくれるメソッドが備わっています。この4つのインデクスを配列に格納することで、これらを`for`ループを使って辿ります。`for`ループを抜けたら、最後に計算した`frame`を覚えているので、物理アドレスを計算できます。この`frame`は、forループの中ではページテーブルのフレームを指していて、最後のループのあと(すなわちレベル1エントリを辿ったあと)では対応する(物理)フレームを指しています。
|
||||
|
||||
ループの中の話をします。前と同じように`physical_memory_offset`を使ってフレームをページテーブルの参照に変換します。次に、そのページテーブルのエントリを読み、[`PageTableEntry::frame`]関数を使って対応するフレームを取得します。もしエントリがフレームに対応付けられていなければ`None`を返します。もしエントリが2MiBや1GiBのhuge pageに対応付けられていたら、今のところはpanicすることにします。
|
||||
ループの中では、前と同じように`physical_memory_offset`を使ってフレームをページテーブルの参照に変換します。次に、そのページテーブルのエントリを読み、[`PageTableEntry::frame`]関数を使って対応するフレームを取得します。もしエントリがフレームに対応付けられていなければ`None`を返します。もしエントリが2MiBや1GiBのhuge pageに対応付けられていたら、今のところはpanicすることにします。
|
||||
|
||||
[`PageTableEntry::frame`]: https://docs.rs/x86_64/0.14.2/x86_64/structures/paging/page_table/struct.PageTableEntry.html#method.frame
|
||||
|
||||
@@ -598,7 +598,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
||||
|
||||

|
||||
|
||||
期待したとおり、恒等対応しているアドレス`0xb8000`は同じ物理アドレスに変換されました。コードページとスタックページは物理アドレスのどこかしかに変換されていますが、その場所はブートローダが私達のカーネルのために最初に作った対応づけに依存します。また、下から12ビットは変換のあとも常に同じであるということも注目に値します:この部分は[ページオフセット][_page offset_]であり、変換には関わらないためです。
|
||||
期待したとおり、恒等対応しているアドレス`0xb8000`は同じ物理アドレスに変換されました。コードページとスタックページは物理アドレスのどこかしかに変換されていますが、その場所はブートローダがカーネルの初期対応づけをどのようにつくったかによります。また、下から12ビットは変換のあとも常に同じであるということも注目に値します:この部分は[ページオフセット][_page offset_]であり、変換には関わらないためです。
|
||||
|
||||
[_page offset_]: @/edition-2/posts/08-paging-introduction/index.ja.md#x86-64niokerupezingu
|
||||
|
||||
|
||||
Reference in New Issue
Block a user