linux内核汇编阶段分析(三)

接着上一篇

r1 =机器号,r2 = atagsdtb

r8 = 偏移地址 r9 = cpuid, r10 = procinfo

 

linux内核汇编阶段分析(三)

 

 

linux内核汇编阶段分析(三)

这个函数主要是检测参数或者设备树的有效性的

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 全部正常的话,我们就返回了

 

linux内核汇编阶段分析(三)

       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寄存器的值都不相同,这可以作为每个核的唯一标志。

 

linux内核汇编阶段分析(三)

没看懂,也没查到别人怎么说的,留着下一次再讲吧

 

linux内核汇编阶段分析(三)

 

比较长,我们慢慢分析

设置初始页表。

我们只设置了使内核运行所需要的最基本的数量,这通常意味着在内核代码中进行映射。

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物理地址来获取页表的物理地址。

linux内核汇编阶段分析(三)

文本加载从管理程序中断向量地址开始。

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页面表

linux内核汇编阶段分析(三)

PROCINFO_MM_MMUFLAGS=8

创建身份映射以满足于enable_mmu

这个标识映射将被paging_init()删除。

SECTION_SHIFT=20

PMD_ORDER=2

 

linux内核汇编阶段分析(三)

 

现在为我们的内核直接映射区域设置pagetables

 

linux内核汇编阶段分析(三)

然后映射r2中的引导参数地址,或者如果没有指定引导参数地址,则映射ram的前1MB (2MB加上LPAE)

 

linux内核汇编阶段分析(三)

返回

 

linux内核汇编阶段分析(三)

使能mmu后会执行这个方法

linux内核汇编阶段分析(三)

 

回到刚才

linux内核汇编阶段分析(三)

linux内核汇编阶段分析(三)

linux内核汇编阶段分析(三)

linux内核汇编阶段分析(三)

就跳转到刚才给r13赋值的start_kernel开始内核了

 

有很多很特别的地方没必要死抓,过两天看看内核说明再把仔细的讲解搬上来