boot地址侧
uboot 将 Image 加载到 地址A
Image 加载地址"Load Address"的限制
TODO
虚拟内存侧
uboot 在 加载 内核最后一步, MMU 肯定是关的
Image 运行过程中 , MMU 会在 start_kernel 前 打开
开了 MMU 之后
物理地址 : 虚拟地址
实例
qemu virt rv32
地址
$ file arch/riscv/boot/Image
arch/riscv/boot/Image: MS-DOS executable PE32 executable RISC-V 32-bit (stripped to external PDB) Mono/.Net assembly, for MS Windows
$ ls arch/riscv/boot/Image -l
-rwxrwxr-x 1 suweishuai suweishuai 25912320 Jun 10 16:04 arch/riscv/boot/Image
Image 加载地址 : 0x80400000
PAGE_OFFSET : 0xC0000000
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
CONFIG_PAGE_OFFSET=0xC0000000
[ 0.000000] lowmem : 0xc0000000 - 0xdfc00000 ( 508 MB)
虚拟地址和物理地址的偏差 : 0x3fc00000
---
虚拟地址 符号 物理地址
0xc0c02000 early_pg_dir 0x81002000
0xc18ba000 trampoline_pg_dir 81CB A000
页表
页表描述
rv32 2级映射,32bit,20+(12)
对于section 映射,只有1级别
下面所有的表项都是PMD表项
每个表项4字节,寻址4M空间
- for mmu_on trampoline_pg_dir
create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr,kernel_map.phys_addr, PGDIR_SIZE, PAGE_KERNEL_E
trampoline_pg_dir 虚拟地址 0xc18ba000 , 物理地址为 0xc18ba000 - 0x3fc00000 = 0x81CBA000
0x81cbac00: 0x201000ef 0x00000000 0x00000000 0x00000000
- for kernel (临时内核(Image)页表) early_pg_dir
create_kernel_page_table(early_pg_dir, true);
0x81002c00 <early_pg_dir+3072>: 0x201000ef 0x202000ef 0x203000ef 0x204000ef
0x81002c10 <early_pg_dir+3088>: 0x205000ef 0x206000ef 0x207000ef 0x00000000
create_fdt_early_page_table(early_pg_dir, dtb_pa);
0x81002000 <early_pg_dir>: 0x00000000 0x27c000e7 0x00000000 0x00000000
create_pgd_mapping(early_pg_dir, FIXADDR_START, fixmap_pgd_next, PGDIR_SIZE, PAGE_TABLE);
early_pg_dir 物理地址 : 0x81002000
0x810029d0 <early_pg_dir+2512>: 0x00000000 0x00000000 0x00000000 0x2072e401
为什么 rv64 从 8020 0000 boot , 而 rv32 从 8040 0000 boot ?
80000000-8040000有没有创建映射
TODO
80000000 - 80400000是干啥的?
8000 0000 开头的地址中存储了 opensbi
Image 必须要从80400000启动吗?
TODO
kernel_map = {
page_offset = 0xc0000000,
virt_addr = 0xc0000000,
phys_addr = 0x80400000,
size = 0x18f8000,
va_pa_offset = 0x3fc00000,
va_kernel_pa_offset = 0x3fc00000,
va_kernel_xip_pa_offset = 0x0
}