aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/mpu.h1
-rw-r--r--arch/arm/kernel/head-nommu.S16
-rw-r--r--arch/arm/kernel/signal.c9
3 files changed, 24 insertions, 2 deletions
diff --git a/arch/arm/include/asm/mpu.h b/arch/arm/include/asm/mpu.h
index 001483465aa4..c3247cc2fe08 100644
--- a/arch/arm/include/asm/mpu.h
+++ b/arch/arm/include/asm/mpu.h
@@ -46,6 +46,7 @@
#define MPU_PROBE_REGION 0
#define MPU_BG_REGION 1
#define MPU_RAM_REGION 2
+#define MPU_VECTORS_REGION 3
/* Maximum number of regions Linux is interested in */
#define MPU_MAX_REGIONS 16
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 13741d004de5..75f14cc3e073 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -22,6 +22,7 @@
#include <asm/thread_info.h>
#include <asm/v7m.h>
#include <asm/mpu.h>
+#include <asm/page.h>
/*
* Kernel startup entry point.
@@ -188,6 +189,7 @@ ENDPROC(__after_proc_init)
* Region 0: Use this for probing the MPU details, so leave disabled.
* Region 1: Background region - covers the whole of RAM as strongly ordered
* Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6
+ * Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page
*
* r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION
*/
@@ -232,6 +234,20 @@ ENTRY(__setup_mpu)
setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
2: isb
+ /* Vectors region */
+ set_region_nr r0, #MPU_VECTORS_REGION
+ isb
+ /* Shared, inaccessible to PL0, rw PL1 */
+ mov r0, #CONFIG_VECTORS_BASE @ Cover from VECTORS_BASE
+ ldr r5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL)
+ /* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */
+ mov r6, #(((PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN)
+
+ setup_region r0, r5, r6, MPU_DATA_SIDE @ VECTORS_BASE, PL0 NA, enabled
+ beq 3f @ Memory-map not unified
+ setup_region r0, r5, r6, MPU_INSTR_SIDE @ VECTORS_BASE, PL0 NA, enabled
+3: isb
+
/* Enable the MPU */
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
bic r0, r0, #CR_BR @ Disable the 'default mem-map'
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 296786bdbb73..1c16c35c271a 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -392,14 +392,19 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
idx += 3;
+ /*
+ * Put the sigreturn code on the stack no matter which return
+ * mechanism we use in order to remain ABI compliant
+ */
if (__put_user(sigreturn_codes[idx], rc) ||
__put_user(sigreturn_codes[idx+1], rc+1))
return 1;
- if (cpsr & MODE32_BIT) {
+ if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) {
/*
* 32-bit code can use the new high-page
- * signal return code support.
+ * signal return code support except when the MPU has
+ * protected the vectors page from PL0
*/
retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
} else {