aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Murzin <vladimir.murzin@arm.com>2017-10-16 07:57:48 -0400
committerRussell King <rmk+kernel@armlinux.org.uk>2017-10-23 11:59:15 -0400
commit9fcb01a9f54c28062a73a545c29137a4cc104c72 (patch)
tree7cebf0b0de05a73132ef66ae9c1671206a58be77
parent89a6dafe136952b3409d5e4ed04cb891e806e924 (diff)
ARM: 8711/1: V7M: Add support for MPU to M-class
This patch makes it possible to use MPU with v7M cores. Tested-by: Szemző András <sza@esh.hu> Tested-by: Alexandre TORGUE <alexandre.torgue@st.com> Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm/Kconfig-nommu4
-rw-r--r--arch/arm/include/asm/cputype.h10
-rw-r--r--arch/arm/include/asm/v7m.h10
-rw-r--r--arch/arm/kernel/head-nommu.S56
-rw-r--r--arch/arm/mm/pmsa-v7.c53
5 files changed, 113 insertions, 20 deletions
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
index 6d18395da24d..930e000489a8 100644
--- a/arch/arm/Kconfig-nommu
+++ b/arch/arm/Kconfig-nommu
@@ -52,8 +52,8 @@ config REMAP_VECTORS_TO_RAM
52 52
53config ARM_MPU 53config ARM_MPU
54 bool 'Use the ARM v7 PMSA Compliant MPU' 54 bool 'Use the ARM v7 PMSA Compliant MPU'
55 depends on !XIP_KERNEL && CPU_V7 55 depends on !XIP_KERNEL && (CPU_V7 || CPU_V7M)
56 default y 56 default y if CPU_V7
57 help 57 help
58 Some ARM systems without an MMU have instead a Memory Protection 58 Some ARM systems without an MMU have instead a Memory Protection
59 Unit (MPU) that defines the type and permissions for regions of 59 Unit (MPU) that defines the type and permissions for regions of
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index b62eaeb147aa..abaac5e07b80 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -173,6 +173,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
173 return read_cpuid(CPUID_CACHETYPE); 173 return read_cpuid(CPUID_CACHETYPE);
174} 174}
175 175
176static inline unsigned int __attribute_const__ read_cpuid_mputype(void)
177{
178 return read_cpuid(CPUID_MPUIR);
179}
180
176#elif defined(CONFIG_CPU_V7M) 181#elif defined(CONFIG_CPU_V7M)
177 182
178static inline unsigned int __attribute_const__ read_cpuid_id(void) 183static inline unsigned int __attribute_const__ read_cpuid_id(void)
@@ -185,6 +190,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
185 return readl(BASEADDR_V7M_SCB + V7M_SCB_CTR); 190 return readl(BASEADDR_V7M_SCB + V7M_SCB_CTR);
186} 191}
187 192
193static inline unsigned int __attribute_const__ read_cpuid_mputype(void)
194{
195 return readl(BASEADDR_V7M_SCB + MPU_TYPE);
196}
197
188#else /* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */ 198#else /* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */
189 199
190static inline unsigned int __attribute_const__ read_cpuid_id(void) 200static inline unsigned int __attribute_const__ read_cpuid_id(void)
diff --git a/arch/arm/include/asm/v7m.h b/arch/arm/include/asm/v7m.h
index 1fd775c1bc5d..5de776c81382 100644
--- a/arch/arm/include/asm/v7m.h
+++ b/arch/arm/include/asm/v7m.h
@@ -57,6 +57,16 @@
57#define V7M_SCB_CCSIDR 0x80 /* Cache size ID register */ 57#define V7M_SCB_CCSIDR 0x80 /* Cache size ID register */
58#define V7M_SCB_CSSELR 0x84 /* Cache size selection register */ 58#define V7M_SCB_CSSELR 0x84 /* Cache size selection register */
59 59
60/* Memory-mapped MPU registers for M-class */
61#define MPU_TYPE 0x90
62#define MPU_CTRL 0x94
63#define MPU_CTRL_ENABLE 1
64#define MPU_CTRL_PRIVDEFENA (1 << 2)
65
66#define MPU_RNR 0x98
67#define MPU_RBAR 0x9c
68#define MPU_RASR 0xa0
69
60/* Cache opeartions */ 70/* Cache opeartions */
61#define V7M_SCB_ICIALLU 0x250 /* I-cache invalidate all to PoU */ 71#define V7M_SCB_ICIALLU 0x250 /* I-cache invalidate all to PoU */
62#define V7M_SCB_ICIMVAU 0x258 /* I-cache invalidate by MVA to PoU */ 72#define V7M_SCB_ICIMVAU 0x258 /* I-cache invalidate by MVA to PoU */
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 5f90a5fb7022..0d64b8ba7e9c 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -176,19 +176,33 @@ ENDPROC(__after_proc_init)
176#ifdef CONFIG_ARM_MPU 176#ifdef CONFIG_ARM_MPU
177 177
178 178
179#ifndef CONFIG_CPU_V7M
179/* Set which MPU region should be programmed */ 180/* Set which MPU region should be programmed */
180.macro set_region_nr tmp, rgnr 181.macro set_region_nr tmp, rgnr, unused
181 mov \tmp, \rgnr @ Use static region numbers 182 mov \tmp, \rgnr @ Use static region numbers
182 mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR 183 mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
183.endm 184.endm
184 185
185/* Setup a single MPU region, either D or I side (D-side for unified) */ 186/* Setup a single MPU region, either D or I side (D-side for unified) */
186.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE 187.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE, unused
187 mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR 188 mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
188 mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR 189 mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
189 mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR 190 mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
190.endm 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
191 204
205#endif
192/* 206/*
193 * Setup the MPU and initial MPU Regions. We create the following regions: 207 * Setup the MPU and initial MPU Regions. We create the following regions:
194 * Region 0: Use this for probing the MPU details, so leave disabled. 208 * Region 0: Use this for probing the MPU details, so leave disabled.
@@ -202,48 +216,58 @@ ENDPROC(__after_proc_init)
202ENTRY(__setup_mpu) 216ENTRY(__setup_mpu)
203 217
204 /* Probe for v7 PMSA compliance */ 218 /* Probe for v7 PMSA compliance */
205 mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0 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])
206 and r0, r0, #(MMFR0_PMSA) @ PMSA field 224 and r0, r0, #(MMFR0_PMSA) @ PMSA field
207 teq r0, #(MMFR0_PMSAv7) @ PMSA v7 225 teq r0, #(MMFR0_PMSAv7) @ PMSA v7
208 bxne lr 226 bxne lr
209 227
210 /* Determine whether the D/I-side memory map is unified. We set the 228 /* Determine whether the D/I-side memory map is unified. We set the
211 * flags here and continue to use them for the rest of this function */ 229 * flags here and continue to use them for the rest of this function */
212 mrc p15, 0, r0, c0, c0, 4 @ MPUIR 230AR_CLASS(mrc p15, 0, r0, c0, c0, 4) @ MPUIR
231M_CLASS(ldr r0, [r12, #MPU_TYPE])
213 ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU 232 ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
214 bxeq lr 233 bxeq lr
215 tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified 234 tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
216 235
217 /* Setup second region first to free up r6 */ 236 /* Setup second region first to free up r6 */
218 set_region_nr r0, #MPU_RAM_REGION 237 set_region_nr r0, #MPU_RAM_REGION, r12
219 isb 238 isb
220 /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */ 239 /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
221 ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET 240 ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET
222 ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL) 241 ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
223 242
224 setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled 243 setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ PHYS_OFFSET, shared, enabled
225 beq 1f @ Memory-map not unified 244 beq 1f @ Memory-map not unified
226 setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled 245 setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ PHYS_OFFSET, shared, enabled
2271: isb 2461: isb
228 247
229 /* First/background region */ 248 /* First/background region */
230 set_region_nr r0, #MPU_BG_REGION 249 set_region_nr r0, #MPU_BG_REGION, r12
231 isb 250 isb
232 /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */ 251 /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
233 mov r0, #0 @ BG region starts at 0x0 252 mov r0, #0 @ BG region starts at 0x0
234 ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA) 253 ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
235 mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled 254 mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled
236 255
237 setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled 256 setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ 0x0, BG region, enabled
238 beq 2f @ Memory-map not unified 257 beq 2f @ Memory-map not unified
239 setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled 258 setup_region r0, r5, r6, MPU_INSTR_SIDE r12 @ 0x0, BG region, enabled
2402: isb 2592: isb
241 260
242 /* Enable the MPU */ 261 /* Enable the MPU */
243 mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR 262AR_CLASS(mrc p15, 0, r0, c1, c0, 0) @ Read SCTLR
244 bic r0, r0, #CR_BR @ Disable the 'default mem-map' 263AR_CLASS(bic r0, r0, #CR_BR) @ Disable the 'default mem-map'
245 orr r0, r0, #CR_M @ Set SCTRL.M (MPU on) 264AR_CLASS(orr r0, r0, #CR_M) @ Set SCTRL.M (MPU on)
246 mcr p15, 0, r0, c1, c0, 0 @ Enable MPU 265AR_CLASS(mcr p15, 0, r0, c1, c0, 0) @ Enable MPU
266
267M_CLASS(ldr r0, [r12, #MPU_CTRL])
268M_CLASS(bic r0, #MPU_CTRL_PRIVDEFENA)
269M_CLASS(orr r0, #MPU_CTRL_ENABLE)
270M_CLASS(str r0, [r12, #MPU_CTRL])
247 isb 271 isb
248 272
249 ret lr 273 ret lr
diff --git a/arch/arm/mm/pmsa-v7.c b/arch/arm/mm/pmsa-v7.c
index cd798271a78d..06e2a853cab9 100644
--- a/arch/arm/mm/pmsa-v7.c
+++ b/arch/arm/mm/pmsa-v7.c
@@ -15,6 +15,8 @@
15static unsigned int __initdata mpu_min_region_order; 15static unsigned int __initdata mpu_min_region_order;
16static unsigned int __initdata mpu_max_regions; 16static unsigned int __initdata mpu_max_regions;
17 17
18#ifndef CONFIG_CPU_V7M
19
18#define DRBAR __ACCESS_CP15(c6, 0, c1, 0) 20#define DRBAR __ACCESS_CP15(c6, 0, c1, 0)
19#define IRBAR __ACCESS_CP15(c6, 0, c1, 1) 21#define IRBAR __ACCESS_CP15(c6, 0, c1, 1)
20#define DRSR __ACCESS_CP15(c6, 0, c1, 2) 22#define DRSR __ACCESS_CP15(c6, 0, c1, 2)
@@ -78,6 +80,51 @@ static inline u32 irbar_read(void)
78 return read_sysreg(IRBAR); 80 return read_sysreg(IRBAR);
79} 81}
80 82
83#else
84
85static inline void rgnr_write(u32 v)
86{
87 writel_relaxed(v, BASEADDR_V7M_SCB + MPU_RNR);
88}
89
90/* Data-side / unified region attributes */
91
92/* Region access control register */
93static inline void dracr_write(u32 v)
94{
95 u32 rsr = readl_relaxed(BASEADDR_V7M_SCB + MPU_RASR) & GENMASK(15, 0);
96
97 writel_relaxed((v << 16) | rsr, BASEADDR_V7M_SCB + MPU_RASR);
98}
99
100/* Region size register */
101static inline void drsr_write(u32 v)
102{
103 u32 racr = readl_relaxed(BASEADDR_V7M_SCB + MPU_RASR) & GENMASK(31, 16);
104
105 writel_relaxed(v | racr, BASEADDR_V7M_SCB + MPU_RASR);
106}
107
108/* Region base address register */
109static inline void drbar_write(u32 v)
110{
111 writel_relaxed(v, BASEADDR_V7M_SCB + MPU_RBAR);
112}
113
114static inline u32 drbar_read(void)
115{
116 return readl_relaxed(BASEADDR_V7M_SCB + MPU_RBAR);
117}
118
119/* ARMv7-M only supports a unified MPU, so I-side operations are nop */
120
121static inline void iracr_write(u32 v) {}
122static inline void irsr_write(u32 v) {}
123static inline void irbar_write(u32 v) {}
124static inline unsigned long irbar_read(void) {return 0;}
125
126#endif
127
81static int __init mpu_present(void) 128static int __init mpu_present(void)
82{ 129{
83 return ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7); 130 return ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7);
@@ -166,7 +213,7 @@ static int __init __mpu_max_regions(void)
166 */ 213 */
167 u32 dregions, iregions, mpuir; 214 u32 dregions, iregions, mpuir;
168 215
169 mpuir = read_cpuid(CPUID_MPUIR); 216 mpuir = read_cpuid_mputype();
170 217
171 dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION; 218 dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;
172 219
@@ -181,7 +228,7 @@ static int __init __mpu_max_regions(void)
181static int __init mpu_iside_independent(void) 228static int __init mpu_iside_independent(void)
182{ 229{
183 /* MPUIR.nU specifies whether there is *not* a unified memory map */ 230 /* MPUIR.nU specifies whether there is *not* a unified memory map */
184 return read_cpuid(CPUID_MPUIR) & MPUIR_nU; 231 return read_cpuid_mputype() & MPUIR_nU;
185} 232}
186 233
187static int __init __mpu_min_region_order(void) 234static int __init __mpu_min_region_order(void)
@@ -284,9 +331,11 @@ void __init mpu_setup(void)
284 MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL); 331 MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL);
285 332
286 /* Vectors */ 333 /* Vectors */
334#ifndef CONFIG_CPU_V7M
287 err |= mpu_setup_region(region++, vectors_base, 335 err |= mpu_setup_region(region++, vectors_base,
288 ilog2(2 * PAGE_SIZE), 336 ilog2(2 * PAGE_SIZE),
289 MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL); 337 MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL);
338#endif
290 if (err) { 339 if (err) {
291 panic("MPU region initialization failure! %d", err); 340 panic("MPU region initialization failure! %d", err);
292 } else { 341 } else {