aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/head-nommu.S
diff options
context:
space:
mode:
authorJonathan Austin <jonathan.austin@arm.com>2013-02-22 12:48:56 -0500
committerJonathan Austin <jonathan.austin@arm.com>2013-06-07 12:02:51 -0400
commit67c9845beab16a0c97b9c07f72a4b36b7175bb86 (patch)
treeeb1346cee133ca027d874b1dfb9fc0f98504587a /arch/arm/kernel/head-nommu.S
parenta2b45b0da8bbb98cb2f062cf16c6fdebab4243a1 (diff)
ARM: mpu: add early bring-up code for the ARMv7 PMSA-compliant MPU
This patch adds initial support for using the MPU, which is necessary for SMP operation on PMSAv7 processors because it is the only way to ensure memory is shared. This is an initial patch and full SMP support is added later in this series. The setup of the MPU is performed in a way analagous to that for the MMU: Very early initialisation before the C environment is brought up, followed by a sanity check and more complete initialisation in C. This patch provides the simplest possible memory region configuration: MPU_PROBE_REGION: Reserved for probing MPU details, not enabled MPU_BG_REGION: A 'background' region that specifies all memory strongly ordered MPU_RAM_REGION: A single shared, cacheable, normal region for the valid RAM. In this early initialisation code we simply map the whole of the address space with the BG_REGION and (at least) the kernel with the RAM_REGION. The MPU has region alignment constraints that require us to round past the end of the kernel. As region 2 has a higher priority than region 1, it overrides the strongly- ordered behaviour for RAM only. Subsequent patches will add more complete initialisation from the C-world and support for bringing up secondary CPUs. Signed-off-by: Jonathan Austin <jonathan.austin@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> CC: Hyok S. Choi <hyok.choi@samsung.com>
Diffstat (limited to 'arch/arm/kernel/head-nommu.S')
-rw-r--r--arch/arm/kernel/head-nommu.S87
1 files changed, 87 insertions, 0 deletions
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 06ba9c8e62be..659912c49571 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -17,9 +17,11 @@
17#include <asm/assembler.h> 17#include <asm/assembler.h>
18#include <asm/ptrace.h> 18#include <asm/ptrace.h>
19#include <asm/asm-offsets.h> 19#include <asm/asm-offsets.h>
20#include <asm/memory.h>
20#include <asm/cp15.h> 21#include <asm/cp15.h>
21#include <asm/thread_info.h> 22#include <asm/thread_info.h>
22#include <asm/v7m.h> 23#include <asm/v7m.h>
24#include <asm/mpu.h>
23 25
24/* 26/*
25 * Kernel startup entry point. 27 * Kernel startup entry point.
@@ -63,6 +65,17 @@ ENTRY(stext)
63 movs r10, r5 @ invalid processor (r5=0)? 65 movs r10, r5 @ invalid processor (r5=0)?
64 beq __error_p @ yes, error 'p' 66 beq __error_p @ yes, error 'p'
65 67
68#ifdef CONFIG_ARM_MPU
69 /* Calculate the size of a region covering just the kernel */
70 ldr r5, =PHYS_OFFSET @ Region start: PHYS_OFFSET
71 ldr r6, =(_end) @ Cover whole kernel
72 sub r6, r6, r5 @ Minimum size of region to map
73 clz r6, r6 @ Region size must be 2^N...
74 rsb r6, r6, #31 @ ...so round up region size
75 lsl r6, r6, #MPU_RSR_SZ @ Put size in right field
76 orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit
77 bl __setup_mpu
78#endif
66 ldr r13, =__mmap_switched @ address to jump to after 79 ldr r13, =__mmap_switched @ address to jump to after
67 @ initialising sctlr 80 @ initialising sctlr
68 adr lr, BSYM(1f) @ return (PIC) address 81 adr lr, BSYM(1f) @ return (PIC) address
@@ -147,4 +160,78 @@ __after_proc_init:
147ENDPROC(__after_proc_init) 160ENDPROC(__after_proc_init)
148 .ltorg 161 .ltorg
149 162
163#ifdef CONFIG_ARM_MPU
164
165
166/* Set which MPU region should be programmed */
167.macro set_region_nr tmp, rgnr
168 mov \tmp, \rgnr @ Use static region numbers
169 mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
170.endm
171
172/* Setup a single MPU region, either D or I side (D-side for unified) */
173.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE
174 mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
175 mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
176 mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
177.endm
178
179/*
180 * Setup the MPU and initial MPU Regions. We create the following regions:
181 * Region 0: Use this for probing the MPU details, so leave disabled.
182 * Region 1: Background region - covers the whole of RAM as strongly ordered
183 * Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6
184 *
185 * r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION
186*/
187
188ENTRY(__setup_mpu)
189
190 /* Probe for v7 PMSA compliance */
191 mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
192 and r0, r0, #(MMFR0_PMSA) @ PMSA field
193 teq r0, #(MMFR0_PMSAv7) @ PMSA v7
194 bne __error_p @ Fail: ARM_MPU on NOT v7 PMSA
195
196 /* Determine whether the D/I-side memory map is unified. We set the
197 * flags here and continue to use them for the rest of this function */
198 mrc p15, 0, r0, c0, c0, 4 @ MPUIR
199 ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
200 beq __error_p @ Fail: ARM_MPU and no MPU
201 tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
202
203 /* Setup second region first to free up r6 */
204 set_region_nr r0, #MPU_RAM_REGION
205 isb
206 /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
207 ldr r0, =PHYS_OFFSET @ RAM starts at PHYS_OFFSET
208 ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
209
210 setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled
211 beq 1f @ Memory-map not unified
212 setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled
2131: isb
214
215 /* First/background region */
216 set_region_nr r0, #MPU_BG_REGION
217 isb
218 /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
219 mov r0, #0 @ BG region starts at 0x0
220 ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
221 mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled
222
223 setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled
224 beq 2f @ Memory-map not unified
225 setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
2262: isb
227
228 /* Enable the MPU */
229 mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
230 bic r0, r0, #CR_BR @ Disable the 'default mem-map'
231 orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
232 mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
233 isb
234 mov pc,lr
235ENDPROC(__setup_mpu)
236#endif
150#include "head-common.S" 237#include "head-common.S"