call setup_vm// 跳转到C函数setup_vm,setup_vm会创建临时页表#ifdefCONFIG_MMUla a0,early_pg_dir call relocate//重定向,实际就是开启MMU#endif/* CONFIG_MMU */call setup_trap_vector/* 重载C环境 */la tp,init_task sw zero,TASK_TI_CPU(tp)la sp,init_thread_union+THREAD_SIZE#ifdefCONFIG_KASA...
RISC-VLinux启动,经历了两次页表创建过程,第一次使用C函数setup_vm()创建临时页表,第二次使用C函数setup_vm_final()创建最终页表。 具体细节参考代码中的注释,下面的代码省略了一些不重要的部分。 setup_vm() asmlinkagevoid__initsetup_vm(uintptr_tdtb_pa){uintptr_tva, pa, end_va;uintptr_tload_pa = ...
RISC-V Linux启动时的页表创建相对来说还是比较容易理解的,都是C语言创建的,代码也比较少。主要就是setup_vm()和setup_vm_final()两个页表创建函数。理解了sv39的一些地址格式后,再去分析源码就比较容易。不过不同kernel版本代码都不一样,需要具体情况具体分析。 本篇提到了setup_vm()会检查kernel入口地址是否2M...
RISC-V Linux启动时的页表创建相对来说还是比较容易理解的,都是C语言创建的,代码也比较少。主要就是setup_vm()和setup_vm_final()两个页表创建函数。理解了sv39的一些地址格式后,再去分析源码就比较容易。不过不同kernel版本代码都不一样,需要具体情况具体分析。 本篇提到了setup_vm()会检查kernel入口地址是否2M...
asmlinkage void __init setup_vm(uintptr_t dtb_pa) { pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd; /* 初始化内核的开始虚拟地址 */ /*在arch/riscv/include/asm/pgtable.h中定义了KERNEL_LINK_ADDR * 这个值的大小为0x FFFFFFFF 80000000*/ kernel_map.virt_addr = KERNEL_LINK_ADDR; ...
boot_jump_linux kernel--使用images->ep地址,以gd->arch.boot_hart和images->ft_addr作为第1-2参数。 RISC-V kernel启动时保存a0/a1寄存器到s0/s1: _start _start_kernel mv s0, a0 mv s1, a1 setup_vm--以DTB物理地址为参数,配置页表映射。
临时页表分析 MMU开启前,需要建立好kernel、dtb、trampoline等页表。以便MMU开启后,并且在内存管理模块运行之前,kernel可以正常初始化,dtb可以正常地被解析。这部分页表都是临时页表,最终的页表在setup_vm_final()建立。 临时页表创建顺序: 首先为fixmap创建早期的PGD
编译过程:使用交叉编译工具链对内核源代码进行编译。编译过程可能需要一定的时间和资源。编译完成后,会生成内核镜像文件(例如vmlinux)和相关的模块文件。 内核加载和启动:将编译生成的内核镜像文件和模块文件加载到目标设备上,并进行启动。具体的加载和启动过程可能因硬件平台而异,可以参考相关文档和资料。
callsetup_vm 1. 2. 3. 4. 5. 6. 7. setup_initial_init_mm() 设备树解析完成后,进行了早期内存的初始化,给出了代码段的起始与结束位置,数据段的结束位置,堆地址结束位置。 [0.000000]OF:fdt:Ignoringmemoryrange0x80000000-0x80200000 [0.000000]Machinemodel:riscv-virtio,qemu ...
下载完毕后,就要开始编译。首先在riscv-gnu-toolchain根目录下,创建build目录。用于编译riscv gcc。 riscv gcc可以编译成以下几个版本 riscv32-unknown-elf-gcc riscv64-unknown-elf-gcc riscv32-unknown-linux-gnu-gcc riscv64-unknown-linux-gnu-gcc ...