arm linux内核启动过程自解压后的启动分析.docx

上传人:b****2 文档编号:3086972 上传时间:2023-05-05 格式:DOCX 页数:15 大小:20.58KB
下载 相关 举报
arm linux内核启动过程自解压后的启动分析.docx_第1页
第1页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第2页
第2页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第3页
第3页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第4页
第4页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第5页
第5页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第6页
第6页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第7页
第7页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第8页
第8页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第9页
第9页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第10页
第10页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第11页
第11页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第12页
第12页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第13页
第13页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第14页
第14页 / 共15页
arm linux内核启动过程自解压后的启动分析.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

arm linux内核启动过程自解压后的启动分析.docx

《arm linux内核启动过程自解压后的启动分析.docx》由会员分享,可在线阅读,更多相关《arm linux内核启动过程自解压后的启动分析.docx(15页珍藏版)》请在冰点文库上搜索。

arm linux内核启动过程自解压后的启动分析.docx

armlinux内核启动过程自解压后的启动分析

内核启动过程分析

/*

*linux/arch/arm/kernel/head.S

*

*Copyright(C)1994-2002RussellKing

*Copyright(c)2003ARMLimited

*AllRightsReserved

*

*Thisprogramisfreesoftware;youcanredistributeitand/ormodify

*itunderthetermsoftheGNUGeneralPublicLicenseversion2as

*publishedbytheFreeSoftwareFoundation.

*

*Kernelstartupcodeforall32-bitCPUs

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#if(PHYS_OFFSET&0x001fffff)

#error"PHYS_OFFSETmustbeataneven2MiBboundary!

"//boundary(分界线)

#endif

#defineKERNEL_RAM_VADDR(PAGE_OFFSET+TEXT_OFFSET)

#defineKERNEL_RAM_PADDR(PHYS_OFFSET+TEXT_OFFSET)

/*

*swapper_pg_diristhevirtualaddressoftheinitialpage

*Weplacethepagetables16KbelowKERNEL_RAM_VADDR.Therefore,wemust

*makesurethatKERNEL_RAM_VADDRiscorrectlyset.Currently,weexpect

*theleastsignificant16bitstobe0x8000,butwecouldprobably

*relaxthisrestrictiontoKERNEL_RAM_VADDR>=PAGE_OFFSET+0x4000.

*/swapper_pg_dir是初始页表的虚拟地址.我们将页表放在KERNEL_RAM_VADDR以下16K的空间中.因此我们必须保证KERNEL_RAM_VADDR已经被正常设置.当前,我们期望的是这个地址的最后16bits为0x8000,但我们或许可以放宽这项限制到KERNEL_RAM_VADDR>=PAGE_OFFSET+0x4000.

#if(KERNEL_RAM_VADDR&0xffff)!

=0x8000

#errorKERNEL_RAM_VADDRmuststartat0xXXXX8000//内核的起始地址必须是32k对齐

#endif

.globlswapper_pg_dir//定义一个全局变量

.equswapper_pg_dir,KERNEL_RAM_VADDR-0x4000/*页表的起始地址,大小为16kb*/

.macropgtbl,rd/*定义一个宏,在建页表时用到*/

ldr\rd,=(KERNEL_RAM_PADDR-0x4000)

.endm

#ifdefCONFIG_XIP_KERNEL

#defineKERNEL_STARTXIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)

#defineKERNEL_END_edata_loc

#else

#defineKERNEL_STARTKERNEL_RAM_VADDR

#defineKERNEL_END_end/*内核镜像的结束地址(虚拟地址,在vmlinux.lds.S中定义)*/

#endif

/*

*Kernelstartupentrypoint.

*---------------------------

*这些参数同通常是由解压代码传进来的

*Thisisnormallycalledfromthedecompressorcode.Therequirements

*are:

MMU=off,D-cache=off,I-cache=dontcare,r0=0,

*r1=machinenr,r2=atagspointer.

*

*Thiscodeismostlypositionindependent,soifyoulinkthekernelat

*0xc0008000,youcallthisat__pa(0xc0008000).

*

*Seelinux/arch/arm/tools/mach-typesforthecompletelistofmachine

*numbersforr1.r1中放的是机器ID

*

*We'retryingtokeepcraptoaminimum;DONOTaddanymachinespecific

*craphere-that'swhatthebootloader(orinextreme极度的,welljustified合理的

*circumstances事件,详细事件,zImage)isfor.不要随意的添加机器ID,要和bootloard提供的相匹配。

*/

.section".text.head","ax"@定义一个.Text.head段,段的属性a是允许段,x可执行v

ENTRY(stext)@入口点

msrcpsr_c,#PSR_F_BIT|PSR_I_BIT|SVC_MODE@ensuresvcmode管理模式

@andirqsdisabled

mrcp15,0,r9,c0,c0@getprocessorid通过协处理器cp15的寄存器c0来获得

