在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。
由于内核启动流程(二)和(三)的铺垫,本篇的代码分析起来就轻松多了,随着对Linux学习的深入,必然会融会贯通。所以,掌握Linux背后的逻辑和思想,然后举一反三才是我们最需要锻炼的能力。
5 __lookup_machine_type剖析(接上篇)
__lookup_machine_type函数和__lookup_processor_type函数设计和实现的思路是一样的,在之前的文章中已经深入分析过,在这里不做重复性工作了。仅对代码作出注释。
/*
* Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
* more information about the __proc_info and __arch_info structures.
*/
.long __proc_info_begin
.long __proc_info_end
3: .long .
.long __arch_info_begin
.long __arch_info_end
/*
* Lookup machine architecture in the linker-build list of architectures.
* Note that we can't use the absolute addresses for the __arch_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.
*
* r1 = machine architecture number
* Returns:
* r3, r4, r6 corrupted
* r5 = mach_info pointer in physical address space
*/
.type __lookup_machine_type, %function
__lookup_machine_type:
adr r3, 3b @ adr伪指令将标号3的物理地址(实际存在的地址)赋值给r3寄存器
ldmia r3, {r4, r5, r6} @ ldmia多寄存器寻址指令等价于: r4 <- [r3] = "."(.代表该行代码的虚拟地址)
@ r5 <- [r3+4] = __arch_info_begin(虚拟地址), r6 <- [r3+4*2]
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type,寄存器相对寻址,MACHINFO_TYPE为type在结构体arch_info中的偏移
teq r3, r1 @ matches loader number? 判断r3中的值是否与r1中的值相等
beq 2f @ found 如果相等就跳转到标号2处,此时r5指向的就是匹配的arch_info结构体
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc 否则,r5指针向前跳一个arch_info结构体的大小
cmp r5, r6 @ 检查r5此时是否已经指向__arch_info_end处
blo 1b @ r5 小于 r6时跳转到标号1处
mov r5, #0 @ unknown machine 否则给r5清零,并退出循环
2: mov pc, lr @ 函数返回
6 lookup_machine_type剖析
lookup_machine_type函数和lookup_processor_type函数设计和实现的思路是一样的,在之前的文章中已经深入分析过,在这里不做重复性工作了。仅对代码作出注释。
/*
* This provides a C-API version of the above function.
*/
ENTRY(lookup_machine_type)
stmfd sp!, {r4 - r6, lr} @ 压栈,保护现场
mov r1, r0 @ 将入参(r0)赋值给r1
bl __lookup_machine_type @ 调用汇编函数
mov r0, r5 @ 将结果(r5)赋值给返回值(r0)
ldmfd sp!, {r4 - r6, pc} @ 弹栈,恢复现场,并进行函数返回
<完>