简述
boot地址侧
uboot 加载 uImage 到 地址A
uboot 将 Image 加载到 地址B
Image 加载地址"Load Address"的限制
TODO
虚拟内存侧
uboot 在 加载 内核最后一步, MMU 肯定是关的
Image 运行过程中 , MMU 会在 start_kernel 前 打开
开了 MMU 之后
物理地址 : 虚拟地址
ZRELADDR : TEXTADDR
实例
qemu virt arm64
地址
$ ls arch/arm64/boot/Image -l
-rw-rw-r-- 1 suweishuai suweishuai 34750976 May 28 21:48 boot/Image
Image加载地址 : 40200000
Image最后一个字节地址:0x423b0000
kimage_vaddr : 0xffff800008000000
image_voffset : 0xffff7fffc7e00000
kimage_vaddr - Image加载地址(_text)
PAGE_OFFSET : 0xffff000000000000
__fdt_pointer : 0x48000000
页表
页表描述
arm64 四级映射,48bit,9+9+9+(9+12)
对于section 映射,只有3级别
下面所有的表项都是PGD表项/PUD表项/PMD表项
每个表项8字节,寻址2M空间
idmap
物理地址:0x41124000 - 0x411248cc 恒等(虚拟地址=物理地址)
虚拟地址:0x41124000 - 0x411248cc
__idmap_text_start - __idmap_text_end
ffff800009791000 D idmap_pg_dir
ffff800009794000 T idmap_pg_end
- for kernel (临时内核(Image)页表)
kernel map
物理地址:0x40200000 - 0x423b0000
虚拟地址:0xffff800008000000 - 0xffff80000a1b0000
_text - _end
ffff800008000000 T _text
ffff80000a1b0000 B _end
ffff80000a1a5000 B init_pg_dir
ffff80000a1a8000 B init_pg_end
ffff80000a1b0000 B _end
临时内核页表的起始虚拟地址由什么决定: KIMAGE_VADDR
KIMAGE_VADDR 值 为 arch/arm64/kernel/vmlinux.lds 中的 _text 地址值
155 . = KIMAGE_VADDR;
156
157 .head.text : {
158 _text = .;
159 HEAD_TEXT
160 }
注意 : 对于 VA_BITS >= 48 ,来讲, KIMAGE_VADDR 为固定值 : 0xffff800008000000
ffff800009794000 T tramp_pg_dir
ffff800009795000 T reserved_pg_dir
ffff800009796000 T swapper_pg_dir
ffff800008010800 T vectors
40000000-4020000有没有创建映射
在 start_kernel 前 没有创建映射
40000000 - 40200000是干啥的?
40000000 地址有bootloader ,但只有 9 字节, 第9字节是 Image 被加载的地址
Image 必须要从40200000启动吗?
Documentation/arm64/booting.rst 中 必须从
起始地址处 2MB 对齐处启动
但是实验数据表明:
偏移0MB不可启动,因为覆盖了bootloader
偏移1MB/512KB/256KB/128KB/64KB/32KB 可启动
偏移16KB 不可启动(不想查了)
dtb 的映射在哪里
TODO
mmu_on 页表 与 kernel 页表的切换
TTBR0_EL1 存储了 mmu_on 页表基址(0x41991000)
TTBR1_EL1 存储了 kernel 页表基址(0x423a5000)
SCTLR 存储了 0x200000034f4d91d(表示开了MMU)
当访问 以类似地址 0x0000aaaabbbbcccdddd 时, 采用 TTBR0_EL0
当访问 以类似地址 0xffffaaaabbbbcccdddd 时, 采用 TTBR0_EL1
__primary_switched 位于 0xffff8000097a032c , 当 pc 位于 0xffff8000097a032c 的时候,自动用TTBR0_EL1 (kernel 页表基址)
就自动完成了 mmu_on 页表 与 kernel 页表的切换
硬件相关
PHYS_OFFSET
179 extern s64 memstart_addr;
180
include/asm/memory.h:181:#define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }
uImage 相关
参考链接中的 uImage相关
Image 相关
虚拟地址
PAGE_OFFSET
PAGE_OFFSET 在 arm64 中 承担了 什么角色 , 和 __HEAD 有什么关系
42 #if (PAGE_OFFSET & 0x1fffff) != 0
43 #error PAGE_OFFSET must be at least 2MB aligned
44 #endif
45
46
61 __HEAD
36
43 #define VA_BITS (CONFIG_ARM64_VA_BITS)
44 #define _PAGE_OFFSET(va) (-(UL(1) << (va)))
45 #define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS))
46 #define KIMAGE_VADDR (MODULES_END)
47 #define MODULES_END (MODULES_VADDR + MODULES_VSIZE)
48 #define MODULES_VADDR (_PAGE_END(VA_BITS_MIN))
49 #define MODULES_VSIZE (SZ_128M)
50 #define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT)))
51 #define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE)
52 #define PCI_IO_END (VMEMMAP_START - SZ_8M)
53 #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE)
54 #define FIXADDR_TOP (VMEMMAP_START - SZ_32M)
运行时的页表
0000000000000000 0000ffffffffffff 256TB user
ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map
ffff800000000000 ffff9fffffffffff 128TB
PAGE_OFFSET 不作用于临时页表阶段,而是作用于运行时页表阶段
在运行时, ffff000000000000 应该对应 __HEAD(即 _text)
PAGE_END
PAGE_OFFSET = (-(UL(1) << (48))) = 0xFFFF000000000000
PAGE_END = (-(UL(1) << (48-1))) = 0xFFFF800000000000
TEXT_OFFSET
arm64 没有 TEXT_OFFSET 的概念
swapper_pg_dir
swapper_pg_dir 不用于临时页表阶段
位于 链接脚本顶层
122266 ffff800009791000 D idmap_pg_dir
122267 ffff800009794000 T idmap_pg_end
122268 ffff800009794000 T tramp_pg_dir
122269 ffff800009795000 T reserved_pg_dir
122270 ffff800009796000 T swapper_pg_dir
164401 ffff80000a1a5000 B init_pg_dir
164402 ffff80000a1a8000 B init_pg_end
164403 ffff80000a1b0000 B _end
43 idmap_pg_dir = .;
44 . += ((((((48)) - 4) / (12 - 3)) - 1) * (1 << 12));
45 idmap_pg_end = .;
46 tramp_pg_dir = .;
47 . += (1 << 12);
48 reserved_pg_dir = .;
49 . += (1 << 12);
50 swapper_pg_dir = .;
51 . += (1 << 12);
52 . = ALIGN(0x00010000);
53 __init_begin = .;
...
106 _edata = .;
107 . = ALIGN((1 << 12)); __bss_start = .; . = ALIGN((1 << 12)); .sbss : AT(ADDR(.sbss) - 0) { *(.dynsbss) *(.sbss) *(.scommon) } .
= ALIGN(0); .bss : AT(ADDR(.bss) - 0) { __hyp_bss_start = .; *(.hyp.bss) . = ALIGN((1 << 12)); __hyp_bss_end = .; . = ALIGN((1
<< 12)); *(.bss..page_aligned) . = ALIGN((1 << 12)); *(.dynbss) *(.bss) *(COMMON) } . = ALIGN(0); __bss_stop = .;
108 . = ALIGN((1 << 12));
109 init_pg_dir = .;
init_pg_dir
用于临时页表阶段
init_pg_dir 0x423a5000
init_pg_end 0x423a8000
idmap_pg_dir
用于临时页表阶段
idmap_pg_dir 0x41991000
idmap_pg_end 0x41994000
__idmap_text_start 0x41124000
物理地址
Image 物理地址
runtime __pa(_text)
runtime __pa(_end)
线性映射中 物理地址和虚拟地址的转换
virt_to_phys
phys_to_virt
其他
__relocate_kernel
(gdb) p/x $w9
$9 = 0x19070d0
(gdb) n
(gdb) p/x $w10
$10 = 0x4f4b20
(gdb) p/x $x11
$11 = 0xffff800008000000
(gdb) p/x $x9
$14 = 0xffff8000099070d0
(gdb) p/x $x10
$15 = 0xffff800009dfbbf0
X9 - X10
64bit 64bit 64bit
X12 X13 X14
addr TYPE value
if (TYPE == 1027(0x403)) *(uint64_t *)addr = value
arch/arm64/kernel/vmlinux.lds
12 . = ((((-(((1)) << ((((48))) - 1)))) + (0x08000000)));
13 .head.text : {
14 _text = .;
15 KEEP(*(.head.text))
16 }
84 .rela.dyn : ALIGN(8) {
85 *(.rela .rela*)
86 }
__rela_offset = ABSOLUTE(ADDR(.rela.dyn) - ((((-(((1)) << ((((48))) - 1)))) + (0x08000000))));
__rela_size = SIZEOF(.rela.dyn);
$ aarch64-linux-gnu-readelf -S vmlinux
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[21] .rela.dyn RELA ffff8000099070d0 019170d0
00000000004f4b20 0000000000000018 A 0 0 8
map
ARM64 start_kernel 前 有 两段映射
第一段是identity mapping,其实就是把物理地址mapping到物理地址上去,在打开MMU的时候需要这样的mapping(ARM ARCH强烈推荐这么做的)。
第二段是kernel image mapping,内核代码欢快的执行当然需要将kernel running需要的地址(kernel txt、dernel rodata、data、bss等等)进行映射了,
210
227 .macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
idmap map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14
kernel map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
x0 0x41991000 1100550144
x1 0x0 0
x2 0x40 64
x3 0x41124000 1091715072
x4 0x200 512
x5 0x21 33
x6 0x411248cc 1091717324
x7 0x701 1793
x8 0x0 0
x9 0x0 0
x10 0x0 0
x11 0x0 0
x12 0x0 0
x13 0x0 0
x14 0x0 0
x15 0x0 0
x16 0x0 0
x17 0x0 0
x18 0x0 0
x19 0x0 0
x20 0x0 0
x21 0x48000000 1207959552
x22 0x0 0
x23 0x0 0
x24 0x0 0
x25 0x0 0
x26 0x0 0
x27 0x0 0
x28 0x419a0018 1100611608
x29 0x0 0
x30 0x419a0054 1100611668
x0 0x423a5000 1111117824
x1 0x41994000 1100562432
x2 0x40 64
x3 0x40200000 1075838976
x4 0x200 512
x5 0xffff800008000000 -140737354137600
x6 0xffff80000a1b0000 -140737318813696
x7 0x701 1793
x8 0x0 0
x9 0x0 0
x10 0x9 9
x11 0x8 8
x12 0x41000701 1090520833
x13 0x41200000 1092616192
x14 0x41993000 1100558336
x15 0x0 0
x16 0x0 0
x17 0x0 0
x18 0x0 0
x19 0x0 0
x20 0x0 0
x21 0x48000000 1207959552
x22 0x0 0
x23 0x0 0
x24 0x0 0
x25 0x0 0
x26 0x0 0
x27 0x0 0
x28 0x419a0018 1100611608
x29 0x0 0
x30 0x419a0054 1100611668
|