bl__lookup_processor_type@r5=procinfor9=cpuid判断内核是否支持处理器cpu

movsr10,r5@invalidprocessor(r5=0)?

beq__error_p@yes,error'p'

bl__lookup_machine_type@r5=machinfo通过机器码判断是否支持单板

movsr8,r5@invalidmachine(r5=0)?

beq__error_a@yes,error'a'

bl__vet_atags//检查atags合法性

bl__create_page_tables//创建页表

/*

*ThefollowingcallsCPUspecificcodeinapositionindependent

*manner.Seearch/arm/mm/proc-*.Sfordetails.r10=baseof

*xxx_proc_infostructureselectedby__lookup_machine_type

*above.Onreturn,theCPUwillbereadyfortheMMUtobe

*turnedon,andr0willholdtheCPUcontrolregistervalue.

*/

ldrr13,__switch_data@addresstojumptoafter

@mmuhasbeenenabled

adrlr,__enable_mmu@return(PIC)address

addpc,r10,#PROCINFO_INITFUNC

ENDPROC(stext)

linux/arch/arm/kernel/head-common.S

__lookup_processor_type:

adrr3,3f

ldmdar3,{r5-r7}

subr3,r3,r7@getoffsetbetweenvirt&phys

addr5,r5,r3@convertvirtaddressesto

addr6,r6,r3@physicaladdressspace

1:

ldmiar5,{r3,r4}@value,mask

andr4,r4,r9@maskwantedbits

teqr3,r4

beq2f

addr5,r5,#PROC_INFO_SZ@sizeof(proc_info_list)

cmpr5,r6

blo1b

movr5,#0@unknownprocessor

2:

movpc,lr

ENDPROC(__lookup_processor_type)

linux/arch/arm/kernel/head-common.S这段代码的定义地址

3:

.long

.long__arch_info_begin

.long__arch_info_end

__lookup_machine_type:

adrr3,3b@r3中存放这标号3处的物理地址

ldmiar3,{r4,r5,r6}@r4中存放标号3处的虚拟地址,r5=__arch_info_begin的虚拟地址,r6存放的是__arch_info_end的虚拟地址

subr3,r3,r4@getoffsetbetweenvirt&phys物理地址与虚拟地址间的偏移量

addr5,r5,r3@convertvirtaddressestor5也变成了对应的物理地址

addr6,r6,r3@physicaladdressspacer6也变成了对应的物理地址

1:

