微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式 arm平台kernel启动第二阶段分析

嵌入式 arm平台kernel启动第二阶段分析

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

链表必须以ATAG_CORE开始,以ATAG_NONE结束。这里的ATAG_CORE,ATAG_NONE是各个参数的标记,本身是一个32位值,例如:ATAG_CORE=0x54410001。其它的参数标记还包括:ATAG_MEM32,ATAG_INITRD,ATAG_RAMDISK,ATAG_COMDLINE等。每个参数标记就代表一个参数结构体,由各个参数结构体构成了参数链表。参数结构体的定义如下:

structtag{
structtag_headerhdr;
union{
structtag_corecore;
structtag_mem32mem;
structtag_videotextvideotext;
structtag_ramdiskramdisk;
structtag_initrdinitrd;
structtag_serialnrserialnr;
structtag_revisionrevision;
structtag_videolfbvideolfb;
structtag_cmdlinecmdline;
structtag_acornacorn;
structtag_memclkmemclk;
}u;
};

参数结构体包括两个部分,一个是tag_header结构体,一个是u联合体。

tag_header结构体的定义如下:

structtag_header{

u32size;

u32tag;

};

其中size:表示整个tag结构体的大小(用字的个数来表示,而不是字节的个数),等于tag_header的大小加上u联合体的大小,例如,参数结构体ATAG_CORE的size=(sizeof(tag->tag_header)+sizeof(tag->u.core))>>2,一般通过函数tag_size(struct*tag_xxx)来获得每个参数结构体的size。其中tag:表示整个tag结构体的标记,如:ATAG_CORE等。

/*r8=machinfo

*Returns:

*r2eithervalidatagspointer,orzero

*/

__vet_atags:

tstr2,#0x3@aligned?r2指向该参数链表的起始位置,此处判断它是否字对齐

bne1f@如果没有对齐,跳到标号1处直接返回,并且把r2的值赋值为0,作为返回值

ldrr5,[r2,#0]@isfirsttagATAG_CORE?获取第一个tag结构的size

cmpr5,#ATAG_CORE_SIZE@判断该tag的长度是否合法

cmpner5,#ATAG_CORE_SIZE_EMPTY

bne1f@如果不合法,异常返回

ldrr5,[r2,#4]@获取第一个tag结构体的标记

ldrr6,=ATAG_CORE@取出标记ATAG_CORE的内容

cmpr5,r6@判断该标记是否等于ATAG_CORE

bne1f@如果不等,异常返回

movpc,lr@atagpointerisok,如果都相等,则正常返回

1:movr2,#0@异常返回值

movpc,lr@异常返回

ENDPROC(__vet_atags)

//

__vet_atags函数的具体解析结束(\arch\arm\kernel\head-common.S)

//

/*创建内核初始化页表*/

bl__create_page_tables

//

__create_page_tables函数的具体解析开始(\arch\arm\kernel\head.S)

//

/*

*r8=machinfo

*r9=cpuid

*r10=procinfo

*Returns:

*r4=physicalpagetableaddress

*/

/*在该文件的开头有如下宏定义*/

#defineKERNEL_RAM_PADDR(PHYS_OFFSET+TEXT_OFFSET)

.macropgtbl,rd

ldr\rd,=(KERNEL_RAM_PADDR-0x4000)

.endm

其中:PHYS_OFFSET在arch/arm/mach-s3c2410/include/mach/memory.h定义,为UL(0x30000000),而TEXT_OFFSET在arch/arm/Makefile中定义,为内核镜像在内存中到内存开始位置的偏移(字节),为$(textofs-y)textofs-y也在文件arch/arm/Makefile中定义,为textofs-y:=0x00008000,r4=30004000为临时页表的起始地址,首先即是初始化16K的页表,高12位虚拟地址为页表索引,每个页表索引占4个字节,所以为4K*4=16K,大页表,每一个页表项,映射1MB虚拟地址.

__create_page_tables:

/*为内核代码存储区域创建页表,首先将内核起始地址-0x4000到内核起始地址之间的16K存储器清0,将创建的页表存于此处*/

pgtblr4@r4中存放的为页表的基地址,最终该地址会写入cp15的寄存器c2,这个值必须是16K对齐的

movr0,r4@把页表的基地址存放到r0中

movr3,#0@把r3清0

addr6,r0,#0x4000@r6指向16K的末尾

1:strr3,[r0],#4@把16K的页表空间清0

strr3,[r0],#4

strr3,[r0],#4

strr3,[r0],#4

teqr0,r6

bne1b

/*从proc_info_list结构中获取字段__cpu_mm_mmu_flags,该字段包含了存储空间访问权限等,此处指令执行之后r7=0x00000c1e*/

ldrr7,[r10,#PROCINFO_MM_MMUFLAGS]@mm_mmuflags

/*为内核的第一MB创建一致的映射,以为打开MMU做准备,这个映射将会被paging_init()移除,这里使用程序计数器来获得相应的段的基地址*/

movr6,pc

movr6,r6,lsr#20@startofkernelsection

orrr3,r7,r6,lsl#20@flags+kernelbase

strr3,[r4,r6,lsl#2]@identitymapping

/*MMU是通过C2中基地址(高18位)与虚拟地址的高12位组合成物理地址,在转换表中查找地址条目。R4中存放的就是这个基地址0x30004000*/

addr0,r4,#(KERNEL_START&0xff000000)>>18@r0=0x30007000r0存放的是转换表的起始位置

strr3,[r0,#(KERNEL_START&0x00f00000)>>18]!@r3存放的是内核镜像代码段的起始地址

ldrr6,=(KERNEL_END-1)@获取内核的尾部虚拟地址存于r6中

addr0,r0,#4@第一个地址条目存放在0x3

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

网站地图

Top