1. 确认 processor type
arch/arm/kernel/head.S中:
00075: mrcp15, 0, r9, c0, c0@ get processor id
00076: bl__lookup_processor_type@ r5=procinfo r9=cpuid
00077: movsr10, r5@ invalid processor (r5=0)?
00078: beq__error_p@ yes, error p
75行: 经过cp15协处理器的c0寄存器来取得processor id的指令. 关于cp15的具体内容可参阅相关的arm手册
76行: 跳转到__lookup_processor_type.在__lookup_processor_type中,会把processor type 存储在r5中
77,78行: 判别r5中的processor type是否是0,假如是0,阐明是无效的processor type,跳转到__error_p(犯错)
__lookup_processor_type 函数主要是依据从cpu中取得的processor id和体系中的proc_info进行匹配,将匹配到的proc_info_list的基地址存到r5中, 0标明没有找到对应的processor type.
下面咱们剖析__lookup_processor_type函数
arch/arm/kernel/head-common.S中:
00145: .type__lookup_processor_type, %function
00146: __lookup_processor_type:
00147: adrr3, 3f
00148: ldmdar3, {r5 – r7}
00149: subr3, r3, r7@ get offset between virt&phys
00150: addr5, r5, r3@ convert virt addresses to
00151: addr6, r6, r3@ physical address space
00152: 1:ldmiar5, {r3, r4}@ value, mask
00153: andr4, r4, r9@ mask wanted bits
00154: teqr3, r4
00155: beq2f
00156: addr5, r5, #PROC_INFO_SZ@ sizeof(proc_info_list)
00157: cmpr5, r6
00158: blo1b
00159: movr5, #0@ unknown processor
00160: 2:movpc, lr
00161:
00162:
00165: ENTRY(lookup_processor_type)
00166: stmfdsp!, {r4 – r7, r9, lr}
00167: movr9, r0
00168: bl__lookup_processor_type
00169: movr0, r5
00170: ldmfdsp!, {r4 – r7, r9, pc}
00171:
00172:
00176: .long__proc_info_begin
00177: .long__proc_info_end
00178: 3:.long.
00179: .long__arch_info_begin
00180: .long__arch_info_end
145, 146行是函数界说
147行: 取地址指令,这儿的3f是向前symbol名称是3的方位,即第178行,将该地址存入r3.
这儿需求留意的是,adr指令取址,取得的是根据pc的一个地址,要分外留意,这个地址是3f处的”运转时地址”,由于此刻MMU还没有翻开,也能够了解成物理地址(实地址).(具体内容可参阅arm指令手册)
148行: 由于r3中的地址是178行的方位的地址,因此履行完后:
r5存的是176行符号 __proc_info_begin的地址;
r6存的是177行符号 __proc_info_end的地址;
r7存的是3f处的地址.
这儿需求留意链接地址和运转时地址的差异. r3存储的是运转时地址(物理地址),而r7中存储的是链接地址(虚拟地址).
__proc_info_begin和__proc_info_end是在arch/arm/kernel/vmlinux.lds.S中:
00031:__proc_info_begin = .;
00032:*(.proc.info.init)
00033:__proc_info_end = .;
这儿是声明晰两个变量:__proc_info_begin 和 __proc_info_end,其间等号后边的”.”是location counter(具体内容请参阅ld.info)
这三行的意思是: __proc_info_begin 的方位上,放置一切文件中的 “.proc.info.init” 段的内容,然后紧接着是 __proc_info_end 的方位.
kernel 运用struct proc_info_list来描绘processor type.
在 include/asm-arm/procinfo.h 中:
00029: struct proc_info_list {
00030: unsigned intcpu_val;
00031: unsigned intcpu_mask;
00032: unsigned long__cpu_mm_mmu_flags;
00033: unsigned long__cpu_io_mmu_flags;
00034: unsigned long__cpu_flush;
00035: const char*arch_name;
00036: const char*elf_name;
00037: unsigned intelf_hwcap;
00038: const char*cpu_name;
00039: struct processor*proc;
00040: struct cpu_tlb_fns*tlb;
00041: struct cpu_user_fns*user;
00042: struct cpu_cache_fns*cache;
00043: };
咱们当时以at91为例,其processor是926的.
在arch/arm/mm/proc-arm926.S 中:
00464: .section “.proc.info.init”, #alloc, #execinstr
00465:
00466: .type__arm926_proc_info,#object
00467: __arm926_proc_info:
00468: .long0x41069260@ ARM926EJ-S (v5TEJ)
00469: .long0xff0ffff0
00470: .long PMD_TYPE_SECT | \
00471: PMD_SECT_BUFFERABLE | \
00472: PMD_SECT_CACHEABLE | \
00473: PMD_BIT4 | \
00474: PMD_SECT_AP_WRITE | \
00475: PMD_SECT_AP_READ
00476: .long PMD_TYPE_SECT | \
00477: PMD_BIT4 | \
00478: PMD_SECT_AP_WRITE | \
00479: PMD_SECT_AP_READ
00480: b__arm926_setup
00481: .longcpu_arch_name
00482: .longcpu_elf_name
00483: .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
00484: .longcpu_arm926_name
00485: .longarm926_processor_functions
00486: .longv4wbi_tlb_fns
00487: .longv4wb_user_fns
00488: .longarm926_cache_fns
00489: .size__arm926_proc_info, . – __arm926_proc_info
从464行,咱们能够看到 __arm926_proc_info 被放到了”.proc.info.init”段中.
对照struct proc_info_list,咱们能够看到 __cpu_flush的界说是在480行,即__arm926_setup.(咱们将在”4. 调用渠道特定的__cpu_flush函数”一节中具体剖析这部分的内容.)
从以上的内容咱们能够看出: r5中的__proc_info_begin是proc_info_list的开始地址, r6中的__proc_info_end是proc_info_list的完毕地址.
149行: 从上面的剖析咱们能够知道r3中存储的是3f处的物理地址,而r7存储的是3f处的虚拟地址,这一行是核算当时程序运转的物理地址和虚拟地址的差值,将其保存到r3中.
150行: 将r5存储的虚拟地址(__proc_info_begin)转换成物理地址
151行: 将r6存储的虚拟地址(__proc_info_end)转换成物理地址
152行: 对照struct proc_info_list,能够得知,这句是将当时proc_info的cpu_val和cpu_mask别离存r3, r4中
153行: r9中存储了processor id(arch/arm/kernel/head.S中的75行),与r4的cpu_mask进行逻辑与操作,得到咱们需求的值
154行: 将153行中得到的值与r3中的cpu_val进行比较
155行: 假如持平,阐明咱们找到了对应的processor type,跳到160行,回来
156行: (假如不持平) , 将r5指向下一个proc_info,
157行: 和r6比较,查看是否到了__proc_info_end.
158行: 假如没有到__proc_info_end,标明还有proc_info装备,回来152行持续查找
159行: 履行到这儿,阐明一切的proc_info都匹配过了,可是没有找到匹配的,将r5设置成0(unknown processor)
160行: 回来
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/chanpin/275645.html