ldrr3,[r5,#MACHINFO_TYPE]@getmachinetype

teqr3,r1@matchesloadernumber?

和内核传进的比较

beq2f@found匹配了那么就返回head.S

addr5,r5,#SIZEOF_MACHINE_DESC@nextmachine_desc

cmpr5,r6@比较看看是不是最后一个机器ID

blo1b

movr5,#0@unknownmachine

2:

movpc,lr

ENDPROC(__lookup_machine_type)

#ifdefined(CONFIG_SMP)

ENTRY(secondary_startup)

/*

*CommonentrypointforsecondaryCPUs.

*

*Ensurethatwe'reinSVCmode,andIRQsaredisabled.Lookup

*theprocessortype-thereisnoneedtocheckthemachinetype

*asithasalreadybeenvalidatedbytheprimaryprocessor.

*/

msrcpsr_c,#PSR_F_BIT|PSR_I_BIT|SVC_MODE

mrcp15,0,r9,c0,c0@getprocessorid

bl__lookup_processor_type

movsr10,r5@invalidprocessor?

moveqr0,#'p'@yes,error'p'

beq__error

/*

*Usethepagetablessuppliedfrom__cpu_up.

*/

adrr4,__secondary_data

ldmiar4,{r5,r7,r13}@addresstojumptoafter

subr4,r4,r5@mmuhasbeenenabled

ldrr4,[r7,r4]@getsecondary_data.pgdir

adrlr,__enable_mmu@returnaddress

addpc,r10,#PROCINFO_INITFUNC@initialiseprocessor

@(returncontrolreg)

ENDPROC(secondary_startup)

/*

*r6=&secondary_data

*/

ENTRY(__secondary_switched)

ldrsp,[r7,#4]@getsecondary_data.stack

movfp,#0

bsecondary_start_kernel

ENDPROC(__secondary_switched)

.type__secondary_data,%object

__secondary_data:

.long.

.longsecondary_data

.long__secondary_switched

#endif/*defined(CONFIG_SMP)*/

/*

*SetupcommonbitsbeforefinallyenablingtheMMU.Essentially

*thisisjustloadingthepagetablepointeranddomainaccess

*registers.

*/

__enable_mmu:

#ifdefCONFIG_ALIGNMENT_TRAP

orrr0,r0,#CR_A/*使能地址对齐检查功能*/

#else

bicr0,r0,#CR_A/*禁止地址对齐检查功能*/

#endif

#ifdefCONFIG_CPU_DCACHE_DISABLE

bicr0,r0,#CR_C/*禁止数据的cache*/

#endif

#ifdefCONFIG_CPU_BPREDICT_DISABLE

bicr0,r0,#CR_Z

#endif

#ifdefCONFIG_CPU_ICACHE_DISABLE

bicr0,r0,#CR_I/*禁止指令的cache*/

#endif

movr5,#(domain_val(DOMAIN_USER,DOMAIN_MANAGER)|\

domain_val(DOMAIN_KERNEL,DOMAIN_MANAGER)|\

domain_val(DOMAIN_TABLE,DOMAIN_MANAGER)|\

domain_val(DOMAIN_IO,DOMAIN_CLIENT))

mcrp15,0,r5,c3,c0,0@loaddomainaccessregister把内核控制域存入cp15的寄存器c3中

mcrp15,0,r4,c2,c0,0@loadpagetablepointer把页表基址存入cp15的寄存器c2中

b__turn_mmu_on

ENDPROC(__enable_mmu)

/*

*EnabletheMMU.Thiscompletelychangesthestructureofthevisible

*memoryspace.Youwillnotbeabletotraceexecutionthroughthis.

*Ifyouhaveanenquiryaboutthis,*please*checkthelinux-arm-kernel

*mailinglistarchivesBEFOREsendinganotherposttothelist.

*

*r0=cp#15controlregister

*r13=*virtual*addresstojumptouponcompletion

*

*otherregistersdependonthefunctioncalleduponcompletion

*/

.align5/*32k对齐*/

__turn_mmu_on:

movr0,r0

mcrp15,0,r0,c1,c0,0@writecontrolreg

mrcp15,0,r3,c0,c0,0@readidreg

movr3,r3

movr3,r3/*为什么这里有两个nop,因为打开mmu操作之后要经过三个cycle之后才生效,这和arm的流水线有关*/

movpc,r13

ENDPROC(__turn_mmu_on)

/*

*Setuptheinitialpagetables.Weonlysetupthebarest

*amountwhicharerequiredtogetthekernelrunning,which

*generallymeansmappinginthekernelcode.

*

*r8=machinfo

*r9=cpuid

*r10=procinfo

*

*Returns:

*r0,r3,r6,r7corrupted

*r4=physicalpagetableaddress

*/

__create_page_tables:

pgtblr4@pagetableaddress

/*

*Clearthe16Klevel1swapper(交易者)pagetable

*/

movr0,r4

movr3,#0

addr6,r0,#0x4000@页表的结束地址

1:

strr3,[r0],#4

strr3,[r0],#4

strr3,[r0],#4

strr3,[r0],#4

teqr0,r6

bne1b@清空整个16k的页表

ldrr7,[r10,#PROCINFO_MM_MMUFLAGS]@mm_mmuflags

/*

*DEFINE(PROCINFO_MM_MMUFLAGS,offsetof(structproc_info_list,*__cpu_mm_mmu_flags));defineinarch\arm\kernel

*/

/*

*CreateidentitymappingforfirstMBofkernelto

*cater(满足)fortheMMUenable.Thisidentitymapping

*willberemovedbypaging_init().Weuseourcurrentprogram

*countertodeterminecorresponding(相应的)sectionbaseaddress.

*/

movr6,pc,lsr#20@startofkernelsection此时mmu还没有开启,所以pc为物理地址

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

strr3,[r4,r6,lsl#2]@identitymapping填到对应的页表中区,lsl#2是因为一个页表占4bit

/*

*Nowsetupthepagetablesforourkerneldirect

*mappedregion.(地区,范围)

*/

addr0,r4,#(KERNEL_START&0xff000000)>>18

strr3,[r0,#(KERNEL_START&0x00f00000)>>18]!

ldrr6,=(KERNEL_END-1)/*内核结束地址(虚拟地址)*/

addr0,r0,#4

addr6,r4,r6,lsr#18

1:

cmpr0,r6

addr3,r3,#1<<20

strlsr3,[r0],#4

bls1b

#ifdefCONFIG_XIP_KERNEL

/*

*Mapsomeramtocoverour.dataand.bssareas.

*/

orrr3,r7,#(KERNEL_RAM_PADDR&0xff000000)

.if(KERNEL_RAM_PADDR&0x00f00000)

orrr3,r3,#(KERNEL_RAM_PADDR&0x00f00000)

.endif

addr0,r4,#(KERNEL_RAM_VADDR&0xff000000)>>18

strr3,[r0,#(KERNEL_RAM_VADDR&0x00f00000)>>18]!

ldrr6,=(_end-1)

addr0,r0,#4

addr6,r4,r6,lsr#18

1:

cmpr0,r6

addr3,r3,#1<<20

strlsr3,[r0],#4

bls1b

#endif

/*

*Thenmapfirst1MBofr

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2