Merge branch 'hotplug' into devel

Conflicts:
arch/arm/kernel/head-common.S

+403 -300
+159 -146
arch/arm/kernel/head-common.S
··· 15 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) 16 #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) 17 18 - .align 2 19 - .type __switch_data, %object 20 - __switch_data: 21 - .long __mmap_switched 22 - .long __data_loc @ r4 23 - .long _sdata @ r5 24 - .long __bss_start @ r6 25 - .long _end @ r7 26 - .long processor_id @ r4 27 - .long __machine_arch_type @ r5 28 - .long __atags_pointer @ r6 29 - .long cr_alignment @ r7 30 - .long init_thread_union + THREAD_START_SP @ sp 31 - 32 - /* 33 - * The following fragment of code is executed with the MMU on in MMU mode, 34 - * and uses absolute addresses; this is not position independent. 35 - * 36 - * r0 = cp#15 control register 37 - * r1 = machine ID 38 - * r2 = atags pointer 39 - * r9 = processor ID 40 - */ 41 - __mmap_switched: 42 - adr r3, __switch_data + 4 43 - 44 - ldmia r3!, {r4, r5, r6, r7} 45 - cmp r4, r5 @ Copy data segment if needed 46 - 1: cmpne r5, r6 47 - ldrne fp, [r4], #4 48 - strne fp, [r5], #4 49 - bne 1b 50 - 51 - mov fp, #0 @ Clear BSS (and zero fp) 52 - 1: cmp r6, r7 53 - strcc fp, [r6],#4 54 - bcc 1b 55 - 56 - ARM( ldmia r3, {r4, r5, r6, r7, sp}) 57 - THUMB( ldmia r3, {r4, r5, r6, r7} ) 58 - THUMB( ldr sp, [r3, #16] ) 59 - str r9, [r4] @ Save processor ID 60 - str r1, [r5] @ Save machine type 61 - str r2, [r6] @ Save atags pointer 62 - bic r4, r0, #CR_A @ Clear 'A' bit 63 - stmia r7, {r0, r4} @ Save control register values 64 - b start_kernel 65 - ENDPROC(__mmap_switched) 66 - 67 /* 68 * Exception handling. Something went wrong and we can't proceed. We 69 * ought to tell the user, but since we don't have any guarantee that ··· 24 * and hope for the best (useful if bootloader fails to pass a proper 25 * machine ID for example). 26 */ 27 - __error_p: 28 - #ifdef CONFIG_DEBUG_LL 29 - adr r0, str_p1 30 - bl printascii 31 - mov r0, r9 32 - bl printhex8 33 - adr r0, str_p2 34 - bl printascii 35 - b __error 36 - str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" 37 - str_p2: .asciz ").\n" 38 - .align 39 - #endif 40 - ENDPROC(__error_p) 41 - 42 __error_a: 43 #ifdef CONFIG_DEBUG_LL 44 mov r4, r1 @ preserve machine ID ··· 34 bl printhex8 35 adr r0, str_a2 36 bl printascii 37 - adr r3, 4f 38 ldmia r3, {r4, r5, r6} @ get machine desc list 39 sub r4, r3, r4 @ get offset between virt&phys 40 add r5, r5, r4 @ convert virt addresses to ··· 62 .align 63 #endif 64 65 - __error: 66 - #ifdef CONFIG_ARCH_RPC 67 - /* 68 - * Turn the screen red on a error - RiscPC only. 69 - */ 70 - mov r0, #0x02000000 71 - mov r3, #0x11 72 - orr r3, r3, r3, lsl #8 73 - orr r3, r3, r3, lsl #16 74 - str r3, [r0], #4 75 - str r3, [r0], #4 76 - str r3, [r0], #4 77 - str r3, [r0], #4 78 - #endif 79 - 1: mov r0, r0 80 - b 1b 81 - ENDPROC(__error) 82 - 83 - 84 - /* 85 - * Read processor ID register (CP#15, CR0), and look up in the linker-built 86 - * supported processor list. Note that we can't use the absolute addresses 87 - * for the __proc_info lists since we aren't running with the MMU on 88 - * (and therefore, we are not in the correct address space). We have to 89 - * calculate the offset. 90 - * 91 - * r9 = cpuid 92 - * Returns: 93 - * r3, r4, r6 corrupted 94 - * r5 = proc_info pointer in physical address space 95 - * r9 = cpuid (preserved) 96 - */ 97 - __lookup_processor_type: 98 - adr r3, 3f 99 - ldmia r3, {r5 - r7} 100 - add r3, r3, #8 101 - sub r3, r3, r7 @ get offset between virt&phys 102 - add r5, r5, r3 @ convert virt addresses to 103 - add r6, r6, r3 @ physical address space 104 - 1: ldmia r5, {r3, r4} @ value, mask 105 - and r4, r4, r9 @ mask wanted bits 106 - teq r3, r4 107 - beq 2f 108 - add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) 109 - cmp r5, r6 110 - blo 1b 111 - mov r5, #0 @ unknown processor 112 - 2: mov pc, lr 113 - ENDPROC(__lookup_processor_type) 114 - 115 - /* 116 - * This provides a C-API version of the above function. 117 - */ 118 - ENTRY(lookup_processor_type) 119 - stmfd sp!, {r4 - r7, r9, lr} 120 - mov r9, r0 121 - bl __lookup_processor_type 122 - mov r0, r5 123 - ldmfd sp!, {r4 - r7, r9, pc} 124 - ENDPROC(lookup_processor_type) 125 - 126 - /* 127 - * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for 128 - * more information about the __proc_info and __arch_info structures. 129 - */ 130 - .align 2 131 - 3: .long __proc_info_begin 132 - .long __proc_info_end 133 - 4: .long . 134 - .long __arch_info_begin 135 - .long __arch_info_end 136 - 137 /* 138 * Lookup machine architecture in the linker-build list of architectures. 139 * Note that we can't use the absolute addresses for the __arch_info ··· 74 * r5 = mach_info pointer in physical address space 75 */ 76 __lookup_machine_type: 77 - adr r3, 4b 78 ldmia r3, {r4, r5, r6} 79 sub r3, r3, r4 @ get offset between virt&phys 80 add r5, r5, r3 @ convert virt addresses to ··· 90 ENDPROC(__lookup_machine_type) 91 92 /* 93 - * This provides a C-API version of the above function. 94 */ 95 - ENTRY(lookup_machine_type) 96 - stmfd sp!, {r4 - r6, lr} 97 - mov r1, r0 98 - bl __lookup_machine_type 99 - mov r0, r5 100 - ldmfd sp!, {r4 - r6, pc} 101 - ENDPROC(lookup_machine_type) 102 103 /* Determine validity of the r2 atags pointer. The heuristic requires 104 * that the pointer be aligned, in the first 16k of physical RAM and ··· 131 1: mov r2, #0 132 mov pc, lr 133 ENDPROC(__vet_atags)
··· 15 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) 16 #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) 17 18 /* 19 * Exception handling. Something went wrong and we can't proceed. We 20 * ought to tell the user, but since we don't have any guarantee that ··· 73 * and hope for the best (useful if bootloader fails to pass a proper 74 * machine ID for example). 75 */ 76 + __HEAD 77 __error_a: 78 #ifdef CONFIG_DEBUG_LL 79 mov r4, r1 @ preserve machine ID ··· 97 bl printhex8 98 adr r0, str_a2 99 bl printascii 100 + adr r3, __lookup_machine_type_data 101 ldmia r3, {r4, r5, r6} @ get machine desc list 102 sub r4, r3, r4 @ get offset between virt&phys 103 add r5, r5, r4 @ convert virt addresses to ··· 125 .align 126 #endif 127 128 /* 129 * Lookup machine architecture in the linker-build list of architectures. 130 * Note that we can't use the absolute addresses for the __arch_info ··· 209 * r5 = mach_info pointer in physical address space 210 */ 211 __lookup_machine_type: 212 + adr r3, __lookup_machine_type_data 213 ldmia r3, {r4, r5, r6} 214 sub r3, r3, r4 @ get offset between virt&phys 215 add r5, r5, r3 @ convert virt addresses to ··· 225 ENDPROC(__lookup_machine_type) 226 227 /* 228 + * Look in arch/arm/kernel/arch.[ch] for information about the 229 + * __arch_info structures. 230 */ 231 + .align 2 232 + .type __lookup_machine_type_data, %object 233 + __lookup_machine_type_data: 234 + .long . 235 + .long __arch_info_begin 236 + .long __arch_info_end 237 + .size __lookup_machine_type_data, . - __lookup_machine_type_data 238 239 /* Determine validity of the r2 atags pointer. The heuristic requires 240 * that the pointer be aligned, in the first 16k of physical RAM and ··· 265 1: mov r2, #0 266 mov pc, lr 267 ENDPROC(__vet_atags) 268 + 269 + /* 270 + * The following fragment of code is executed with the MMU on in MMU mode, 271 + * and uses absolute addresses; this is not position independent. 272 + * 273 + * r0 = cp#15 control register 274 + * r1 = machine ID 275 + * r2 = atags pointer 276 + * r9 = processor ID 277 + */ 278 + __INIT 279 + __mmap_switched: 280 + adr r3, __mmap_switched_data 281 + 282 + ldmia r3!, {r4, r5, r6, r7} 283 + cmp r4, r5 @ Copy data segment if needed 284 + 1: cmpne r5, r6 285 + ldrne fp, [r4], #4 286 + strne fp, [r5], #4 287 + bne 1b 288 + 289 + mov fp, #0 @ Clear BSS (and zero fp) 290 + 1: cmp r6, r7 291 + strcc fp, [r6],#4 292 + bcc 1b 293 + 294 + ARM( ldmia r3, {r4, r5, r6, r7, sp}) 295 + THUMB( ldmia r3, {r4, r5, r6, r7} ) 296 + THUMB( ldr sp, [r3, #16] ) 297 + str r9, [r4] @ Save processor ID 298 + str r1, [r5] @ Save machine type 299 + str r2, [r6] @ Save atags pointer 300 + bic r4, r0, #CR_A @ Clear 'A' bit 301 + stmia r7, {r0, r4} @ Save control register values 302 + b start_kernel 303 + ENDPROC(__mmap_switched) 304 + 305 + .align 2 306 + .type __mmap_switched_data, %object 307 + __mmap_switched_data: 308 + .long __data_loc @ r4 309 + .long _sdata @ r5 310 + .long __bss_start @ r6 311 + .long _end @ r7 312 + .long processor_id @ r4 313 + .long __machine_arch_type @ r5 314 + .long __atags_pointer @ r6 315 + .long cr_alignment @ r7 316 + .long init_thread_union + THREAD_START_SP @ sp 317 + .size __mmap_switched_data, . - __mmap_switched_data 318 + 319 + /* 320 + * This provides a C-API version of __lookup_machine_type 321 + */ 322 + ENTRY(lookup_machine_type) 323 + stmfd sp!, {r4 - r6, lr} 324 + mov r1, r0 325 + bl __lookup_machine_type 326 + mov r0, r5 327 + ldmfd sp!, {r4 - r6, pc} 328 + ENDPROC(lookup_machine_type) 329 + 330 + /* 331 + * This provides a C-API version of __lookup_processor_type 332 + */ 333 + ENTRY(lookup_processor_type) 334 + stmfd sp!, {r4 - r6, r9, lr} 335 + mov r9, r0 336 + bl __lookup_processor_type 337 + mov r0, r5 338 + ldmfd sp!, {r4 - r6, r9, pc} 339 + ENDPROC(lookup_processor_type) 340 + 341 + /* 342 + * Read processor ID register (CP#15, CR0), and look up in the linker-built 343 + * supported processor list. Note that we can't use the absolute addresses 344 + * for the __proc_info lists since we aren't running with the MMU on 345 + * (and therefore, we are not in the correct address space). We have to 346 + * calculate the offset. 347 + * 348 + * r9 = cpuid 349 + * Returns: 350 + * r3, r4, r6 corrupted 351 + * r5 = proc_info pointer in physical address space 352 + * r9 = cpuid (preserved) 353 + */ 354 + __CPUINIT 355 + __lookup_processor_type: 356 + adr r3, __lookup_processor_type_data 357 + ldmia r3, {r4 - r6} 358 + sub r3, r3, r4 @ get offset between virt&phys 359 + add r5, r5, r3 @ convert virt addresses to 360 + add r6, r6, r3 @ physical address space 361 + 1: ldmia r5, {r3, r4} @ value, mask 362 + and r4, r4, r9 @ mask wanted bits 363 + teq r3, r4 364 + beq 2f 365 + add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) 366 + cmp r5, r6 367 + blo 1b 368 + mov r5, #0 @ unknown processor 369 + 2: mov pc, lr 370 + ENDPROC(__lookup_processor_type) 371 + 372 + /* 373 + * Look in <asm/procinfo.h> for information about the __proc_info structure. 374 + */ 375 + .align 2 376 + .type __lookup_processor_type_data, %object 377 + __lookup_processor_type_data: 378 + .long . 379 + .long __proc_info_begin 380 + .long __proc_info_end 381 + .size __lookup_processor_type_data, . - __lookup_processor_type_data 382 + 383 + __error_p: 384 + #ifdef CONFIG_DEBUG_LL 385 + adr r0, str_p1 386 + bl printascii 387 + mov r0, r9 388 + bl printhex8 389 + adr r0, str_p2 390 + bl printascii 391 + b __error 392 + str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" 393 + str_p2: .asciz ").\n" 394 + .align 395 + #endif 396 + ENDPROC(__error_p) 397 + 398 + __error: 399 + #ifdef CONFIG_ARCH_RPC 400 + /* 401 + * Turn the screen red on a error - RiscPC only. 402 + */ 403 + mov r0, #0x02000000 404 + mov r3, #0x11 405 + orr r3, r3, r3, lsl #8 406 + orr r3, r3, r3, lsl #16 407 + str r3, [r0], #4 408 + str r3, [r0], #4 409 + str r3, [r0], #4 410 + str r3, [r0], #4 411 + #endif 412 + 1: mov r0, r0 413 + b 1b 414 + ENDPROC(__error)
+1 -4
arch/arm/kernel/head-nommu.S
··· 48 movs r8, r5 @ invalid machine (r5=0)? 49 beq __error_a @ yes, error 'a' 50 51 - ldr r13, __switch_data @ address to jump to after 52 - @ the initialization is done 53 adr lr, BSYM(__after_proc_init) @ return (PIC) address 54 ARM( add pc, r10, #PROCINFO_INITFUNC ) 55 THUMB( add r12, r10, #PROCINFO_INITFUNC ) ··· 85 mcr p15, 0, r0, c1, c0, 0 @ write control reg 86 #endif /* CONFIG_CPU_CP15 */ 87 88 - mov r3, r13 89 - mov pc, r3 @ clear the BSS and jump 90 @ to start_kernel 91 ENDPROC(__after_proc_init) 92 .ltorg
··· 48 movs r8, r5 @ invalid machine (r5=0)? 49 beq __error_a @ yes, error 'a' 50 51 adr lr, BSYM(__after_proc_init) @ return (PIC) address 52 ARM( add pc, r10, #PROCINFO_INITFUNC ) 53 THUMB( add r12, r10, #PROCINFO_INITFUNC ) ··· 87 mcr p15, 0, r0, c1, c0, 0 @ write control reg 88 #endif /* CONFIG_CPU_CP15 */ 89 90 + b __mmap_switched @ clear the BSS and jump 91 @ to start_kernel 92 ENDPROC(__after_proc_init) 93 .ltorg
+139 -111
arch/arm/kernel/head.S
··· 98 * above. On return, the CPU will be ready for the MMU to be 99 * turned on, and r0 will hold the CPU control register value. 100 */ 101 - ldr r13, __switch_data @ address to jump to after 102 @ mmu has been enabled 103 - adr lr, BSYM(__enable_mmu) @ return (PIC) address 104 ARM( add pc, r10, #PROCINFO_INITFUNC ) 105 THUMB( add r12, r10, #PROCINFO_INITFUNC ) 106 THUMB( mov pc, r12 ) 107 ENDPROC(stext) 108 - 109 - #if defined(CONFIG_SMP) 110 - ENTRY(secondary_startup) 111 - /* 112 - * Common entry point for secondary CPUs. 113 - * 114 - * Ensure that we're in SVC mode, and IRQs are disabled. Lookup 115 - * the processor type - there is no need to check the machine type 116 - * as it has already been validated by the primary processor. 117 - */ 118 - setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 119 - mrc p15, 0, r9, c0, c0 @ get processor id 120 - bl __lookup_processor_type 121 - movs r10, r5 @ invalid processor? 122 - moveq r0, #'p' @ yes, error 'p' 123 - beq __error 124 - 125 - /* 126 - * Use the page tables supplied from __cpu_up. 127 - */ 128 - adr r4, __secondary_data 129 - ldmia r4, {r5, r7, r12} @ address to jump to after 130 - sub r4, r4, r5 @ mmu has been enabled 131 - ldr r4, [r7, r4] @ get secondary_data.pgdir 132 - adr lr, BSYM(__enable_mmu) @ return address 133 - mov r13, r12 @ __secondary_switched address 134 - ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor 135 - @ (return control reg) 136 - THUMB( add r12, r10, #PROCINFO_INITFUNC ) 137 - THUMB( mov pc, r12 ) 138 - ENDPROC(secondary_startup) 139 - 140 - /* 141 - * r6 = &secondary_data 142 - */ 143 - ENTRY(__secondary_switched) 144 - ldr sp, [r7, #4] @ get secondary_data.stack 145 - mov fp, #0 146 - b secondary_start_kernel 147 - ENDPROC(__secondary_switched) 148 - 149 - .type __secondary_data, %object 150 - __secondary_data: 151 - .long . 152 - .long secondary_data 153 - .long __secondary_switched 154 - #endif /* defined(CONFIG_SMP) */ 155 - 156 - 157 - 158 - /* 159 - * Setup common bits before finally enabling the MMU. Essentially 160 - * this is just loading the page table pointer and domain access 161 - * registers. 162 - */ 163 - __enable_mmu: 164 - #ifdef CONFIG_ALIGNMENT_TRAP 165 - orr r0, r0, #CR_A 166 - #else 167 - bic r0, r0, #CR_A 168 - #endif 169 - #ifdef CONFIG_CPU_DCACHE_DISABLE 170 - bic r0, r0, #CR_C 171 - #endif 172 - #ifdef CONFIG_CPU_BPREDICT_DISABLE 173 - bic r0, r0, #CR_Z 174 - #endif 175 - #ifdef CONFIG_CPU_ICACHE_DISABLE 176 - bic r0, r0, #CR_I 177 - #endif 178 - mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ 179 - domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ 180 - domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ 181 - domain_val(DOMAIN_IO, DOMAIN_CLIENT)) 182 - mcr p15, 0, r5, c3, c0, 0 @ load domain access register 183 - mcr p15, 0, r4, c2, c0, 0 @ load page table pointer 184 - b __turn_mmu_on 185 - ENDPROC(__enable_mmu) 186 - 187 - /* 188 - * Enable the MMU. This completely changes the structure of the visible 189 - * memory space. You will not be able to trace execution through this. 190 - * If you have an enquiry about this, *please* check the linux-arm-kernel 191 - * mailing list archives BEFORE sending another post to the list. 192 - * 193 - * r0 = cp#15 control register 194 - * r13 = *virtual* address to jump to upon completion 195 - * 196 - * other registers depend on the function called upon completion 197 - */ 198 - .align 5 199 - __turn_mmu_on: 200 - mov r0, r0 201 - mcr p15, 0, r0, c1, c0, 0 @ write control reg 202 - mrc p15, 0, r3, c0, c0, 0 @ read id reg 203 - mov r3, r3 204 - mov r3, r13 205 - mov pc, r3 206 - ENDPROC(__turn_mmu_on) 207 - 208 209 /* 210 * Setup the initial page tables. We only setup the barest ··· 118 * r10 = procinfo 119 * 120 * Returns: 121 - * r0, r3, r6, r7 corrupted 122 * r4 = physical page table address 123 */ 124 __create_page_tables: ··· 140 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags 141 142 /* 143 - * Create identity mapping for first MB of kernel to 144 - * cater for the MMU enable. This identity mapping 145 - * will be removed by paging_init(). We use our current program 146 - * counter to determine corresponding section base address. 147 */ 148 - mov r6, pc 149 - mov r6, r6, lsr #20 @ start of kernel section 150 - orr r3, r7, r6, lsl #20 @ flags + kernel base 151 - str r3, [r4, r6, lsl #2] @ identity mapping 152 153 /* 154 * Now setup the pagetables for our kernel direct 155 * mapped region. 156 */ 157 add r0, r4, #(KERNEL_START & 0xff000000) >> 18 158 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! 159 ldr r6, =(KERNEL_END - 1) ··· 247 mov pc, lr 248 ENDPROC(__create_page_tables) 249 .ltorg 250 251 #ifdef CONFIG_SMP_ON_UP 252 __fixup_smp:
··· 98 * above. On return, the CPU will be ready for the MMU to be 99 * turned on, and r0 will hold the CPU control register value. 100 */ 101 + ldr r13, =__mmap_switched @ address to jump to after 102 @ mmu has been enabled 103 + adr lr, BSYM(1f) @ return (PIC) address 104 ARM( add pc, r10, #PROCINFO_INITFUNC ) 105 THUMB( add r12, r10, #PROCINFO_INITFUNC ) 106 THUMB( mov pc, r12 ) 107 + 1: b __enable_mmu 108 ENDPROC(stext) 109 + .ltorg 110 111 /* 112 * Setup the initial page tables. We only setup the barest ··· 216 * r10 = procinfo 217 * 218 * Returns: 219 + * r0, r3, r5-r7 corrupted 220 * r4 = physical page table address 221 */ 222 __create_page_tables: ··· 238 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags 239 240 /* 241 + * Create identity mapping to cater for __enable_mmu. 242 + * This identity mapping will be removed by paging_init(). 243 */ 244 + adr r0, __enable_mmu_loc 245 + ldmia r0, {r3, r5, r6} 246 + sub r0, r0, r3 @ virt->phys offset 247 + add r5, r5, r0 @ phys __enable_mmu 248 + add r6, r6, r0 @ phys __enable_mmu_end 249 + mov r5, r5, lsr #20 250 + mov r6, r6, lsr #20 251 + 252 + 1: orr r3, r7, r5, lsl #20 @ flags + kernel base 253 + str r3, [r4, r5, lsl #2] @ identity mapping 254 + teq r5, r6 255 + addne r5, r5, #1 @ next section 256 + bne 1b 257 258 /* 259 * Now setup the pagetables for our kernel direct 260 * mapped region. 261 */ 262 + mov r3, pc 263 + mov r3, r3, lsr #20 264 + orr r3, r7, r3, lsl #20 265 add r0, r4, #(KERNEL_START & 0xff000000) >> 18 266 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! 267 ldr r6, =(KERNEL_END - 1) ··· 335 mov pc, lr 336 ENDPROC(__create_page_tables) 337 .ltorg 338 + __enable_mmu_loc: 339 + .long . 340 + .long __enable_mmu 341 + .long __enable_mmu_end 342 + 343 + #if defined(CONFIG_SMP) 344 + __CPUINIT 345 + ENTRY(secondary_startup) 346 + /* 347 + * Common entry point for secondary CPUs. 348 + * 349 + * Ensure that we're in SVC mode, and IRQs are disabled. Lookup 350 + * the processor type - there is no need to check the machine type 351 + * as it has already been validated by the primary processor. 352 + */ 353 + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 354 + mrc p15, 0, r9, c0, c0 @ get processor id 355 + bl __lookup_processor_type 356 + movs r10, r5 @ invalid processor? 357 + moveq r0, #'p' @ yes, error 'p' 358 + beq __error_p 359 + 360 + /* 361 + * Use the page tables supplied from __cpu_up. 362 + */ 363 + adr r4, __secondary_data 364 + ldmia r4, {r5, r7, r12} @ address to jump to after 365 + sub r4, r4, r5 @ mmu has been enabled 366 + ldr r4, [r7, r4] @ get secondary_data.pgdir 367 + adr lr, BSYM(__enable_mmu) @ return address 368 + mov r13, r12 @ __secondary_switched address 369 + ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor 370 + @ (return control reg) 371 + THUMB( add r12, r10, #PROCINFO_INITFUNC ) 372 + THUMB( mov pc, r12 ) 373 + ENDPROC(secondary_startup) 374 + 375 + /* 376 + * r6 = &secondary_data 377 + */ 378 + ENTRY(__secondary_switched) 379 + ldr sp, [r7, #4] @ get secondary_data.stack 380 + mov fp, #0 381 + b secondary_start_kernel 382 + ENDPROC(__secondary_switched) 383 + 384 + .type __secondary_data, %object 385 + __secondary_data: 386 + .long . 387 + .long secondary_data 388 + .long __secondary_switched 389 + #endif /* defined(CONFIG_SMP) */ 390 + 391 + 392 + 393 + /* 394 + * Setup common bits before finally enabling the MMU. Essentially 395 + * this is just loading the page table pointer and domain access 396 + * registers. 397 + * 398 + * r0 = cp#15 control register 399 + * r1 = machine ID 400 + * r2 = atags pointer 401 + * r4 = page table pointer 402 + * r9 = processor ID 403 + * r13 = *virtual* address to jump to upon completion 404 + */ 405 + __enable_mmu: 406 + #ifdef CONFIG_ALIGNMENT_TRAP 407 + orr r0, r0, #CR_A 408 + #else 409 + bic r0, r0, #CR_A 410 + #endif 411 + #ifdef CONFIG_CPU_DCACHE_DISABLE 412 + bic r0, r0, #CR_C 413 + #endif 414 + #ifdef CONFIG_CPU_BPREDICT_DISABLE 415 + bic r0, r0, #CR_Z 416 + #endif 417 + #ifdef CONFIG_CPU_ICACHE_DISABLE 418 + bic r0, r0, #CR_I 419 + #endif 420 + mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ 421 + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ 422 + domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ 423 + domain_val(DOMAIN_IO, DOMAIN_CLIENT)) 424 + mcr p15, 0, r5, c3, c0, 0 @ load domain access register 425 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer 426 + b __turn_mmu_on 427 + ENDPROC(__enable_mmu) 428 + 429 + /* 430 + * Enable the MMU. This completely changes the structure of the visible 431 + * memory space. You will not be able to trace execution through this. 432 + * If you have an enquiry about this, *please* check the linux-arm-kernel 433 + * mailing list archives BEFORE sending another post to the list. 434 + * 435 + * r0 = cp#15 control register 436 + * r1 = machine ID 437 + * r2 = atags pointer 438 + * r9 = processor ID 439 + * r13 = *virtual* address to jump to upon completion 440 + * 441 + * other registers depend on the function called upon completion 442 + */ 443 + .align 5 444 + __turn_mmu_on: 445 + mov r0, r0 446 + mcr p15, 0, r0, c1, c0, 0 @ write control reg 447 + mrc p15, 0, r3, c0, c0, 0 @ read id reg 448 + mov r3, r3 449 + mov r3, r13 450 + mov pc, r3 451 + __enable_mmu_end: 452 + ENDPROC(__turn_mmu_on) 453 + 454 455 #ifdef CONFIG_SMP_ON_UP 456 __fixup_smp:
+55 -8
arch/arm/kernel/smp.c
··· 33 #include <asm/pgtable.h> 34 #include <asm/pgalloc.h> 35 #include <asm/processor.h> 36 #include <asm/tlbflush.h> 37 #include <asm/ptrace.h> 38 #include <asm/localtimer.h> ··· 68 IPI_CPU_STOP, 69 }; 70 71 int __cpuinit __cpu_up(unsigned int cpu) 72 { 73 struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); 74 struct task_struct *idle = ci->idle; 75 pgd_t *pgd; 76 - pmd_t *pmd; 77 int ret; 78 79 /* ··· 137 * a 1:1 mapping for the physical address of the kernel. 138 */ 139 pgd = pgd_alloc(&init_mm); 140 - pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET); 141 - *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) | 142 - PMD_TYPE_SECT | PMD_SECT_AP_WRITE); 143 - flush_pmd_entry(pmd); 144 - outer_clean_range(__pa(pmd), __pa(pmd + 1)); 145 146 /* 147 * We need to tell the secondary core where to find ··· 184 secondary_data.stack = NULL; 185 secondary_data.pgdir = 0; 186 187 - *pmd = __pmd(0); 188 - clean_pmd_entry(pmd); 189 pgd_free(&init_mm, pgd); 190 191 if (ret) {
··· 33 #include <asm/pgtable.h> 34 #include <asm/pgalloc.h> 35 #include <asm/processor.h> 36 + #include <asm/sections.h> 37 #include <asm/tlbflush.h> 38 #include <asm/ptrace.h> 39 #include <asm/localtimer.h> ··· 67 IPI_CPU_STOP, 68 }; 69 70 + static inline void identity_mapping_add(pgd_t *pgd, unsigned long start, 71 + unsigned long end) 72 + { 73 + unsigned long addr, prot; 74 + pmd_t *pmd; 75 + 76 + prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; 77 + if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) 78 + prot |= PMD_BIT4; 79 + 80 + for (addr = start & PGDIR_MASK; addr < end;) { 81 + pmd = pmd_offset(pgd + pgd_index(addr), addr); 82 + pmd[0] = __pmd(addr | prot); 83 + addr += SECTION_SIZE; 84 + pmd[1] = __pmd(addr | prot); 85 + addr += SECTION_SIZE; 86 + flush_pmd_entry(pmd); 87 + outer_clean_range(__pa(pmd), __pa(pmd + 1)); 88 + } 89 + } 90 + 91 + static inline void identity_mapping_del(pgd_t *pgd, unsigned long start, 92 + unsigned long end) 93 + { 94 + unsigned long addr; 95 + pmd_t *pmd; 96 + 97 + for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) { 98 + pmd = pmd_offset(pgd + pgd_index(addr), addr); 99 + pmd[0] = __pmd(0); 100 + pmd[1] = __pmd(0); 101 + clean_pmd_entry(pmd); 102 + outer_clean_range(__pa(pmd), __pa(pmd + 1)); 103 + } 104 + } 105 + 106 int __cpuinit __cpu_up(unsigned int cpu) 107 { 108 struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); 109 struct task_struct *idle = ci->idle; 110 pgd_t *pgd; 111 int ret; 112 113 /* ··· 101 * a 1:1 mapping for the physical address of the kernel. 102 */ 103 pgd = pgd_alloc(&init_mm); 104 + if (!pgd) 105 + return -ENOMEM; 106 + 107 + if (PHYS_OFFSET != PAGE_OFFSET) { 108 + #ifndef CONFIG_HOTPLUG_CPU 109 + identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end)); 110 + #endif 111 + identity_mapping_add(pgd, __pa(_stext), __pa(_etext)); 112 + identity_mapping_add(pgd, __pa(_sdata), __pa(_edata)); 113 + } 114 115 /* 116 * We need to tell the secondary core where to find ··· 143 secondary_data.stack = NULL; 144 secondary_data.pgdir = 0; 145 146 + if (PHYS_OFFSET != PAGE_OFFSET) { 147 + #ifndef CONFIG_HOTPLUG_CPU 148 + identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end)); 149 + #endif 150 + identity_mapping_del(pgd, __pa(_stext), __pa(_etext)); 151 + identity_mapping_del(pgd, __pa(_sdata), __pa(_edata)); 152 + } 153 + 154 pgd_free(&init_mm, pgd); 155 156 if (ret) {
+17 -7
arch/arm/kernel/vmlinux.lds.S
··· 8 #include <asm/memory.h> 9 #include <asm/page.h> 10 11 OUTPUT_ARCH(arm) 12 ENTRY(stext) 13 ··· 44 HEAD_TEXT 45 INIT_TEXT 46 _einittext = .; 47 - __proc_info_begin = .; 48 - *(.proc.info.init) 49 - __proc_info_end = .; 50 __arch_info_begin = .; 51 *(.arch.info.init) 52 __arch_info_end = .; ··· 84 /DISCARD/ : { 85 *(.ARM.exidx.exit.text) 86 *(.ARM.extab.exit.text) 87 - #ifndef CONFIG_HOTPLUG_CPU 88 - *(.ARM.exidx.cpuexit.text) 89 - *(.ARM.extab.cpuexit.text) 90 - #endif 91 #ifndef CONFIG_HOTPLUG 92 *(.ARM.exidx.devexit.text) 93 *(.ARM.extab.devexit.text) ··· 114 *(.glue_7) 115 *(.glue_7t) 116 *(.got) /* Global offset table */ 117 } 118 119 RO_DATA(PAGE_SIZE)
··· 8 #include <asm/memory.h> 9 #include <asm/page.h> 10 11 + #define PROC_INFO \ 12 + VMLINUX_SYMBOL(__proc_info_begin) = .; \ 13 + *(.proc.info.init) \ 14 + VMLINUX_SYMBOL(__proc_info_end) = .; 15 + 16 + #ifdef CONFIG_HOTPLUG_CPU 17 + #define ARM_CPU_DISCARD(x) 18 + #define ARM_CPU_KEEP(x) x 19 + #else 20 + #define ARM_CPU_DISCARD(x) x 21 + #define ARM_CPU_KEEP(x) 22 + #endif 23 + 24 OUTPUT_ARCH(arm) 25 ENTRY(stext) 26 ··· 31 HEAD_TEXT 32 INIT_TEXT 33 _einittext = .; 34 + ARM_CPU_DISCARD(PROC_INFO) 35 __arch_info_begin = .; 36 *(.arch.info.init) 37 __arch_info_end = .; ··· 73 /DISCARD/ : { 74 *(.ARM.exidx.exit.text) 75 *(.ARM.extab.exit.text) 76 + ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text)) 77 + ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) 78 #ifndef CONFIG_HOTPLUG 79 *(.ARM.exidx.devexit.text) 80 *(.ARM.extab.devexit.text) ··· 105 *(.glue_7) 106 *(.glue_7t) 107 *(.got) /* Global offset table */ 108 + ARM_CPU_KEEP(PROC_INFO) 109 } 110 111 RO_DATA(PAGE_SIZE)
+1 -1
arch/arm/mm/proc-arm1020.S
··· 430 #endif /* CONFIG_MMU */ 431 mov pc, lr 432 433 - __INIT 434 435 .type __arm1020_setup, #function 436 __arm1020_setup:
··· 430 #endif /* CONFIG_MMU */ 431 mov pc, lr 432 433 + __CPUINIT 434 435 .type __arm1020_setup, #function 436 __arm1020_setup:
+1 -1
arch/arm/mm/proc-arm1020e.S
··· 412 #endif /* CONFIG_MMU */ 413 mov pc, lr 414 415 - __INIT 416 417 .type __arm1020e_setup, #function 418 __arm1020e_setup:
··· 412 #endif /* CONFIG_MMU */ 413 mov pc, lr 414 415 + __CPUINIT 416 417 .type __arm1020e_setup, #function 418 __arm1020e_setup:
+1 -1
arch/arm/mm/proc-arm1022.S
··· 394 #endif /* CONFIG_MMU */ 395 mov pc, lr 396 397 - __INIT 398 399 .type __arm1022_setup, #function 400 __arm1022_setup:
··· 394 #endif /* CONFIG_MMU */ 395 mov pc, lr 396 397 + __CPUINIT 398 399 .type __arm1022_setup, #function 400 __arm1022_setup:
+1 -1
arch/arm/mm/proc-arm1026.S
··· 384 mov pc, lr 385 386 387 - __INIT 388 389 .type __arm1026_setup, #function 390 __arm1026_setup:
··· 384 mov pc, lr 385 386 387 + __CPUINIT 388 389 .type __arm1026_setup, #function 390 __arm1026_setup:
+1 -1
arch/arm/mm/proc-arm6_7.S
··· 238 mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc 239 mov pc, r0 240 241 - __INIT 242 243 .type __arm6_setup, #function 244 __arm6_setup: mov r0, #0
··· 238 mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc 239 mov pc, r0 240 241 + __CPUINIT 242 243 .type __arm6_setup, #function 244 __arm6_setup: mov r0, #0
+1 -1
arch/arm/mm/proc-arm720.S
··· 113 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 114 mov pc, r0 115 116 - __INIT 117 118 .type __arm710_setup, #function 119 __arm710_setup:
··· 113 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 114 mov pc, r0 115 116 + __CPUINIT 117 118 .type __arm710_setup, #function 119 __arm710_setup:
+1 -1
arch/arm/mm/proc-arm740.S
··· 55 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 56 mov pc, r0 57 58 - __INIT 59 60 .type __arm740_setup, #function 61 __arm740_setup:
··· 55 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 56 mov pc, r0 57 58 + __CPUINIT 59 60 .type __arm740_setup, #function 61 __arm740_setup:
+1 -1
arch/arm/mm/proc-arm7tdmi.S
··· 46 ENTRY(cpu_arm7tdmi_reset) 47 mov pc, r0 48 49 - __INIT 50 51 .type __arm7tdmi_setup, #function 52 __arm7tdmi_setup:
··· 46 ENTRY(cpu_arm7tdmi_reset) 47 mov pc, r0 48 49 + __CPUINIT 50 51 .type __arm7tdmi_setup, #function 52 __arm7tdmi_setup:
+1 -1
arch/arm/mm/proc-arm920.S
··· 375 #endif 376 mov pc, lr 377 378 - __INIT 379 380 .type __arm920_setup, #function 381 __arm920_setup:
··· 375 #endif 376 mov pc, lr 377 378 + __CPUINIT 379 380 .type __arm920_setup, #function 381 __arm920_setup:
+1 -1
arch/arm/mm/proc-arm922.S
··· 379 #endif /* CONFIG_MMU */ 380 mov pc, lr 381 382 - __INIT 383 384 .type __arm922_setup, #function 385 __arm922_setup:
··· 379 #endif /* CONFIG_MMU */ 380 mov pc, lr 381 382 + __CPUINIT 383 384 .type __arm922_setup, #function 385 __arm922_setup:
+1 -1
arch/arm/mm/proc-arm925.S
··· 428 #endif /* CONFIG_MMU */ 429 mov pc, lr 430 431 - __INIT 432 433 .type __arm925_setup, #function 434 __arm925_setup:
··· 428 #endif /* CONFIG_MMU */ 429 mov pc, lr 430 431 + __CPUINIT 432 433 .type __arm925_setup, #function 434 __arm925_setup:
+1 -1
arch/arm/mm/proc-arm926.S
··· 389 #endif 390 mov pc, lr 391 392 - __INIT 393 394 .type __arm926_setup, #function 395 __arm926_setup:
··· 389 #endif 390 mov pc, lr 391 392 + __CPUINIT 393 394 .type __arm926_setup, #function 395 __arm926_setup:
+1 -1
arch/arm/mm/proc-arm940.S
··· 264 .long arm940_dma_unmap_area 265 .long arm940_dma_flush_range 266 267 - __INIT 268 269 .type __arm940_setup, #function 270 __arm940_setup:
··· 264 .long arm940_dma_unmap_area 265 .long arm940_dma_flush_range 266 267 + __CPUINIT 268 269 .type __arm940_setup, #function 270 __arm940_setup:
+1 -1
arch/arm/mm/proc-arm946.S
··· 317 mcr p15, 0, r0, c7, c10, 4 @ drain WB 318 mov pc, lr 319 320 - __INIT 321 322 .type __arm946_setup, #function 323 __arm946_setup:
··· 317 mcr p15, 0, r0, c7, c10, 4 @ drain WB 318 mov pc, lr 319 320 + __CPUINIT 321 322 .type __arm946_setup, #function 323 __arm946_setup:
+1 -1
arch/arm/mm/proc-arm9tdmi.S
··· 46 ENTRY(cpu_arm9tdmi_reset) 47 mov pc, r0 48 49 - __INIT 50 51 .type __arm9tdmi_setup, #function 52 __arm9tdmi_setup:
··· 46 ENTRY(cpu_arm9tdmi_reset) 47 mov pc, r0 48 49 + __CPUINIT 50 51 .type __arm9tdmi_setup, #function 52 __arm9tdmi_setup:
+1 -1
arch/arm/mm/proc-fa526.S
··· 134 #endif 135 mov pc, lr 136 137 - __INIT 138 139 .type __fa526_setup, #function 140 __fa526_setup:
··· 134 #endif 135 mov pc, lr 136 137 + __CPUINIT 138 139 .type __fa526_setup, #function 140 __fa526_setup:
+1 -1
arch/arm/mm/proc-feroceon.S
··· 494 #endif 495 mov pc, lr 496 497 - __INIT 498 499 .type __feroceon_setup, #function 500 __feroceon_setup:
··· 494 #endif 495 mov pc, lr 496 497 + __CPUINIT 498 499 .type __feroceon_setup, #function 500 __feroceon_setup:
+1 -1
arch/arm/mm/proc-mohawk.S
··· 338 mcr p15, 0, r0, c7, c10, 4 @ drain WB 339 mov pc, lr 340 341 - __INIT 342 343 .type __mohawk_setup, #function 344 __mohawk_setup:
··· 338 mcr p15, 0, r0, c7, c10, 4 @ drain WB 339 mov pc, lr 340 341 + __CPUINIT 342 343 .type __mohawk_setup, #function 344 __mohawk_setup:
+1 -1
arch/arm/mm/proc-sa110.S
··· 156 #endif 157 mov pc, lr 158 159 - __INIT 160 161 .type __sa110_setup, #function 162 __sa110_setup:
··· 156 #endif 157 mov pc, lr 158 159 + __CPUINIT 160 161 .type __sa110_setup, #function 162 __sa110_setup:
+1 -1
arch/arm/mm/proc-sa1100.S
··· 169 #endif 170 mov pc, lr 171 172 - __INIT 173 174 .type __sa1100_setup, #function 175 __sa1100_setup:
··· 169 #endif 170 mov pc, lr 171 172 + __CPUINIT 173 174 .type __sa1100_setup, #function 175 __sa1100_setup:
+5 -1
arch/arm/mm/proc-v6.S
··· 135 136 .align 137 138 - __INIT 139 140 /* 141 * __v6_setup ··· 193 v6_crval: 194 crval clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c 195 196 .type v6_processor_functions, #object 197 ENTRY(v6_processor_functions) 198 .word v6_early_abort ··· 207 .word cpu_v6_switch_mm 208 .word cpu_v6_set_pte_ext 209 .size v6_processor_functions, . - v6_processor_functions 210 211 .type cpu_arch_name, #object 212 cpu_arch_name:
··· 135 136 .align 137 138 + __CPUINIT 139 140 /* 141 * __v6_setup ··· 193 v6_crval: 194 crval clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c 195 196 + __INITDATA 197 + 198 .type v6_processor_functions, #object 199 ENTRY(v6_processor_functions) 200 .word v6_early_abort ··· 205 .word cpu_v6_switch_mm 206 .word cpu_v6_set_pte_ext 207 .size v6_processor_functions, . - v6_processor_functions 208 + 209 + .section ".rodata" 210 211 .type cpu_arch_name, #object 212 cpu_arch_name:
+5 -1
arch/arm/mm/proc-v7.S
··· 168 .ascii "ARMv7 Processor" 169 .align 170 171 - __INIT 172 173 /* 174 * __v7_setup ··· 325 __v7_setup_stack: 326 .space 4 * 11 @ 11 registers 327 328 .type v7_processor_functions, #object 329 ENTRY(v7_processor_functions) 330 .word v7_early_abort ··· 339 .word cpu_v7_switch_mm 340 .word cpu_v7_set_pte_ext 341 .size v7_processor_functions, . - v7_processor_functions 342 343 .type cpu_arch_name, #object 344 cpu_arch_name:
··· 168 .ascii "ARMv7 Processor" 169 .align 170 171 + __CPUINIT 172 173 /* 174 * __v7_setup ··· 325 __v7_setup_stack: 326 .space 4 * 11 @ 11 registers 327 328 + __INITDATA 329 + 330 .type v7_processor_functions, #object 331 ENTRY(v7_processor_functions) 332 .word v7_early_abort ··· 337 .word cpu_v7_switch_mm 338 .word cpu_v7_set_pte_ext 339 .size v7_processor_functions, . - v7_processor_functions 340 + 341 + .section ".rodata" 342 343 .type cpu_arch_name, #object 344 cpu_arch_name:
+1 -1
arch/arm/mm/proc-xsc3.S
··· 404 405 .align 406 407 - __INIT 408 409 .type __xsc3_setup, #function 410 __xsc3_setup:
··· 404 405 .align 406 407 + __CPUINIT 408 409 .type __xsc3_setup, #function 410 __xsc3_setup:
+1 -1
arch/arm/mm/proc-xscale.S
··· 506 507 .align 508 509 - __INIT 510 511 .type __xscale_setup, #function 512 __xscale_setup:
··· 506 507 .align 508 509 + __CPUINIT 510 511 .type __xscale_setup, #function 512 __xscale_setup: