linux内核汇编阶段分析(三)
接着上一篇
r1 =机器号,r2 = atags或dtb,
r8 = 偏移地址 r9 = cpuid, r10 = procinfo
这个函数主要是检测参数或者设备树的有效性的
tst r2, #0x3 @ aligned? r2指向该参数链表的起始位置,此处判断它是否字对齐
bne 1f 不对齐的话就返回0了
ldr r5, [r2, #0] 把r2加载到r5
cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? ATAG_CORE_SIZE=5我这里没有设备树所以没检查设备树 标签总大小5
cmpne r5, #ATAG_CORE_SIZE_EMPTY ATAG_CORE_SIZE_EMPTY=2
bne 1f 这里检测的是参数大小
ldr r5, [r2, #4] 加载R2+4,就是atag的下一个参数
ldr r6, =ATAG_CORE ATAG_CORE =0x54410001 标签列表开始标志
cmp r5, r6
bne 1f 这里检测的标签开始标识,ATAG_CORE是固定的
2: mov pc, lr @ atag/dtb pointer is ok 全部正常的话,我们就返回了
and r3, r9, #0x000f0000 @ architecture version
teq r3, #0x000f0000 @ CPU ID supported?
bne __fixup_smp_on_up @ no, assume UP
通过cpuid检查是否有多核不支持的话会跳转到__fixup_smp_on_up
bic r3, r9, #0x00ff0000
bic r3, r3, #0x0000000f @ mask 0xff00fff0
mov r4, #0x41000000
orr r4, r4, #0x0000b000
orr r4, r4, #0x00000020 @ val 0x4100b020
teq r3, r4 @ ARM 11MPCore?
moveq pc, lr @ yes, assume SMP
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
and r0, r0, #0xc0000000 @ multiprocessing extensions and
teq r0, #0x80000000 @ not part of a uniprocessor system?
moveq pc, lr @ yes, assume SMP
每个核都有一个MPIDR寄存器,并且每个核的MPIDR寄存器的值都不相同,这可以作为每个核的唯一标志。
没看懂,也没查到别人怎么说的,留着下一次再讲吧
比较长,我们慢慢分析
设置初始页表。
我们只设置了使内核运行所需要的最基本的数量,这通常意味着在内核代码中进行映射。
r8 = phys_offset, r9 = cpuid, r10 = procinfo
返回时
r0, r3, r5-r7 corrupted
r4 = physical page table address
pgtbl r4, r8 @ page table address
/*
* Clear the swapper page table
*/
mov r0, r4
mov r3, #0
add r6, r0, #PG_DIR_SIZE
1: str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
teq r0, r6
bne 1b
pgtbl 宏用于通过DRAM物理地址来获取页表的物理地址。
文本加载从管理程序中断向量地址开始。
TEXT_OFFSET - PG_DIR_SIZE=#16384; 0x4000
TEXT_OFFSET 内核在RAM中的起始位置相对于RAM起始地址偏移。值为0x00008000
./arch/arm/Makefile
textofs-y := 0x00008000
#define PG_DIR_SIZE 0x4000
R8= RAM第一个bank的物理起始地址0x40000000 PHYS_OFFSET
PAGE_OFFSET=0xc0000000代表的是内核空间和用户空间对虚拟地址空间的划分,对不同的体系结构不同。
.macro 如果有一段程序需要多次使用,为使程序不重复书写这段程序,可用宏定义把所需要重复出现的程序块定义成宏指令(这里有很多地址很乱啊,下一章总结一下)
R4清除swapper页面表
PROCINFO_MM_MMUFLAGS=8
创建身份映射以满足于enable_mmu。
这个标识映射将被paging_init()删除。
SECTION_SHIFT=20
PMD_ORDER=2
现在为我们的内核直接映射区域设置pagetables。
然后映射r2中的引导参数地址,或者如果没有指定引导参数地址,则映射ram的前1MB (2MB加上LPAE)。
返回
使能mmu后会执行这个方法
回到刚才
就跳转到刚才给r13赋值的start_kernel开始内核了
有很多很特别的地方没必要死抓,过两天看看内核说明再把仔细的讲解搬上来