ホームページ >運用・保守 >Linuxの運用と保守 >実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

嵌入式Linux充电站
嵌入式Linux充电站転載
2023-08-01 15:37:591214ブラウズ

前回の記事では、RISC-V Linux のエントリ アドレスが 2M にアライメントされている必要があると述べましたが、今日は 2M アライメントの問題を解決する方法について説明します。メモリの一部を最適化します。

注: この記事は linux5.10.111 カーネルに基づいています

メモリ使用量分析

各チップが工場から出荷された時点で、そのブートROMのアドレスはチップ内に固定されていると仮定します。ブートROMは0x0、つまり上記のとおりです。電源を入れると、プログラムはアドレス0x0から実行を開始します。

RISC-V Linux を起動する前に、最初に opensbi を実行する必要があるため、opensbi をアドレス 0x0处,这样芯片上电后,就会从0x0地址处执行opensbi。在opensbi运行完后,会跳转到opensbi运行地址偏移2M的位置去执行下一级boot(这里下一级boot是kernel),即跳转到0x200000地址处运行kernel,因此应该把kernel放到内存的0x200000 に配置する必要があります。

メモリ分布図は次のとおりです:

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

カーネルの場合、起動時に独自のカーネルからアドレスをロードします (つまり、0x200000) は、ページ テーブル マッピングの確立を開始します。ページ テーブル マッピングが物理メモリに対して確立された場合にのみ、後でこれらのメモリにアクセスできるようになります。カーネルはアドレスの前に 2M メモリをロードします (つまり、0x0 - 0x200000) はカーネルによって無視され、この 2M メモリに対してページ テーブルは確立されません。つまり、カーネルはこの 2M メモリにアクセスできません。 0x200000)开始建立页表映射,只有对物理内存建立了页表映射,后面才能访问这些内存。而kernel加载地址前面的2M内存(即0x0 - 0x200000)将被kernel忽略,不会对这2M内存建立页表,即kernel无法访问这2M内存。

在QEMU上RISC-V Linux的启动信息:

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

但opensbi实际不需要使用2M这么大的范围,默认是512KB,opensbi的pmp会保护这512KB内存,不让其他程序访问。

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

因此在Kernel和opensbi之间会存在1.5M

QEMU 上の RISC-V Linux の起動情報:

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化 ただしopensbi は実際には 2M ほどの範囲を使用する必要はありません。デフォルトは 512KB、opensbi の pmp はこれを保護します512KB メモリ。他のプログラムによるアクセスは許可されません。 実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

したがって、カーネルと opensbi の間には 1.5M メモリ ギャップ、およびメモリギャップのこの部分はプログラムによって使用されないため、メモリの無駄が発生します。では、メモリの以前の部分をカーネルに使用させるにはどうすればよいでしょうか。

最適化計画

この 2M メモリを最適化するには 2 つの計画があります: 🎜🎜🎜オプション 1🎜: opensbi をメモリの最後に置き、カーネル エントリ アドレスは 2M アラインメントを維持します。 🎜🎜🎜オプション 2🎜: Opensbi は引き続きメモリの先頭に配置されます。カーネル ソース コードを変更し、2M アライメント制限を解除することで、カーネル アドレスを前方に移動できます。 🎜

オプション 1

opensbi をメモリの最後に置きますが、カーネル エントリ アドレスは 2M アラインメントを維持します。

つまり、カーネルはメモリの前に配置され、opensbi は後ろに配置されます。

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

たとえば、カーネルはメモリの 0x0地址处,opensbi放到内存的0x10000000地址处。这样kernel前面就不会有预留内存,只不过这样需要修改bootrom的地址,将地址从0x0修改为0x0x10000000。这种方案只适合芯片还没出厂前,因为用户无法修改bootrom的地址,芯片出厂后,bootrom地址是固定的,假设bootrom地址为0x0,那么芯片上电后,就会从0x0开始运行程序,所以opensbi必须放到0x0 アドレスに配置されるため、カーネルは2Mオフセット。

オプション 2

RISC-V Linux のカーネル ソース コードを変更して、2M アライメント制限を解除することもできます。必要なのは setup_vm () 関数を使用して、 元の第 2 レベルのページ テーブルを第 3 レベルのページ テーブルに変更します。これにより、カーネル エントリ アドレスを 4K に揃えるだけで済み、カーネルを前方に移動するため、フロントメモリが使用されます。 setup_vm()函数中,将原来的二级页表改为三级页表,这样kernel入口地址只需要4K对齐,因此就能将kernel往前挪,从而利用前面的内存。

修改代码

路径:arch/riscv/mm/init.c

コードを変更します

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化パス: arch /riscv/mm/init.c

元の 2M アライメント チェックをコメントします:

実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

カーネルの最初の 2M ページ テーブル マッピングを第 2 レベルのページ テーブルから第 3 レベルのページ テーブルに変更します。 :

//新增一个PTE
pte_t trampoline_pte[PTRS_PER_PTE] __page_aligned_bss;

create_pgd_mapping(trampoline_pg_dir,PAGE_OFFSET,
                   (uintptr_t)trampoline_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(trampoline_pmd,PAGE_OFFSET,
                   (uintptr_t)trampoline_pte,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + PMD_SIZE;
for (va = PAGE_OFFSET; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(trampoline_pte,PAGE_OFFSET,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

カーネル全体のページテーブルマッピングが第 2 レベルのページテーブルから第 3 レベルのページテーブルに変更されます:
実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化
カーネルサイズが 4M+
実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化
//定义三个PTE
pte_t load_sz_pte[PTRS_PER_PTE] __page_aligned_bss;
pte_t load_sz_pte1[PTRS_PER_PTE] __page_aligned_bss;
pte_t load_sz_pte2[PTRS_PER_PTE] __page_aligned_bss;

//=======0-2M======
create_pgd_mapping(early_pg_dir,PAGE_OFFSET,
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + PMD_SIZE;
for (va = PAGE_OFFSET; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte,PAGE_OFFSET,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

//=======2-4M==========
create_pgd_mapping(early_pg_dir,PAGE_OFFSET + PMD_SIZE,
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte1,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + (PMD_SIZE * 2);
for (va = PAGE_OFFSET + PMD_SIZE; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte1,va,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

//=======4-6M==========
create_pgd_mapping(early_pg_dir,PAGE_OFFSET + (PMD_SIZE*2),
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte2,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + (PMD_SIZE * 3);
for (va = PAGE_OFFSET + (PMD_SIZE*2); va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte2,va,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

🎜🎜 であると仮定します。 🎜🎜上記のコードを変更することにより、カーネル エントリは、アドレスを 1.5M ずつ前方に移動し、opensbi 用に 512KB のみを予約できるようになり、RISC-V Linux の起動後に利用可能な物理メモリが増加します。 🎜
実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化

概要

RISC-V Linuxエントリアドレスの2Mアライメント操作はまだ説明されていませんが、opensbi用に2Mを予約する必要があるため、カーネルはセカンダリページテーブルを確立するだけです。エントリアドレスは 2M でアライメントされている必要があります。メモリのこの部分の最適化ソリューションはまだ誰も提供していません。この記事の最適化ソリューションが一部の人々を助け、すべての人にインスピレーションを与えることを願っています。

以上が実践的な戦闘 | RISC-V Linux エントリ アドレス 2M 予約メモリの最適化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は嵌入式Linux充电站で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。