1 /* 2 * Kernel startup entry point. 3 * --------------------------- 4 * 5 * This is normally called from the decompressor code. The requirements 6 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, 7 * r1 = machine nr, r2 = atags or dtb pointer. 8 * 9 * This code is mostly position independent, so if you link the kernel at 10 * 0xc0008000, you call this at __pa(0xc0008000). 11 * 12 * See linux/arch/arm/tools/mach-types for the complete list of machine 13 * numbers for r1. 14 * 15 * We're trying to keep crap to a minimum; DO NOT add any machine specific 16 * crap here - that's what the boot loader (or in extreme, well justified 17 * circumstances, zImage) is for. 18 */ 19 .arm 20 21 __HEAD 22 ENTRY(stext) 23 24 THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. 25 THUMB( bx r9 ) @ If this is a Thumb-2 kernel, 26 THUMB( .thumb ) @ switch to Thumb now. 27 THUMB( 1: ) 28 29 #ifdef CONFIG_ARM_VIRT_EXT /* unlikely */ 30 bl __hyp_stub_install 31 #endif 32 @ 进入svc模式,并mask掉所有中断 33 safe_svcmode_maskall r9 34 @\ 35 @====================================================== 36 @.macro safe_svcmode_maskall reg:req 37 @ mrs \reg , cpsr 38 @ eor \reg, \reg, #HYP_MODE @ mode==HYP_MODE? reg=0: reg=!0 (HYP_MODE=0x1a) 39 @ tst \reg, #MODE_MASK @ reg==0? Z=1: Z=0 (MODE_MASK=0x1f) 40 @ bic \reg , \reg , #MODE_MASK @ 清除模式位r9[4:0] 41 @ orr \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ 关闭IRQ,FIQ,处理器设为SVC_MODE 42 @ THUMB( orr \reg , \reg , #PSR_T_BIT ) @ 如果支持Thumb指令,设置T位 43 @ bne 1f @ 大多cpu上电后非HYP_MODE,所以一般都是在这里进行跳转 44 @ orr \reg, \reg, #PSR_A_BIT @ 以下几行代码有待解析,暂时用不到 45 @ adr lr, BSYM(2f) 46 @ msr spsr_cxsf, \reg 47 @ __MSR_ELR_HYP(14) 48 @ __ERET 49 @1: msr cpsr_c, \reg @ 把修改好的值写入cpsr_c(cpsr[7:0]) 50 @2: 51 @.endm 52 @====================================================== 53 mrc p15, 0, r9, c0, c0 @ OUT r9=processor id 54 bl __lookup_processor_type @ OUT r5=procinfo IN r9=processor id 55 @\ 56 @====================================================== 57 @__lookup_processor_type: @ 注意:(phys)表示是物理地址, (virt)表示线性地址 58 @ adr r3, __lookup_processor_type_data @ r3=(phys)__lookup_processor_type_data 59 @ ldmia r3, {r4 - r6} @ r4=(virt). r5=(virt)__proc_info_begin r6=(virt)__proc_info_end 60 @ sub r3, r3, r4 @ r3=(phys)r3-(virt)r4 (接下来两行把virt转换成phys的时候使用) 61 @ add r5, r5, r3 @ (phys)r5=(virt)r5+r3 62 @ add r6, r6, r3 @ (phys)r6=(virt)r6+r3 63 @1: ldmia r5, {r3, r4} @ r3=value r4=mask (参考struct proc_info_list) 64 @ and r4, r4, r9 @ 对processor id进行mask 65 @ teq r3, r4 @ 把mask后的processor id与value进行比较 66 @ beq 2f @ 如果一致,匹配成功,如果不匹配继续搜索(请参考proc-*.S) 67 @ add r5, r5, #PROC_INFO_SZ @ r5往后偏移sizeof(struct proc_info_list) 68 @ cmp r5, r6 @ r6是存放proc_info_list的末尾 69 @ blo 1b 70 @ mov r5, #0 @ 如果没有匹配成功结果是unknown processor(r5=0) 71 @2: mov pc, lr @ 正常情况都能匹配到,并返回找到的procinfo的首地址 72 @ENDPROC(__lookup_processor_type) 73 @ 74 @ .align 2 75 @ .type __lookup_processor_type_data, %object 76 @__lookup_processor_type_data: 77 @ .long . @ r4 78 @ .long __proc_info_begin @ r5 79 @ .long __proc_info_end @ r6 80 @ .size __lookup_processor_type_data, . - __lookup_processor_type_data 81 @====================================================== 82 movs r10, r5 @ invalid processor (r5=0)? 83 THUMB( it eq ) @ force fixup-able long branch encoding 84 beq __error_p @ yes, error 'p' 85 86 #ifdef CONFIG_ARM_LPAE 87 mrc p15, 0, r3, c0, c1, 4 88 and r3, r3, #0xf 89 cmp r3, #5 90 THUMB( it lo ) 91 blo __error_p 92 #endif 93 94 #ifndef CONFIG_XIP_KERNEL 95 adr r3, 2f 96 ldmia r3, {r4, r8} 97 sub r4, r3, r4 98 add r8, r8, r4 99 #else 100 ldr r8, =PHYS_OFFSET @ r8=RAM开头的物理地址 101 #endif 102 103 /* 104 * r1 = machine no, r2 = atags or dtb, 105 * r8 = phys_offset, r9 = cpuid, r10 = procinfo 106 */ 107 bl __vet_atags @检查第一个atag 108 @\ 109 @====================================================== 110 @__vet_atags: 111 @ tst r2, #0x3 @ 检查是否4个字节对齐 112 @ bne 1f @ 如果不对齐跳转至下一个1: 出错返回 113 @ 114 @ ldr r5, [r2, #0] @ 从atags所在的内存中读取4个字节到r5中 115 @#ifdef CONFIG_OF_FLATTREE 116 @ ldr r6, =OF_DT_MAGIC 117 @ cmp r5, r6 118 @ beq 2f 119 @#endif 120 @ cmp r5, #ATAG_CORE_SIZE @ r5和5比较 (bootloader会把ATAG_CORE放在最前面) 121 @ cmpne r5, #ATAG_CORE_SIZE_EMPTY @ r5和2比较 122 @ bne 1f @ 以上两个条件都不满足,跳转至下一个1: 出错返回 123 @ ldr r5, [r2, #4] @ 读取下4个字节到r5中 124 @ ldr r6, =ATAG_CORE @ r6=0x54410001 125 @ cmp r5, r6 @ 比较r5和r6 126 @ bne 1f @ 如果不等于,跳转至下一个1:出错返回 127 @ 128 @2: mov pc, lr @ 成功返回 129 @ 130 @1: mov r2, #0 131 @ mov pc, lr @ 出错返回 132 @ENDPROC(__vet_atags) 133 @====================================================== 134 #ifdef CONFIG_SMP_ON_UP 135 bl __fixup_smp 136 #endif 137 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT 138 bl __fixup_pv_table 139 #endif 140 bl __create_page_tables @ 设置初始页目录表,具体内容请参考"1.1_create_page_tables" 141 142 /* 143 * The following calls CPU specific code in a position independent 144 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of 145 * xxx_proc_info structure selected by __lookup_processor_type 146 * above. On return, the CPU will be ready for the MMU to be 147 * turned on, and r0 will hold the CPU control register value. 148 */ 149 ldr r13, =__mmap_switched @ 请注意这行代码,待会跳转到r13处 150 151 adr lr, BSYM(1f) @ lr中放置往下数五行"1: b __enable_mmu"这条指令的地址 152 mov r8, r4 @ set TTBR1 to swapper_pg_dir 153 ARM( add pc, r10, #PROCINFO_INITFUNC ) @ 注意这段代码,r10是__lookup_processor_type里找到的procinfo的首地址 154 @ PROCINFO_INITFUNC=16 根据vmlinux.lds.S文件能够发现 这些procinfo是在proc-*.S在中填充的 155 @ proc-v7.S的话proc type多,而且还用了宏。所以举个proc-v6.S的例子,这个看起来一目了然 156 @\ 157 @====================================================== 158 @ .type __v6_proc_info, #object 159 @__v6_proc_info: 160 @ .long 0x0007b000 @ 匹配成功后r10指向这里 161 @ .long 0x0007f000 162 @ ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_FLAGS_SMP) 163 @ ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_FLAGS_UP) 164 @ .long PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ 165 @ b __v6_setup @ ALT_SMP和ALT_UP这个宏只会同时有一个有效,所以pc指这里 166 @ @ 具体内容请参考"1.2 __v6_setup" 167 @ .long cpu_arch_name 168 @ .long cpu_elf_name 169 @====================================================== 170 171 THUMB( add r12, r10, #PROCINFO_INITFUNC ) 172 THUMB( mov pc, r12 ) 173 1: b __enable_mmu @ enable mmu,具体内容请参考"1.3 __enable_mmu" 174 ENDPROC(stext) 175 .ltorg 176 #ifndef CONFIG_XIP_KERNEL 177 2: .long . 178 .long PAGE_OFFSET 179 #endif
浙公网安备 33010602011771号