Windows system >> Windowsの知識 >  >> Linuxシステムチュートリアル >> Linuxチュートリアル >> Linuxページングメカニズムの起動(X86)

Linuxページングメカニズムの起動(X86)

  

ページングメカニズムを有効にするLinuxが起動すると、まずリアルモードで実行され、次にプロテクトモードになります。第2章のメカニズムではLinuxのセグメンテーション設定を紹介したので、ここでは主にページングメカニズムに関する問題について説明します。 Linuxカーネルコードへのエントリポイントは/arch/i386/kernel/head.Sのstartup_32です。

1。ページテーブルの初期初期化:


/*

*ここでページテーブルはたった8MBに初期化されています - 最終ページ

*テーブルが設定されていますメモリサイズに応じて後で上がります。

* /

.org 0x2000

ENTRY(pg0)


.org 0x3000 < Br>

ENTRY(pg1)


/*

* empty_zero_pageはページテーブルの直後に続かなければなりません!(

*初期化ループのカウントempty_zero_pageまで)

* /


.org 0x4000

ENTRY(empty_zero_page)


/*

*ページテーブルの初期化

* /


movl $ pg0 -__ PAGE_OFFSET、%edi /*ページテーブルの初期化* /

movl $ 007、%eax /*" 007"は強制終了を意味するものではありませんが、

PRESENT + RW + USER * /

2:stosl

$ 0x1000、%eaxを追加します。

cmp $ empty_zero_page -__ PAGE_OFFSET、%edi

jne 2b

このコードは、ページメカニズムがまだ有効になっていないため、カーネルによって実行されます。保護モードに入らなかったので、命令レジスタEIPのアドレスはまだ物理アドレスですが、pg0は仮想グラウンドを格納しているためです。 (カーネルをコンパイルした後にgccによって形成されるシンボリックアドレスが仮想アドレスであると考えてください。)したがって、 "$ pg0 -__ PAGE_OFFSET"は、pg0の物理アドレスを得るためにそれは0x00102000であり、pg1の物理アドレスは0x00103000です。 2つのページテーブルPg0とpg1のエントリは、0x007、0x1007、0x2007などに設定されています。最下位の3ビットは1で、2ページがユーザーページで書き込み可能で、ページの内容がメモリ内にあることを示しています(図2.24参照)。マッピングされた物理ページのベースアドレスは、0x0、0x1000、0x2000など、すなわち物理メモリ内のページ0、1、2、3などであり、合計2Kページ、すなわち8MBの記憶空間がマッピングされる。 Linuxカーネルの最小物理メモリー所要量は8MBであることがわかります。次に、empty_zero_pageページ(ゼロページ)が格納され、ゼロページにはシステム起動時のパラメータとコマンドラインパラメータが格納されます(詳細は13章を参照)。


2。ページングメカニズムを有効にします。


/*

*これは、0〜8MでIDマッピングを作成するために初期化されます(ブートアップのため)。

*目的のために)仮想アドレスでの0-8M領域の別のマッピング

* PAGE_OFFSET。

* /

.org 0x1000

ENTRY(swapper_pg_dir)

.long 0x00102007

.long 0x00103007

.fill BOOT_USER_PGD_PTRS-2,4,0

/*デフォルト値:766エントリ* /

.long 0x00102007

.long 0x00103007

/*デフォルト値:254エントリ* /

.fill BOOT_KERNEL_PGD_PTRS-2,4,0

/*


*ページングを有効にする

* /

3:

movl $ swapper_pg_dir -__ PAGE_OFFSET、%eax

movl%eax、%cr3 /*ページテーブルポインタを設定します。* /

movl%cr0、%eax

orl $ 0x80000000、%eax

movl% Eax、%cr0 /*そしてページング(PG)ビットを設定する* /

jmp 1f /*プリフェッチキューをフラッシュする* /

1:

movl $ 1 f、%eax

jmp *%eax /* eipが再配置されていることを確認してください。* /

1:



最初にこのコードの機能を見てみましょう。このコードは、ページディレクトリswapper_pg_dirの物理アドレスを制御レジスタcr3にロードし、cr0の最上位位置を1に設定することでページングメカニズムを開きます。

ただし、ページングメカニズムは有効になっています。この時点では、命令レジスタEIPのアドレスは仮想アドレスではなく物理アドレスであるため、Linuxカーネルが実際に保護モードに入るわけではありません。 ' jmp 1f'命令は論理的には何も言いませんが、機能的には命令パイプラインの内容を破棄するように動作します(これはIntelのi386テクニカルドキュメントで推奨されています)。ジャンプ、EIPはまだ物理アドレスです。次のmov命令とjmp命令は、番号1の2番目のアドレスをEAXレジスタにロードし、そこでジャンプします。これら2つの命令の実行中、EIPは依然として<1MB +どこかにある”物理アドレスを指す。コンパイラはすべてのシンボルアドレスを仮想メモリ空​​間に作成するので、2番目のラベル1のアドレスは仮想メモリ空​​間のどこかにあるため((PAGE_OFFSET + somewhere))、jmp命令が実行された後、EIPは仮想メモリ空​​間を指します。 CPUをカーネル空間に移行させ、リアルモードからプロテクトモードへのスムーズな移行を完了させるカーネル空間のアドレス。次に、ページディレクトリswapper_pg_dirの内容を確認します。 2つのページテーブルpg0およびpg1の開始物理アドレスはそれぞれ0x00102000および0x00103000であることが知られており、図2から22から分かるように、ページディレクトリエントリの最下位12ビットがページテーブルの属性を記述するために使用される。 0と最初のディレクトリエントリ0x00102007、0x00103007は、2つのページテーブルpg0とpg1が書き込み可能で、ページテーブルの内容がメモリ内にあることを意味します。

次に、2番目のページテーブルをswapper_pg_dirに置きます。 〜767合計766個のディレクトリエントリが0に設定されます。ページテーブルサイズは4KBなので、各テーブルエントリは4バイトを占有します。つまり、各ページテーブルは1024エントリを含み、各ページサイズも4KBです。したがって、これら768個のディレクトリエントリはマッピングされています。仮想空間は768×1024×4K = 3Gです。つまり、swapper_pg_dirテーブルの最初の768個のディレクトリエントリは、ユーザ空間をマップします。最後に、pg0とppは、768番目と769番目のディレクトリエントリに格納されます。 Pg1は2つのページテーブルのアドレスおよび属性を示し、770から1023までの254個のディレクトリエントリを0に設定する。256個のディレクトリエントリによってマッピングされる仮想アドレス空間は256×1024×4K = 1Gであり、これはswapper_pg_dirテーブルである。最後の256個のディレクトリエントリはカーネル空間にマッピングされています。



初期ページのディレクトリswapper_pg_dirには、ユーザー空間とカーネル空間の両方があります。図6.6に示すように、最初の2つのディレクトリエントリ、つまり8MBの領域のみがマッピングされ、同じマッピングを持ちます。

図6.6初期ページディレクトリのマッピングswapper_pg_dir

読者Q、カーネルは実行後にカーネル空間で実行されますが、なぜユーザー空間の低空間(8M)もマッピングされ、カーネル空間の低空間へのマッピングも同じですか?要するに、リアルモードからプロテクトモードです。スムーズな移行特に、CPUがカーネルコードのstartup_32の開始点に入ると、この場合、ページディレクトリがカーネル空間のみをマッピングし、ユーザー空間の下位スペースをマッピングしない場合、ページマッピングメカニズムが有効になると、実行を継続することはできません。真ん中の命令レジスタEIPは依然として下位領域を指しており、絶対転送またはサブルーチンがシンボルアドレスに対して呼び出されるまで、命令は物理アドレスでフェッチされます。そのため、Linuxカーネルは上記のソリューションを採用しました。

Copyright © Windowsの知識 All Rights Reserved