三:__lookup_processor_type函数
__lookup_processor_type函数是一个非常讲究技巧的函数,Kernel代码将所有CPU信息的定义都放到.proc.info.init段中,因此可以认为.proc.info.init段就是一个数组,每个元素都定义了一个或一种CPU的信息。目前__lookup_processor_type使用该元素的前两个字段cpuid和mask来匹配当前CPUID,如果满足CPUID & mask == cpuid,则找到当前cpu的定义并返回。
[cpp]
/* * 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) */ __CPUINIT __lookup_processor_type: /* adr 是相对寻址,它的寻计算结果是将当前PC值加上__lookup_processor_type_data符号与PC的偏移量, * 而PC是物理地址,因此r3的结果也是__lookup_processor_type_data符号的物理地址 */ adr r3, __lookup_processor_type_data ldmia r3, {r4 - r6} 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: ldmia r5, {r3, r4} @ value, mask /* 将当前CPUID和mask相与,并与数组元素中的CPUID比较是否相同 * 若相同,则找到当前CPU的__proc_info定义,r5指向访元素并返回。 */ and r4, r4, r9 @ mask wanted bits teq r3, r4 beq 2f /* r5指向下一个__proc_info元素 */ add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) /* 是否遍历完所有__proc_info元素 */ cmp r5, r6 blo 1b /* 找不到则返回NULL */ mov r5, #0 @ unknown processor 2: mov pc, lr ENDPROC(__lookup_processor_type)