1/* 2 * linux/arch/arm/kernel/head-nommu.S 3 * 4 * Copyright (C) 1994-2002 Russell King 5 * Copyright (C) 2003-2006 Hyok S. Choi 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Common kernel startup code (non-paged MM) 12 * 13 */ 14#include <linux/linkage.h> 15#include <linux/init.h> 16#include <linux/errno.h> 17 18#include <asm/assembler.h> 19#include <asm/ptrace.h> 20#include <asm/asm-offsets.h> 21#include <asm/memory.h> 22#include <asm/cp15.h> 23#include <asm/thread_info.h> 24#include <asm/v7m.h> 25#include <asm/mpu.h> 26#include <asm/page.h> 27 28/* 29 * Kernel startup entry point. 30 * --------------------------- 31 * 32 * This is normally called from the decompressor code. The requirements 33 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, 34 * r1 = machine nr. 35 * 36 * See linux/arch/arm/tools/mach-types for the complete list of machine 37 * numbers for r1. 38 * 39 */ 40 41 __HEAD 42 43#ifdef CONFIG_CPU_THUMBONLY 44 .thumb 45ENTRY(stext) 46#else 47 .arm 48ENTRY(stext) 49 50 THUMB( badr r9, 1f ) @ Kernel is always entered in ARM. 51 THUMB( bx r9 ) @ If this is a Thumb-2 kernel, 52 THUMB( .thumb ) @ switch to Thumb now. 53 THUMB(1: ) 54#endif 55 56 setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode 57 @ and irqs disabled 58#if defined(CONFIG_CPU_CP15) 59 mrc p15, 0, r9, c0, c0 @ get processor id 60#elif defined(CONFIG_CPU_V7M) 61 ldr r9, =BASEADDR_V7M_SCB 62 ldr r9, [r9, V7M_SCB_CPUID] 63#else 64 ldr r9, =CONFIG_PROCESSOR_ID 65#endif 66 bl __lookup_processor_type @ r5=procinfo r9=cpuid 67 movs r10, r5 @ invalid processor (r5=0)? 68 beq __error_p @ yes, error 'p' 69 70#ifdef CONFIG_ARM_MPU 71 /* Calculate the size of a region covering just the kernel */ 72 ldr r5, =PLAT_PHYS_OFFSET @ Region start: PHYS_OFFSET 73 ldr r6, =(_end) @ Cover whole kernel 74 sub r6, r6, r5 @ Minimum size of region to map 75 clz r6, r6 @ Region size must be 2^N... 76 rsb r6, r6, #31 @ ...so round up region size 77 lsl r6, r6, #MPU_RSR_SZ @ Put size in right field 78 orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit 79 bl __setup_mpu 80#endif 81 82 badr lr, 1f @ return (PIC) address 83 ldr r12, [r10, #PROCINFO_INITFUNC] 84 add r12, r12, r10 85 ret r12 861: bl __after_proc_init 87 b __mmap_switched 88ENDPROC(stext) 89 90#ifdef CONFIG_SMP 91 .text 92ENTRY(secondary_startup) 93 /* 94 * Common entry point for secondary CPUs. 95 * 96 * Ensure that we're in SVC mode, and IRQs are disabled. Lookup 97 * the processor type - there is no need to check the machine type 98 * as it has already been validated by the primary processor. 99 */ 100 setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 101#ifndef CONFIG_CPU_CP15 102 ldr r9, =CONFIG_PROCESSOR_ID 103#else 104 mrc p15, 0, r9, c0, c0 @ get processor id 105#endif 106 bl __lookup_processor_type @ r5=procinfo r9=cpuid 107 movs r10, r5 @ invalid processor? 108 beq __error_p @ yes, error 'p' 109 110 ldr r7, __secondary_data 111 112#ifdef CONFIG_ARM_MPU 113 /* Use MPU region info supplied by __cpu_up */ 114 ldr r6, [r7] @ get secondary_data.mpu_rgn_info 115 bl __secondary_setup_mpu @ Initialize the MPU 116#endif 117 118 badr lr, 1f @ return (PIC) address 119 ldr r12, [r10, #PROCINFO_INITFUNC] 120 add r12, r12, r10 121 ret r12 1221: bl __after_proc_init 123 ldr sp, [r7, #12] @ set up the stack pointer 124 mov fp, #0 125 b secondary_start_kernel 126ENDPROC(secondary_startup) 127 128 .type __secondary_data, %object 129__secondary_data: 130 .long secondary_data 131#endif /* CONFIG_SMP */ 132 133/* 134 * Set the Control Register and Read the process ID. 135 */ 136__after_proc_init: 137#ifdef CONFIG_CPU_CP15 138 /* 139 * CP15 system control register value returned in r0 from 140 * the CPU init function. 141 */ 142#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 143 orr r0, r0, #CR_A 144#else 145 bic r0, r0, #CR_A 146#endif 147#ifdef CONFIG_CPU_DCACHE_DISABLE 148 bic r0, r0, #CR_C 149#endif 150#ifdef CONFIG_CPU_BPREDICT_DISABLE 151 bic r0, r0, #CR_Z 152#endif 153#ifdef CONFIG_CPU_ICACHE_DISABLE 154 bic r0, r0, #CR_I 155#endif 156 mcr p15, 0, r0, c1, c0, 0 @ write control reg 157#elif defined (CONFIG_CPU_V7M) 158 /* For V7M systems we want to modify the CCR similarly to the SCTLR */ 159#ifdef CONFIG_CPU_DCACHE_DISABLE 160 bic r0, r0, #V7M_SCB_CCR_DC 161#endif 162#ifdef CONFIG_CPU_BPREDICT_DISABLE 163 bic r0, r0, #V7M_SCB_CCR_BP 164#endif 165#ifdef CONFIG_CPU_ICACHE_DISABLE 166 bic r0, r0, #V7M_SCB_CCR_IC 167#endif 168 movw r3, #:lower16:(BASEADDR_V7M_SCB + V7M_SCB_CCR) 169 movt r3, #:upper16:(BASEADDR_V7M_SCB + V7M_SCB_CCR) 170 str r0, [r3] 171#endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */ 172 ret lr 173ENDPROC(__after_proc_init) 174 .ltorg 175 176#ifdef CONFIG_ARM_MPU 177 178 179#ifndef CONFIG_CPU_V7M 180/* Set which MPU region should be programmed */ 181.macro set_region_nr tmp, rgnr, unused 182 mov \tmp, \rgnr @ Use static region numbers 183 mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR 184.endm 185 186/* Setup a single MPU region, either D or I side (D-side for unified) */ 187.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE, unused 188 mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR 189 mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR 190 mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR 191.endm 192#else 193.macro set_region_nr tmp, rgnr, base 194 mov \tmp, \rgnr 195 str \tmp, [\base, #MPU_RNR] 196.endm 197 198.macro setup_region bar, acr, sr, unused, base 199 lsl \acr, \acr, #16 200 orr \acr, \acr, \sr 201 str \bar, [\base, #MPU_RBAR] 202 str \acr, [\base, #MPU_RASR] 203.endm 204 205#endif 206/* 207 * Setup the MPU and initial MPU Regions. We create the following regions: 208 * Region 0: Use this for probing the MPU details, so leave disabled. 209 * Region 1: Background region - covers the whole of RAM as strongly ordered 210 * Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6 211 * Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page 212 * 213 * r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION 214*/ 215 216ENTRY(__setup_mpu) 217 218 /* Probe for v7 PMSA compliance */ 219M_CLASS(movw r12, #:lower16:BASEADDR_V7M_SCB) 220M_CLASS(movt r12, #:upper16:BASEADDR_V7M_SCB) 221 222AR_CLASS(mrc p15, 0, r0, c0, c1, 4) @ Read ID_MMFR0 223M_CLASS(ldr r0, [r12, 0x50]) 224 and r0, r0, #(MMFR0_PMSA) @ PMSA field 225 teq r0, #(MMFR0_PMSAv7) @ PMSA v7 226 bxne lr 227 228 /* Determine whether the D/I-side memory map is unified. We set the 229 * flags here and continue to use them for the rest of this function */ 230AR_CLASS(mrc p15, 0, r0, c0, c0, 4) @ MPUIR 231M_CLASS(ldr r0, [r12, #MPU_TYPE]) 232 ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU 233 bxeq lr 234 tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified 235 236 /* Setup second region first to free up r6 */ 237 set_region_nr r0, #MPU_RAM_REGION, r12 238 isb 239 /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */ 240 ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET 241 ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL) 242 243 setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ PHYS_OFFSET, shared, enabled 244 beq 1f @ Memory-map not unified 245 setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ PHYS_OFFSET, shared, enabled 2461: isb 247 248 /* First/background region */ 249 set_region_nr r0, #MPU_BG_REGION, r12 250 isb 251 /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */ 252 mov r0, #0 @ BG region starts at 0x0 253 ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA) 254 mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled 255 256 setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ 0x0, BG region, enabled 257 beq 2f @ Memory-map not unified 258 setup_region r0, r5, r6, MPU_INSTR_SIDE r12 @ 0x0, BG region, enabled 2592: isb 260 261#ifdef CONFIG_XIP_KERNEL 262 set_region_nr r0, #MPU_ROM_REGION, r12 263 isb 264 265 ldr r5,=(MPU_AP_PL1RO_PL0NA | MPU_RGN_NORMAL) 266 267 ldr r0, =CONFIG_XIP_PHYS_ADDR @ ROM start 268 ldr r6, =(_exiprom) @ ROM end 269 sub r6, r6, r0 @ Minimum size of region to map 270 clz r6, r6 @ Region size must be 2^N... 271 rsb r6, r6, #31 @ ...so round up region size 272 lsl r6, r6, #MPU_RSR_SZ @ Put size in right field 273 orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit 274 275 setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled 276 beq 3f @ Memory-map not unified 277 setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled 2783: isb 279#endif 280 281 /* Enable the MPU */ 282AR_CLASS(mrc p15, 0, r0, c1, c0, 0) @ Read SCTLR 283AR_CLASS(bic r0, r0, #CR_BR) @ Disable the 'default mem-map' 284AR_CLASS(orr r0, r0, #CR_M) @ Set SCTRL.M (MPU on) 285AR_CLASS(mcr p15, 0, r0, c1, c0, 0) @ Enable MPU 286 287M_CLASS(ldr r0, [r12, #MPU_CTRL]) 288M_CLASS(bic r0, #MPU_CTRL_PRIVDEFENA) 289M_CLASS(orr r0, #MPU_CTRL_ENABLE) 290M_CLASS(str r0, [r12, #MPU_CTRL]) 291 isb 292 293 ret lr 294ENDPROC(__setup_mpu) 295 296#ifdef CONFIG_SMP 297/* 298 * r6: pointer at mpu_rgn_info 299 */ 300 301ENTRY(__secondary_setup_mpu) 302 /* Probe for v7 PMSA compliance */ 303 mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0 304 and r0, r0, #(MMFR0_PMSA) @ PMSA field 305 teq r0, #(MMFR0_PMSAv7) @ PMSA v7 306 bne __error_p 307 308 /* Determine whether the D/I-side memory map is unified. We set the 309 * flags here and continue to use them for the rest of this function */ 310 mrc p15, 0, r0, c0, c0, 4 @ MPUIR 311 ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU 312 beq __error_p 313 314 ldr r4, [r6, #MPU_RNG_INFO_USED] 315 mov r5, #MPU_RNG_SIZE 316 add r3, r6, #MPU_RNG_INFO_RNGS 317 mla r3, r4, r5, r3 318 3191: 320 tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified 321 sub r3, r3, #MPU_RNG_SIZE 322 sub r4, r4, #1 323 324 set_region_nr r0, r4 325 isb 326 327 ldr r0, [r3, #MPU_RGN_DRBAR] 328 ldr r6, [r3, #MPU_RGN_DRSR] 329 ldr r5, [r3, #MPU_RGN_DRACR] 330 331 setup_region r0, r5, r6, MPU_DATA_SIDE 332 beq 2f 333 setup_region r0, r5, r6, MPU_INSTR_SIDE 3342: isb 335 336 mrc p15, 0, r0, c0, c0, 4 @ Reevaluate the MPUIR 337 cmp r4, #0 338 bgt 1b 339 340 /* Enable the MPU */ 341 mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR 342 bic r0, r0, #CR_BR @ Disable the 'default mem-map' 343 orr r0, r0, #CR_M @ Set SCTRL.M (MPU on) 344 mcr p15, 0, r0, c1, c0, 0 @ Enable MPU 345 isb 346 347 ret lr 348ENDPROC(__secondary_setup_mpu) 349 350#endif /* CONFIG_SMP */ 351#endif /* CONFIG_ARM_MPU */ 352#include "head-common.S" 353