您的位置:首页 > 其它

kernel/head.S

2015-12-03 14:58 344 查看
1.初始化指向--stext标签

通过引导加载项加载内核以后,首先执行的部分就是stext。执行该标签时要如下状态:

MMU = off

D-Cache = off

r0 = 0

r1 = machime number

r2 = atags pointer

在stext标签中,首先转换为SVC模式,并禁用IRQ。然后调用调用多个检查程序,查找CPU和机器信息,并检查atag信息,追加设置页表,启动MMU。

arch/arm/kernel/head.S

ENTRY(stext)

ARM_BE8(setend be )@ ensure we are in BE8 mode

THUMB( adr
r9, BSYM(1f) )@ Kernel is always entered in ARM.

THUMB( bx
r9 ) @ If this is a Thumb-2 kernel,

THUMB( .thumb)@ switch to Thumb now.

THUMB(1: )

#ifdef CONFIG_ARM_VIRT_EXT

bl __hyp_stub_install

#endif

@ ensure svc mode and all interrupts masked

safe_svcmode_maskall r9 =>转换为SVC模式,并禁用IRQ

mrc p15, 0, r9, c0, c0@ get processor id =>获取CPU ID 并和__lookup_processor_type做比较 r5 = procinfo地址

bl __lookup_processor_type @ r5=procinfo r9=cpuid

movs r10, r5@ invalid processor (r5=0)?

THUMB( it eq )@ force fixup-able long branch encoding

beq __error_p@ yes, error 'p'

... ...

/*

* r1 = machine no, r2 = atags or dtb,

* r8 = phys_offset, r9 = cpuid, r10 = procinfo

*/

bl __vet_atags

#ifdef CONFIG_SMP_ON_UP

bl __fixup_smp

#endif

#ifdef CONFIG_ARM_PATCH_PHYS_VIRT

bl __fixup_pv_table

#endif

bl __create_page_tables

ldr
r13, =__mmap_switched @ address to jump to after =>将switch data放在r13中。 Lr(r14)中保存了__enable_mmu的地址,执行PROCINFO_INITFUNC后通 过lr 寄存器中的__enable_mmu执行返回,从而激活MMU

@ mmu has been enabled

adr lr, BSYM(1f)@ return (PIC) address

mov r8, r4@ set TTBR1 to swapper_pg_dir

ARM( add
pc, r10, #PROCINFO_INITFUNC )
=>r10中存储了通过__lookup_processor_type获得的proc_info_list结构体的起始地址。该值加上PROCINFO_INITFUNC即可调用__v6_setup子程序。通过arch/arm/kernel/asm-offset.c执行编译时生成的include/asm-offset.h中。PROCINFO_INITFUNC的定义如下:

DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));含义:在struct proc_info_list结构体中,将__cpu_flush成员变量所在偏移量指定为PROCINFO_INITFUNC的值,DEFINE的定义见:http://blog.csdn.net/lory17/article/details/50160947。

THUMB( addr12, r10, #PROCINFO_INITFUNC)

THUMB( ret
r12 )

1: b __enable_mmu

ENDPROC(stext)

__look_processor_type标签:

位置:arch/arm/kernel/head-common.S文件。记录了内核中求处理器类型的代码。

bl __lookup_processor_type
@ r5=procinfo r9=cpuid


ENTRY(lookup_processor_type)

stmfd sp!, {r4 - r6, r9, lr}

mov r9, r0

bl __lookup_processor_type

mov r0, r5

ldmfd sp!, {r4 - r6, r9, pc}

ENDPROC(lookup_processor_type) =>C代码中调用lookup_processor_type()函数使用。利用stmfd指令在战中备份寄存器值,将r0(CPU ID)参数传递保存在r9中。执行__lookup_processor_type后,将结果值(r5)保存在返回值的寄存器(r0)中。最后还原栈并返回。

__FINIT

.text

/*

* Read processor ID register (CP#15, CR0), and look up in the linker-built

* supported processor list. Note that we can't use the absolute addresses

* for the __proc_info lists since we aren't running with the MMU on

* (and therefore, we are not in the correct address space). We have to

* calculate the offset.

*

* r9 = cpuid

* Returns:

* r3, r4, r6 corrupted

* r5 = proc_info pointer in physical address space

* r9 = cpuid (preserved)

*/

__lookup_processor_type:

adr r3, __lookup_processor_type_data

ldmia r3, {r4 - r6} =>
r3 <- __lokkup_processor_type_data /*物理地址*/

r5 <- __proc_info_begin /*虚拟地址*/

r6<- __proc_info_end /*虚拟地址*/

sub r3, r3, r4
@ get offset between virt&phys

add r5, r5, r3
@ convert virt addresses to

add r6, r6, r3
@ physical address space =>计算偏倚,将 r5 r6 __proc_info_begin __proc_info_end 虚拟地址转换成物理地址,因为mmu没有激活,无法使用虚拟地址。

1: ldmia
r5, {r3, r4} @ value, mask

and r4, r4, r9
@ mask wanted bits

teq r3, r4

beq 2f

add r5, r5, #PROC_INFO_SZ
@ sizeof(proc_info_list) => __proc_info_begin __proc_info_end之间保存内核的所有处理器信息。

cmp r5, r6

blo 1b

mov r5, #0
@ unknown processor

2: ret
lr

ENDPROC(__lookup_processor_type) => ENDPROC()定义在 include/linux/linkage.h,将__lookup_processor_type标签作为函数注册到符号列表,使其能够从外部调用。

/*

* Look in <asm/procinfo.h> for information about the __proc_info structure.

*/

.align
2

.type __lookup_processor_type_data, %object

__lookup_processor_type_data:

.long .

.long __proc_info_begin

.long __proc_info_end

.size __lookup_processor_type_data, . - __lookup_processor_type_data
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: