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

 

posted on 2013-08-19 21:40  choi87  阅读(822)  评论(0)    收藏  举报