Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

嵌入式Linux充电站
嵌入式Linux充电站ke hadapan
2023-08-01 15:37:59946semak imbas

Artikel sebelumnya menganalisis penciptaan jadual halaman untuk permulaan RISC-V Linux Disebutkan bahawa alamat kemasukan RISC-V Linux mesti sejajar 2M Hari ini saya akan bercakap tentang cara menyelesaikan masalah penjajaran 2M, atau bagaimana mengoptimumkan sebahagian daripada ingatan.

Nota: Artikel ini berdasarkan kernel linux5.10.111

Analisis penggunaan memori

Apabila setiap cip keluar dari kilang. Dengan anggapan cip itu telah kukuh di dalam kilang bootrom adalah 0x0, iaitu, di atas Selepas dihidupkan, program akan mula berjalan dari alamat 0x0.

Sebelum memulakan RISC-V Linux, anda perlu menjalankan opensbi terlebih dahulu, jadi opensbi perlu diletakkan di alamat 0x0处,这样芯片上电后,就会从0x0地址处执行opensbi。在opensbi运行完后,会跳转到opensbi运行地址偏移2M的位置去执行下一级boot(这里下一级boot是kernel),即跳转到0x200000地址处运行kernel,因此应该把kernel放到内存的0x200000.

Rajah agihan ingatan adalah seperti berikut:

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

Untuk kernel, ia akan memuatkan alamat dari kernelnya sendiri apabila bermula (iaitu 0x200000) mula mewujudkan pemetaan jadual halaman. Hanya apabila pemetaan jadual halaman ditubuhkan untuk memori fizikal, kenangan ini boleh diakses kemudian. Kernel memuatkan memori 2M di hadapan alamat (iaitu 0x0 - 0x200000) akan diabaikan oleh kernel, dan jadual halaman tidak akan ditubuhkan untuk memori 2M ini, iaitu, kernel tidak boleh mengakses memori 2M ini. 0x200000)开始建立页表映射,只有对物理内存建立了页表映射,后面才能访问这些内存。而kernel加载地址前面的2M内存(即0x0 - 0x200000)将被kernel忽略,不会对这2M内存建立页表,即kernel无法访问这2M内存。

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

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

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

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

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

Maklumat permulaan RISC-V Linux pada QEMU:

opensbi sebenarnya tidak perlu menggunakan julat sebesar 2M lalai ialah 512KB, pmp opensbi akan melindungimemori 512KB, tidak dibenarkan untuk diakses oleh atur cara lain. . font-size: 14px;overflow-wrap: break-word; padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05 );font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">1.5M jurang memori , dan bahagian jurang memori ini tidak digunakan oleh program, yang akan menyebabkan pembaziran memori Jadi bagaimana untuk membiarkan kernel menggunakan bahagian memori sebelumnya? . Pilihan 2

: Opensbi masih diletakkan pada permulaan memori Dengan mengubah suai kod sumber kernel dan mengangkat sekatan penjajaran 2M, alamat kernel boleh dialihkan ke hadapan.

Pilihan 1

Kami meletakkan opensbi di hujung memori, dan alamat kemasukan kernel masih mengekalkan penjajaran 2M.

Iaitu, kernel diletakkan di hadapan memori, dan opensbi diletakkan di belakang:

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

Sebagai contoh, kernel diletakkan di alamat 0x0地址处,opensbi放到内存的0x10000000地址处。这样kernel前面就不会有预留内存,只不过这样需要修改bootrom的地址,将地址从0x0修改为0x0x10000000。这种方案只适合芯片还没出厂前,因为用户无法修改bootrom的地址,芯片出厂后,bootrom地址是固定的,假设bootrom地址为0x0,那么芯片上电后,就会从0x0开始运行程序,所以opensbi必须放到0x0 memori, jadi kernel hanya boleh diimbangi oleh 2M.

Pilihan 2

Kami juga boleh mengubah suai kod sumber kernel RISC-V Linux untuk menarik balik sekatan penjajaran 2M. Kita hanya perlu setup_vm () fungsi, tukar jadual halaman peringkat kedua asal kepada jadual halaman peringkat ketiga, supaya alamat kemasukan kernel hanya perlu diselaraskan pada 4K, supaya kernel boleh bergerak ke hadapan, dengan itu menggunakan ingatan hadapan. setup_vm()函数中,将原来的二级页表改为三级页表,这样kernel入口地址只需要4K对齐,因此就能将kernel往前挪,从而利用前面的内存。

修改代码

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

Ubah suai kod

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimumanLaluan: arch /riscv/mm/init.c

Ulas semakan penjajaran 2M asal:

Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

Tukar pemetaan jadual halaman 2M pertama bagi kernel daripada jadual halaman peringkat kedua kepada jadual halaman peringkat ketiga :

//新增一个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);
}

Pemetaan jadual halaman keseluruhan kernel ditukar daripada jadual halaman peringkat kedua kepada jadual halaman peringkat ketiga:
Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman
Andaikan saiz kernel ialah 4M+
Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman
//定义三个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);
}

🎜🎜🎜 🎜🎜Dengan mengubah suai kod di atas, entri Kernel boleh Pindahkan alamat ke hadapan sebanyak 1.5M dan menempah hanya 512KB untuk opensbi, supaya selepas RISC-V Linux bermula, memori fizikal yang tersedia akan meningkat. 🎜. alamat kemasukan mestilah sejajar 2M. Belum ada sesiapa yang memberikan penyelesaian pengoptimuman untuk bahagian memori ini. Saya harap penyelesaian pengoptimuman dalam artikel ini dapat membantu sesetengah orang dan memberi anda sedikit inspirasi.
Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman

Atas ialah kandungan terperinci Pertempuran praktikal |. RISC-V Linux alamat kemasukan 2M terpelihara pengoptimuman. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:嵌入式Linux充电站. Jika ada pelanggaran, sila hubungi admin@php.cn Padam