64 bit 環境におけるメモリマップの話 (その1/2)
GNU/Linux (以下、Linux) が ia64 アーキテクチャに対応してから久しいが。ここで改めて、仮想メモリの話題を中心に 64bit 環境での Linux の実装について勉強してゆく。
32bit 版 x86 環境におけるアドレス解決の方法や仮想メモリの取扱い方は、恐らくどのカーネル本にも載っている内容でもあるし、Onix カーネルフレームワークを作る仮定でずいぶん調べた。
しかし、64bit の仮想アドレスのメモリマップはどうなるのかや、アドレス解決はどうするのかといった内容をまとめて記載したページは、あまり存在しない。
なので今回は 64bit 版 x86 互換アーキテクチャにおけるこれらの内容について、Linux のコードを追いながら調べて行く。尚、例によって話が長くなったので、2 回に分ける事にする。
今回の内容は次の 3 つ。
・x86_64 における、アドレス解決の方法
・ " Linux のメモリマップ
・ " Linux でのページテーブル初期化処理
Linux でのページテーブル初期化処理については、次回に示す。
まずは、x86_64 におけるアドレス解決の方法について。
32bit 版 x86 互換アーキテクチャ (以下、x86) では、ページディレクトリテーブルとページテーブルによる 2 段階 (*1) のアドレス解決を行う事で、ページを特定する。
対して、64bit 版 x86 互換のアーキテクチャ (以下、x86_64) では、4 段階のアドレス解決を行う事で、ページを特定する。ただし、一般的に利用されるアドレスバスの幅は 48 ビットとなり、48-63 ビットは 47 ビットの符号拡張となる。この仕組みについて、英語版 wikipedia (*2) に詳しく記述してある (ちなみに日本語版では、このくだりがザックリと省かれている)。
次に、x86_64 における Linux のメモリマップについて。
ここで言っている "メモリマップ" とは、仮想メモリ空間をカーネルがどのように使うかの設計を言っている。x86 におけるメモリマップは 32 ビットのアドレス空間のうち、0x00000000 - 0xbfffffff までをユーザプロセスが使い、0xc0000000 - 0xffffffff までをカーネルが直接参照する領域としていた。又、カーネル参照領域もメモリゾーンで分割されており、特に 1GB を越える物理メモリをカーネル空間にマッピングさる為の ZONE_HIGH で表されるハイメモリ空間が有名である。
そして、仮想アドレス 0xC0000000 からのページ群を物理ページフレームにストレートマップさせる。
x86_64 における Linux のメモリマッピングについては、カーネルドキュメント (*3) に記載されている。以下、カーネルドキュメント抜粋。
0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
hole caused by [48:63] sign extension
ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0
ffffffffa0000000 - fffffffffff00000 (=1536 MB) module mapping space
(中略)
-Andi Kleen, Jul 2004
見てのとおり、0xffff8800 00000000 から始まる 46 ビット幅の領域を物理メモリにストレートマップさせると言っている。
実際の所は定かではないが、このように巨大な物理ページを仮想アドレス空間からダイレクトに参照できるので、x86 のハイメモリ空間みたいなまどろっこしい設計はいらない (*4)。
(*1) : CR4 特殊レジスタの PSE フラグをセットする事で実現する拡張ページを用いた場合、ページディレクトリが直接ページを参照する。つまりここで言う、1 段階のアドレス解決になる。
(*2) : http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
(*3) : Documentation/x86/x86_64/mm.txt
(*4) : その昔の 16 ビットアーキテクチャでは、1MB のアドレス空間を連続的に扱う為に、A20 アドレスラインなる仕組みがあり、それなりに機能していたらしい
- Category(s)
- 学習経過
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/ohyama/64-bit-74b05883306b304a3051308b30e130e230ea30de30c3306e8a71-305d306e1-2/tbping