6

カーネルを初期化するとき、発生する必要があることがいくつかあります。1)ページングを有効にする必要があります。2)物理メモリマネージャーはgrubからメモリマップを解析する必要があります。3)さまざまな起動コードは必要なデータにアクセスする必要があります。後で使用するためにそこにとどまる(たとえば、GDT、IDT、メモリ管理構造)。

これらのステップ間の依存関係は私を夢中にさせています。上半分では、カーネルはその仮想アドレスでリンクされているため、私が思いついたオプションは次のとおりです。1)アセンブリでページングを有効にします。これには、(アセンブリ内の)すべてのマルチブートポインターをたどって、引き続きアクセスできるようにする必要があります。物理メモリマネージャに接続し、後でそれらすべてのマッピングを解除します。2)起動コードをその物理アドレスにリンクし、ポインタ操作を行って物理アドレスのカーネル構造にもアクセスします。または3)上位半分を使用しないでください。カーネル。

また、コンパイル時に物理メモリの量を知らなくても、物理メモリマネージャをブートストラップすることも含まれます。最初の構造を割り当てるときにすべてのマルチブート構造を慎重に回避するか、最初にすべてを使用してからそれらを上書きすることを心配しないでください(ただし、モジュールとこのアプローチを処理する必要があります)マルチブートテーブルを、物理メモリマネージャーのセットアップ中に必要な既知の場所にコピーする必要があります)。

これらの問題が、私がこれまで上位半分のカーネルを避けてきた理由です。これらの依存関係を解決するための優れたシステムを持っている人はいますか?リンク/仮想アドレスのカーネルと物理アドレスのマルチブートテーブルの両方にアクセスするためのこのGDTトリックのバリエーション、または上記の問題を回避するある種の事前定義されたページテーブルを使用する場合、おそらくPSEが関係しますか?

4

1 に答える 1

6

これが私がこの問題に取り組んだ方法です:

私のカーネルイメージは、GRUBによって(物理)アドレス0x01000000(16MB、ISA DMA領域のすぐ上)にロードされます。この画像は基本的に2つの部分で構成されています。

  1. 「初期初期化」セクション。このセクションには、上位半分のカーネルにジャンプする準備をするために実行されるコードが含まれています。また、このセクションでは、この準備中に使用されるスタックとヒープ用にいくらかのスペースを予約します。このセクションのすべてのコードは、(仮想)アドレス0x01000000でリンクされています。
  2. 画像の残りの部分には、上位半分のカーネルの一部であるコードとデータが含まれています。この部分のすべてのコードは、(仮想)アドレス0xc0000000(3GB)でリンクされています。

初期のinitセクションのコードは、ロードされた場所と同じアドレスにリンクされているため、GRUBは問題なくこのコードにジャンプできます。この初期の初期化コードは、次の手順を実行します。

  1. GRUBがカーネルに渡すMBI構造を再配置します。これには、初期初期化セクション内のヒープが使用されます。
  2. IDは、物理アドレス0x0から始まり、初期のinitセクションで使用される最後のページの物理アドレスまでのすべてのページをマップします。IDマッピングは、仮想アドレスが物理アドレスと同じであることを意味します。これにより、ページングを有効にした後でも、初期のinitセクションのコードを実行できるようになります。
  3. 上位半分のカーネルを仮想アドレス0xc0000000にマップします。
  4. ページングを有効にします。
  5. 上位半分のカーネルにジャンプします。

この時点で、残りの初期化は上位半分のコードから実行されます。これには、GDT、IDT、メモリ管理などの設定が含まれます。MBIは既知の場所に再配置されるため、独自のデータ構造で上書きすることを心配する必要はありません。

物理メモリマネージャーについて簡単に説明します。データ構造に必要なページ数を計算し、カーネルイメージの後の最初のページからこれらの構造を割り当て、これらのデータ構造の後からページの処理を開始します。

この説明が明確であることを願っています。そうでない場合は、私に知らせてください。必要に応じて、カーネルのコピーを提供することもできます。

于 2011-06-03T08:39:34.127 に答える