Linux-3.7.1 arm启动过程笔记

时间:2021-10-26 04:55:28

最新的linux-3.7.1发布,和linux-2.6.xxarm启动部分有些修改,主要去掉了查找板子型号,采用新的dtb描述板级信息。

内核被解压缩程序解压到PHY_OFFSET+0x8000,即物理内存偏移0x8000处(当然这也不是绝对,arch/arm/Makefiletextofs-y决定这个值)。

解压后内核的入口arch/arm/kernel/head.S:79stext.head.S:59开始的注释里解压缩代码调用此地址,需要MMU=offD-cache=off,I-cache=don’tcare,

r0= 0,r1=machine nr,r2 = atags or dtb pointer

接下来主要过程如下:

safe_svcmode_maskallr9 切换到SVC模式,并禁止所有中断

mrc p15,0, r9, c0, c0 获取cpuidr9

__lookup_processor_type; 获取cpuid相关procinfo地址r5;r5r10

ldrr8, =PHYS_OFFSET ; 板子物理内存偏移r8

现在r1machineno , r2 = atags or dtb, r8 = phys_offset, r9 = cpuid, r10 = procinfo

__vet_atags ;检查r2atags or dtb合法性,非法r2返回0arm/kernel/head-common.S

__create_page_tables ;建立页表

ldrr13, =__mmap_switched

adrlr, BSYM(1f) @ return (PIC) address

movr8, r4 @ set TTBR1 to swapper_pg_dir

ARM(add pc, r10, #PROCINFO_INITFUNC)

1: b __enable_mmu



接下来直接用图说话,万恶的word,把我码的字毁了

  1. 我们使用qemu模拟arm启动,并在到start_kernel之前导出内存镜像

  2. 下载qemu-1.3 并编译,安装,具体怎么做baidu or google

  3. 下载内核源码linux-3.7.1 交叉编译,我使用cpurealview-pb-a8

  4. 制作文件系统,我们使用initramfs 把内核和文件系统做在一起



直接看图

Linux-3.7.1 arm启动过程笔记

输入qemu-system-arm-M realview-pb-a8 -kernel ./zImage -append "noinitrdinit=/linuxrc console=ttyAMA0 mem=128M" -s -S

Linux-3.7.1 arm启动过程笔记

此时qemu会处于Stopped状态,等待gdb连接

Linux-3.7.1 arm启动过程笔记

进入内核目录,输入arm-none-linux-gnueabi-gdb./vmlinux 运行如下

Linux-3.7.1 arm启动过程笔记

输入targetremote localhost:1234,start_kernel处设置断点linit/main.c:400

Linux-3.7.1 arm启动过程笔记

Start_kernel处于init/main.c:468行,设置断点b468;接着继续运行

Linux-3.7.1 arm启动过程笔记

Gdb出现断点停住后,鼠标进入qemu界面里(鼠标在qemu黑框里点一下),按ctrl+alt+2切换到控制台,想切换回来使用ctrl+alt+1

Linux-3.7.1 arm启动过程笔记

导出当前内存只导出1M,保存文件名为mem.log,在qemu控制台输入memsave0xc0000000 1024*1024 mem.log.注意此时mmu已经开启所以为0xc0000000.接下来我们分析一下内存镜像

我们使用hexdump打开来看

Linux-3.7.1 arm启动过程笔记

其中*表示这之间的内容全为0

Arm启动代码中,说明一级页表描述符是从内存偏移16K处建立,即0xc0004000.从内存镜像我们可以看出一级页表描述符

0x4000-0x5c03全为0

0x5c040x70100c0e

0x5c08-0x6fff全为0

0x7000-0x7027:0x7000 0c0e

0x7010 0c0e

0x70200c0e

…….

0x70800c0e

0x70900c0e

0x7028-0x7fff全为0

一级页描述符(Level1 Descriptor),一个这样的表项占4个字节,可以是以下四种格式之一:

Linux-3.7.1 arm启动过程笔记

如果描述符的最低两位是00,属于Fault格式,表示该范围的VA没有映射到PA。如果描述符的最低两位是10,属于Section格式,这种格式没有二级页表而是直接映射到物理页面,一个Section1M的大页面,描述符中[31:20]位就是这个页面的基地址,基地址的[19:0]低位全为0,对齐到1M地址边界,描述符中的DomainAP位控制访问权限,CB两位控制缓存。

Realview的内存物理地址0x7000 0000.一级页表从0x7000 4000 建立,则Cp15 TTB=0x7000 4000

当CPU发出虚拟地址VA时候

CP15 TTB [31..14]à一级页表基地址,(16K对齐)

VA[31..20]>>20 一级页表偏移。

                                   ------------->物理首地址 TTB & 0xffff c000 | (VA&0xfff0 0000 >>20)

VA[19..0] 代表物理首地址偏移。

VA 对应物理地址 *(TTB & 0xffff c000 | (VA&0xfff0 0000 >>20))+VA & 0x000f ffff

例:

Cpu 寻址 0xc000 2210

页表基址:TTB = 0x7000 4000 ,TTB & 0xffffc000 =0x7000 4000

页表偏移:VA[31..20] = 0xc000 2210 & 0xfff0 0000 >>20  0xc000 0000 >>20=0xc00

最终物理首地址 *(0x7000 4000+0xc00)=0x0000 0000

0x7000 4c00没有映射物理地址,访问失败


根据上述镜像,我可以得出:

0x5c04 :0x7010 0c0e  

页内偏移=0x5c04-0x4000=0x1c04 因为4Byte对齐 0x1c04>>2=0x701

VA[31..20]=0x1c04<<20=0x7010 0000

由此可以看出VA=0x701x xxxx被mmu映射到0x701x xxxx的物理地址上,一一映射

0x7000 :0x7000 0c0e

页内偏移=0x7000-0x4000=0x3000 因为4Byte对齐 0x3000>>2=0xc00

VA[31..20]=0xc00<<20=0xc000 0000

由此可以看出VA=0xc00x xxxx被mmu映射到0x700x xxxx的物理地址上

0x7004 :0x7010 0c0e  页内偏移=0x7004-0x4000=0x3004 因为4Byte对齐 0x3004>>2=0xc01

VA[31..20]=0xc01<<20=0xc010 0000

由此可以看出VA=0xc01x xxxx被mmu映射到0x701x xxxx的物理地址上

……..

为什么会有0x5c04 à0x7010 0c0e.内核在开启mmu后….