[オリジナル](B)は、Linux物理メモリ初期化

背景

  • Read the fucking source code! --By魯迅
  • A picture is worth a thousand words. --Byゴーリキー

説明:

  1. カーネルのバージョン:4.14
  2. ARM64プロセッサ、コンテックス-A53、二核
  3. ツールを使用してください:Source Insightは3.5、Visioの

1.はじめに

私たちはいくつかの簡単な質問を考えてみましょうか?

  1. システムがどのように物理メモリを認識しているのですか?
  2. 実メモリ管理初期化コードが実行される前にカーネルがどのように対処するメモリを割り当てる必要がありますか?

さんが読んで、最初の質問に答えることをしてみましょうdts学生をドキュメント見ている必要がありますmemoryへのノードのarch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi例:

    memory@80000000 {
        device_type = "memory";
        reg = <0x00000000 0x80000000 0 0x80000000>;
              /* DRAM space - 1, size : 2 GB DRAM */
    };

このノードは、開始アドレスとメモリのサイズを記述し、実際には、カーネルは、構文解析dtbファイル読む時間memoryシステムメモリに登録して検出するように、ノードの内容を。

そして、新たな問題再び?Ubootは意志kernel imagedtbメモリにコピーし、そしてだろうdtb物理地址知らせるkernelkernel物理アドレスから読み取る必要があるdtb最後のメモリ情報を取得するために、ファイルおよび解決、dtbアクセスする仮想アドレスにマッピングされる物理アドレスが、今回はpaging_initまだしていません呼び出して、それはそれを行うにはどのようにして、物理アドレスのマッピングがまだ完了していないと言うことでしょうか?はい、Fixed mapメカニズムが登場しました。

すべての物理メモリは、システムに追加された:2番目の質問への答えmm_initのシステムが使用する前に、memblockメモリを管理するためのモジュールを。

アドベンチャーは、それを開きます!

2. early_fixmap_init

簡単に言えば、Fixed map仮想アドレス期間の領域を指し、並進ステージ内のすべての線形アドレスは、この領域で良好に決定され、これらの仮想アドレスは、必要boot物理アドレスフェーズにマッピングします。
仮想アドレス空間の写真を見て:

図はfixed: 0xffffffbefe7fd000 - 0xffffffbefec00000、記載されているFixed map領域です。

そして、この地域のより詳細なレイアウトは何ですか?見てください、それは明確な計画を構造をしますarch/arm64/include/asm/fixmap.henum fixed_address

図からわかるようにアクセスしたい場合は、DTB物理アドレスが配置され、その後、物理アドレスをにマップする必要があるFixed map地域、そして仮想アドレスが領域にアクセスします。アクセスIOスペースが同じ理由で、次のようにと話をします。

そして、見てみましょうearly_fixmap_init、それの機能のキーコード:

void __init early_fixmap_init(void)
{
    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    unsigned long addr = FIXADDR_START;              /* (1) */

    pgd = pgd_offset_k(addr);           /* (2) */
    if (CONFIG_PGTABLE_LEVELS > 3 &&
        !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa_symbol(bm_pud))) {
        /*
         * We only end up here if the kernel mapping and the fixmap
         * share the top level pgd entry, which should only happen on
         * 16k/4 levels configurations.
         */
        BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
        pud = pud_offset_kimg(pgd, addr);
    } else {
        if (pgd_none(*pgd))
            __pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);          /* (3) */
        pud = fixmap_pud(addr);
    }
    if (pud_none(*pud))
        __pud_populate(pud, __pa_symbol(bm_pmd), PMD_TYPE_TABLE);    /* (4) */
    pmd = fixmap_pmd(addr);
    __pmd_populate(pmd, __pa_symbol(bm_pte), PMD_TYPE_TABLE);        /* (5) */
......
}

キーポイント:

  1. FIXADDR_START定義Fixed map領域の開始アドレスは、配置されているarch/arm64/include/asm/fixmap.h中で、
  2. pgd_offset_k(addr)入手するにはaddrPGDグローバル・ページ・テーブルに対応するアドレスをentry、このPGDグローバル・ページ・テーブルは、swapper_pg_dirグローバル・ページ・テーブル;
  3. bm_pud物理アドレスは、内容の書かれたPGDグローバル・ページ・テーブルです。
  4. bm_pmd物理アドレスが書かれたPUDのページディレクトリテーブルです。
  5. bm_pte物理アドレスは、内容の書かれたPMDのページテーブル表です。

bm_pud/bm_pmd/bm_pteページ・テーブル、ページテーブル記憶レベルの中央に対応する3つのグローバル配列、entry次のように定義されます:

static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused;
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;

