微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM linux解析之压缩内核zImage的启动过程

ARM linux解析之压缩内核zImage的启动过程

时间:11-10 来源:互联网 点击:

(0x24)存入CP15的C2寄存器,这样ARM就知道到哪里去找那些页表项了。下面我们来看一下整个MMU的虚拟地址的寻址过程,如图4所示。

简单解释一下。首先,ARM的CPU从CP15的C2寄存器中找取出页表基地址,然后把虚拟地址的最高12位左移两位变为14位放到页表基址的低14位,组合成对应1M空间的页表项在MMU页表中的地址。然后,再取出页表项的值,检查AP位,域,判断是否有读写的权限,如果没有权限测会抛出数据或指令异常,如果有权限,就把最高12位取出加上虚拟地址的低20位段内偏移地址组合成最终的物理地址。到这里整个MMU从虚拟地址到物理地址的转换过程就完成了。

这段代码里,只会开启页表所在代码的开始的256K对齐的一个0x10(256M)空间的大小(这个空间必然包含解压后的内核),使能cache和write buffer,其他的4G-256M的空间不开启。这里使用的是1:1的映射。到这里也很容易明白MMU和cache和write buffer的关系了,为什么不开MMU无法使用cache了。

图.4 MMU的段页表的虚拟地址与物理地址的转换过程

这里的4G空间全部映射完成之后,还会做一个映射,代码如下:

movr1, #0x1e

orr r1, r1, #3 < 10

movr2, pc

movr2, r2, lsr #20

orr r1, r1, r2, lsl #20

add r0, r3, r2, lsl #2

strr1, [r0], #4

add r1, r1, #1048576

strr1, [r0]

movpc, lr

通过注释就可以知道把当前PC所在地址1M对齐的地方的2M空间开启cache和write buffer为了加快代码在nor flash中运行的速度。然后反回,到这里16K的MMU页表就完全建立好了。

然后再反回到建立页表后的代码,如下:

movr0, #0

mcrp15, 0, r0, c7, c10, 4@ drain write buffer

tstr11, #0xf@ VMSA

mcrnep15, 0, r0, c8, c7, 0@ flush I,D TLBs

#endif

mrcp15, 0, r0, c1, c0, 0@ read control reg

bicr0, r0, #1 < 28@ clear SCTLR.TRE

orr r0, r0, #0x5@ I-cache enable, RR cache replacement

orr r0, r0, #0x003c@ write buffer

#ifdef CONFIG_MMU

#ifdef CONFIG_CPU_ENDIAN_BE8

orr r0, r0, #1 < 25@ big-endian page tables

#endif

orrner0, r0, #1@ MMU enabled

movner1, #-1

mcrnep15, 0, r3, c2, c0, 0@ load page table pointer

mcrnep15, 0, r1, c3, c0, 0@ load domain access control

#endif

mcrp15, 0, r0, c1, c0, 0@ load control register

mrcp15, 0, r0, c1, c0, 0@ and read it back

movr0, #0

mcrp15, 0, r0, c7, c5, 4@ ISB

movpc, r12

这段代码就不具体解释了,多数是关于CP15的控制寄存器的操作,主要是flush I-cache,D-cache, TLBS,write buffer,然后存页表基址啊,最后打开MMU这个是最后一步,前面所有东西都设好之后再使用MMU,否则系统就会挂掉。最后用保存在r12中的地址,反回到BL cache_on的下一句代码。如下:

restart:adr r0,LC0

ldmiar0, {r1, r2, r3, r6, r10, r11, r12}

ldrsp, [r0, #28]

sub r0, r0, r1@ calculate the delta offset

add r6, r6, r0@ _edata

add r10, r10, r0@ inflated kernel size location

好了,先来看一下LC0是什么东西吧。

.align2

.typeLC0, #object

LC0:.wordLC0@ r1

.word__bss_start@ r2

.word_end@ r3

.word_edata@ r6

.wordinput_data_end - 4 @ r10 (inflated size location)

.word_got_start@ r11

.word_got_end@ ip

.word.L_user_stack_end@ sp

.sizeLC0, . - LC0

好吧,要理解它,再把arch/arm/boot/vmlinux.lds.in搬出来吧:

_got_start = .;

.got: { *(.got) }

_got_end = .;

.got.plt: { *(.got.plt) }

_edata = .;

. = BSS_START;

__bss_start = .;

.bss: { *(.bss) }

_end = .;

. = ALIGN(8);

.stack: { *(.stack) }

.align

.section ".stack", "aw", %nobits

再加上最后一段代码,关于stack的空间的大小分配:

.L_user_stack:.space4096

.L_user_stack_end:

这里不仅可以看到各个寄存器里所存的值的意思,还可以看到. = BSS_START;在这里的作用

arch/arm/boot/compressed/Makefile里面:

ifeq ($(CONFIG_ZBOOT_ROM),y)

ZTEXTADDR:= $(CONFIG_ZBOOT_ROM_TEXT)

ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)

else

ZTEXTADDR:= 0

ZBSSADDR := ALIGN(8)

endif

SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/

对应到这里的话,就是BSS_START =ALIGN(8),这个替换过程会在vmlinux.lds.in到vmlinux.lds的过程中完成,这个过程主要是为了有些内核在nor flash中运行而设置的。

好了,再次言归正传,从vmlinux.lds文件,可以看到链接后各个段的位置,如下。

图.5 zImage各个段的位置

从这里可以看到,zImage在RAM中运行和在NorFlash中直接运行是有些

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top