1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
| #include <asm.h> #include <arch/arm/cores.h> #include <arch/arm/mmu.h> #include <kernel/vm.h>
.section ".text.boot" .globl _start // 声明全局符号_start _start: b platform_reset b arm_undefined b arm_syscall b arm_prefetch_abort b arm_data_abort b arm_reserved b arm_irq b arm_fiq #if WITH_SMP b arm_reset #endif
.weak platform_reset platform_reset: /* Fall through for the weak symbol */
.globl arm_reset arm_reset: /* do some early cpu setup */ mrc p15, 0, r12, c1, c0, 0 /* i/d cache disable, mmu disabled */ bic r12, #(1<<12) bic r12, #(1<<2 | 1<<0) #if WITH_KERNEL_VM /* enable caches so atomics and spinlocks work */ orr r12, r12, #(1<<12) orr r12, r12, #(1<<2) #endif // WITH_KERNEL_VM mcr p15, 0, r12, c1, c0, 0
/* calculate the physical offset from our eventual virtual location */ .Lphys_offset: ldr r4, =.Lphys_offset adr r11, .Lphys_offset sub r11, r11, r4
#if WITH_SMP /* figure out our cpu number */ mrc p15, 0, r12, c0, c0, 5 /* read MPIDR */
/* mask off the bottom bits to test cluster number:cpu number */ ubfx r12, r12, #0, #SMP_CPU_ID_BITS
/* if we're not cpu 0:0, fall into a trap and wait */ teq r12, #0 movne r0, r12 bne arm_secondary_setup #endif // WITH_SMP
#if WITH_CPU_EARLY_INIT /* call platform/arch/etc specific init code */ bl __cpu_early_init #endif // WITH_CPU_EARLY_INIT
#if WITH_NO_PHYS_RELOCATION /* assume that image is properly loaded in physical memory */ #else /* see if we need to relocate to our proper location in physical memory */ adr r4, _start /* this emits sub r4, pc, #constant */ ldr r5, =(MEMBASE + KERNEL_LOAD_OFFSET) /* calculate the binary's physical load address */ subs r12, r4, r5 /* calculate the delta between where we're loaded and the proper spot */ beq .Lrelocate_done
/* we need to relocate ourselves to the proper spot */ ldr r6, =__data_end ldr r7, =(KERNEL_BASE - MEMBASE) sub r6, r7 add r6, r12
.Lrelocate_loop: // 进行循环拷贝,将代码段拷贝到代码地址处 ldr r7, [r4], #4 str r7, [r5], #4 cmp r4, r6 // 判断拷贝是否完成 bne .Lrelocate_loop
/* we're relocated, jump to the right address */ sub pc, r12 nop /* skipped in the add to pc */
/* recalculate the physical offset */ sub r11, r11, r12
.Lrelocate_done: #endif // !WITH_NO_PHYS_RELOCATION
#if ARM_WITH_MMU .Lsetup_mmu:
/* set up the mmu according to mmu_initial_mappings */
/* load the base of the translation table and clear the table */ ldr r4, =arm_kernel_translation_table add r4, r4, r11 /* r4 = physical address of translation table */
mov r5, #0 mov r6, #0
/* walk through all the entries in the translation table, setting them up */ 0: str r5, [r4, r6, lsl #2] add r6, #1 cmp r6, #4096 bne 0b
/* load the address of the mmu_initial_mappings table and start processing */ ldr r5, =mmu_initial_mappings add r5, r5, r11 /* r5 = physical address of mmu initial mapping table */
.Linitial_mapping_loop: ldmia r5!, { r6-r10 } /* r6 = phys, r7 = virt, r8 = size, r9 = flags, r10 = name */
/* round size up to 1MB alignment */ ubfx r10, r6, #0, #20 add r8, r8, r10 add r8, r8, #(1 << 20) sub r8, r8, #1
/* mask all the addresses and sizes to 1MB boundaries */ lsr r6, #20 /* r6 = physical address / 1MB */ lsr r7, #20 /* r7 = virtual address / 1MB */ lsr r8, #20 /* r8 = size in 1MB chunks */
/* if size == 0, end of list */ cmp r8, #0 beq .Linitial_mapping_done
/* set up the flags */ ldr r10, =MMU_KERNEL_L1_PTE_FLAGS teq r9, #MMU_INITIAL_MAPPING_FLAG_UNCACHED ldreq r10, =MMU_INITIAL_MAP_STRONGLY_ORDERED beq 0f teq r9, #MMU_INITIAL_MAPPING_FLAG_DEVICE ldreq r10, =MMU_INITIAL_MAP_DEVICE /* r10 = mmu entry flags */
0: orr r12, r10, r6, lsl #20 /* r12 = phys addr | flags */
/* store into appropriate translation table entry */ str r12, [r4, r7, lsl #2]
/* loop until we're done */ add r6, #1 add r7, #1 subs r8, #1 bne 0b
b .Linitial_mapping_loop
.Linitial_mapping_done:
#if MMU_WITH_TRAMPOLINE /* move arm_kernel_translation_table address to r8 and * set cacheable attributes on translation walk */ orr r8, r4, #MMU_TTBRx_FLAGS
/* Prepare tt_trampoline page table */ /* Calculate pagetable physical addresses */ ldr r4, =tt_trampoline /* r4 = tt_trampoline vaddr */ add r4, r4, r11 /* r4 = tt_trampoline paddr */
/* Zero tt_trampoline translation tables */ mov r6, #0 mov r7, #0 1: str r7, [r4, r6, lsl#2] add r6, #1 cmp r6, #0x1000 blt 1b
/* Setup 1M section mapping at * phys -> phys and * virt -> phys */ lsr r6, pc, #20 /* r6 = paddr index */ ldr r7, =MMU_KERNEL_L1_PTE_FLAGS add r7, r7, r6, lsl #20 /* r7 = pt entry */
str r7, [r4, r6, lsl #2] /* tt_trampoline[paddr index] = pt entry */
rsb r6, r11, r6, lsl #20 /* r6 = vaddr */ str r7, [r4, r6, lsr #(20 - 2)] /* tt_trampoline[vaddr index] = pt entry */ #endif // MMU_WITH_TRAMPOLINE
/* set up the mmu */ bl .Lmmu_setup #endif // WITH_KERNEL_VM
/* at this point we're running at our final location in virtual memory (if enabled) */ .Lstack_setup: /* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */ mov r12, #0
cpsid i,#0x12 /* irq */ mov sp, r12
cpsid i,#0x11 /* fiq */ mov sp, r12
cpsid i,#0x17 /* abort */ mov sp, r12
cpsid i,#0x1b /* undefined */ mov sp, r12
cpsid i,#0x1f /* system */ mov sp, r12
cpsid i,#0x13 /* supervisor */ ldr r12, =abort_stack add r12, #ARCH_DEFAULT_STACK_SIZE mov sp, r12
/* stay in supervisor mode from now on out */
/* copy the initialized data segment out of rom if necessary */ ldr r4, =__data_start_rom ldr r5, =__data_start ldr r6, =__data_end
cmp r4, r5 beq .L__do_bss
.L__copy_loop: cmp r5, r6 ldrlt r7, [r4], #4 strlt r7, [r5], #4 blt .L__copy_loop
.L__do_bss: #if FOR_VERIFICATION_DONT_CLEAR_BSS == 0 /* clear out the bss */ ldr r4, =__bss_start ldr r5, =_end mov r6, #0 .L__bss_loop: cmp r4, r5 strlt r6, [r4], #4 blt .L__bss_loop #endif #if FOR_VERIFICATION == 1 mov r0, #0 mov r1, #0 mov r2, #0 mov r3, #0 #endif bl lk_main b .
|