実際には、early_fixmap_init再び使用される対応を移入するときだけ充填を行っていないマッピング、特定の物理および仮想アドレスのマッピングのための枠組みを確立し、これはユーザー固有ですpte entryようなfixmap_remap_fdt()機能は、典型的な充填でpte entry読み取る前にマッピングの最終段階を完了するために、プロセスdtbファイルを。

理解するための絵に、理解して徹底しました:

3. early_ioremap_init

あなたは初期ブートで動作する必要がある場合はIO设备、その後、ioremap一緒にプレイするために、実際のメモリ管理との関係が大きすぎ、あまりにも詳細な分析ではありませんので。

簡単に言えば、ioremap空間7 * 256K領域に格納されているslot_vir[]場合、最終的にIO操作の必要性、呼び出す、アレイ__early_ioremap機能、充填に相当する機能をpte entryこのように仮想アドレスと物理アドレスの最終的なマッピングを完成。

4. memblock

以上の内容について、単に適切にアクセスするためには、伏線されDTBたファイルを物理アドレス情報を解決します。以下の呼び出し手順への入口から最終追加:

したがって、この章の焦点はしているmemblockモジュール、これは初期のメモリ割り当てマネージャーです、私は助けるが、中に前に考えることはできませんNuttx達成するためのメモリプール、および詳細は、すでに明らかではないが、思考の枠組みは似ています。

4.1構造

これは、3つのデータ構造の合計によって記述されています。

  • struct memblockこれは、すべての物理メモリを維持するために使用されるグローバル変数を定義し;
  • struct memblock_typeメモリ及び記憶保持を含むシステム、メモリの代表的なタイプは、実際に使用されます。
  • struct memblock_region特定のメモリ領域を記述するために使用され、中に含まれる配列、あなたは128まで保存することができます。struct memblock_typeregions

その上に直接コード:

static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
#endif

struct memblock memblock __initdata_memblock = {
    .memory.regions     = memblock_memory_init_regions,
    .memory.cnt     = 1,    /* empty dummy entry */
    .memory.max     = INIT_MEMBLOCK_REGIONS,
    .memory.name        = "memory",

    .reserved.regions   = memblock_reserved_init_regions,
    .reserved.cnt       = 1,    /* empty dummy entry */
    .reserved.max       = INIT_MEMBLOCK_REGIONS,
    .reserved.name      = "reserved",

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
    .physmem.regions    = memblock_physmem_init_regions,
    .physmem.cnt        = 1,    /* empty dummy entry */
    .physmem.max        = INIT_PHYSMEM_REGIONS,
    .physmem.name       = "physmem",
#endif

    .bottom_up      = false,
    .current_limit      = MEMBLOCK_ALLOC_ANYWHERE,
};

定義されたmemblock定義が初期化されているグローバル変数として。初期化時間regions点アレイのサイズ前記静的グローバル配列であるINIT_MEMBLOCK_REGIONS、即ち128は、これらのメモリブロックの数を制限し、実際にこの値よりも、配列がされる場合、コードに見ることができます2倍高速の動的拡張。

初期化が終わった後は、一般的には次のようになります。

4.2 memblock_add / memblock_remove

memblockサブモジュール、基本的なロジックを追加および削除操作のメモリに関連し、そして最終的に呼び出すことによってmemblock_add_range/memblock_remove_range達成しました。

  • memblock_add_range

図の左側は、パフォーマンスが適切な部分で達成され、機能の実行を示すフローチャートです。図面の右側の部分は、実際の状況は、より多くのがあってもよい典型的なケースであるが、コアロジックが中に挿入されたregion物理アドレス範囲の重複が表示された場合、次に実行、決意split最終それを備え、操作を行動操作。flagregionmerge

  • memblock_remove_range
    典型的な場合、以下に示すような機能による効果:

今複数の領域にまたがるオフ領域を、削除する必要がある場合region、それは最初に呼び出されます、memblock_isolate_rangeこの作品分割領域であることを、その後、呼び出しmemblock_isolate_range地域ベースの上でregion除去操作。

あなたが呼び出すとmemblock_alloc、IPアドレスを割り当てるための最後の呼び出しを機能をmemblock_add_range実現するために、このメモリのアプリケーションは、最終的に追加されますreserved入力し、結局、他の人が使用すべきではない、出て配分されています。

5. arm64_memblock_init

物理メモリがシステムに追加されると、arm64_memblock_init主な仕事は、いくつかの特別な領域を追加することで、全体の物理メモリを整理しますreservedメモリに。以下に示すように機能が、完成されています。

  • ライトグリーンのボックスが示しているメモリ領域を確保されており、残りの部分は、あなたがメモリの実際の使用に行くことができるということです。

物理メモリの一般的な外観があり、メモリページテーブルマッピングの必要性についてのフォローアップは、の仮想アドレスから物理アドレスへの実際のマッピングを行います。

それは継続されるでしょう。

おすすめ

転載: www.cnblogs.com/LoyenWang/p/11440957.html