Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0995c08 authored by Vladimir Murzin's avatar Vladimir Murzin Committed by Russell King
Browse files

ARM: 8708/1: NOMMU: Rework MPU to be mostly done in C



Currently, there are several issues with how MPU is setup:

 1. We won't boot if MPU is missing
 2. We won't boot if use XIP
 3. Further extension of MPU setup requires asm skills

The 1st point can be relaxed, so we can continue with boot CPU even if
MPU is missed and fail boot for secondaries only. To address the 2nd
point we could create region covering CONFIG_XIP_PHYS_ADDR - _end and
that might work for the first stage of MPU enable, but due to MPU's
alignment requirement we could cover too much, IOW we need more
flexibility in how we're partitioning memory regions... and it'd be
hardly possible to archive because of the 3rd point.

This patch is trying to address 1st and 3rd issues and paves the path
for 2nd and further improvements.

The most visible change introduced with this patch is that we start
using mpu_rgn_info array (as it was supposed?), so change in MPU setup
done by boot CPU is recorded there and feed to secondaries. It
allows us to keep minimal region setup for boot CPU and do the rest in
C. Since we start programming MPU regions in C evaluation of MPU
constrains (number of regions supported and minimal region order) can
be done once, which in turn open possibility to free-up "probe"
region early.

Tested-by: default avatarSzemző András <sza@esh.hu>
Tested-by: default avatarAlexandre TORGUE <alexandre.torgue@st.com>
Tested-by: default avatarBenjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: default avatarVladimir Murzin <vladimir.murzin@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
parent e8b47e12
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ struct mpu_rgn {
};

struct mpu_rgn_info {
	u32 mpuir;
	unsigned int used;
	struct mpu_rgn rgns[MPU_MAX_REGIONS];
};
extern struct mpu_rgn_info mpu_rgn_info;
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ asmlinkage void secondary_start_kernel(void);
 */
struct secondary_data {
	union {
		unsigned long mpu_rgn_szr;
		struct mpu_rgn_info *mpu_rgn_info;
		u64 pgdir;
	};
	unsigned long swapper_pg_dir;
+11 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <asm/mach/arch.h>
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/mpu.h>
#include <asm/procinfo.h>
#include <asm/suspend.h>
#include <asm/vdso_datapage.h>
@@ -186,6 +187,16 @@ int main(void)
  BLANK();
#ifdef CONFIG_VDSO
  DEFINE(VDSO_DATA_SIZE,	sizeof(union vdso_data_store));
#endif
  BLANK();
#ifdef CONFIG_ARM_MPU
  DEFINE(MPU_RNG_INFO_RNGS,	offsetof(struct mpu_rgn_info, rgns));
  DEFINE(MPU_RNG_INFO_USED,	offsetof(struct mpu_rgn_info, used));

  DEFINE(MPU_RNG_SIZE,		sizeof(struct mpu_rgn));
  DEFINE(MPU_RGN_DRBAR,		offsetof(struct mpu_rgn, drbar));
  DEFINE(MPU_RGN_DRSR,		offsetof(struct mpu_rgn, drsr));
  DEFINE(MPU_RGN_DRACR,		offsetof(struct mpu_rgn, dracr));
#endif
  return 0; 
}
+62 −18
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 */
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/errno.h>

#include <asm/assembler.h>
#include <asm/ptrace.h>
@@ -110,8 +111,8 @@ ENTRY(secondary_startup)

#ifdef CONFIG_ARM_MPU
	/* Use MPU region info supplied by __cpu_up */
	ldr	r6, [r7]			@ get secondary_data.mpu_szr
	bl      __setup_mpu			@ Initialize the MPU
	ldr	r6, [r7]			@ get secondary_data.mpu_rgn_info
	bl      __secondary_setup_mpu		@ Initialize the MPU
#endif

	badr	lr, 1f				@ return (PIC) address
@@ -204,13 +205,13 @@ ENTRY(__setup_mpu)
	mrc	p15, 0, r0, c0, c1, 4		@ Read ID_MMFR0
	and	r0, r0, #(MMFR0_PMSA)		@ PMSA field
	teq	r0, #(MMFR0_PMSAv7)		@ PMSA v7
	bne	__error_p			@ Fail: ARM_MPU on NOT v7 PMSA
	bxne	lr

	/* Determine whether the D/I-side memory map is unified. We set the
	 * flags here and continue to use them for the rest of this function */
	mrc	p15, 0, r0, c0, c0, 4		@ MPUIR
	ands	r5, r0, #MPUIR_DREGION_SZMASK	@ 0 size d region => No MPU
	beq	__error_p			@ Fail: ARM_MPU and no MPU
	bxeq	lr
	tst	r0, #MPUIR_nU			@ MPUIR_nU = 0 for unified

	/* Setup second region first to free up r6 */
@@ -238,19 +239,59 @@ 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
	/* Enable the MPU */
	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
	bic	r0, r0, #CR_BR			@ Disable the 'default mem-map'
	orr	r0, r0, #CR_M			@ Set SCTRL.M (MPU on)
	mcr	p15, 0, r0, c1, c0, 0		@ Enable MPU
	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, #(((2 * 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
	ret	lr
ENDPROC(__setup_mpu)

#ifdef CONFIG_SMP
/*
 * r6: pointer at mpu_rgn_info
 */

ENTRY(__secondary_setup_mpu)
	/* Probe for v7 PMSA compliance */
	mrc	p15, 0, r0, c0, c1, 4		@ Read ID_MMFR0
	and	r0, r0, #(MMFR0_PMSA)		@ PMSA field
	teq	r0, #(MMFR0_PMSAv7)		@ PMSA v7
	bne	__error_p

	/* Determine whether the D/I-side memory map is unified. We set the
	 * flags here and continue to use them for the rest of this function */
	mrc	p15, 0, r0, c0, c0, 4		@ MPUIR
	ands	r5, r0, #MPUIR_DREGION_SZMASK	@ 0 size d region => No MPU
	beq	__error_p

	ldr	r4, [r6, #MPU_RNG_INFO_USED]
	mov	r5, #MPU_RNG_SIZE
	add	r3, r6, #MPU_RNG_INFO_RNGS
	mla	r3, r4, r5, r3

1:
	tst	r0, #MPUIR_nU			@ MPUIR_nU = 0 for unified
	sub	r3, r3, #MPU_RNG_SIZE
	sub	r4, r4, #1

	set_region_nr r0, r4
	isb

	ldr	r0, [r3, #MPU_RGN_DRBAR]
	ldr	r6, [r3, #MPU_RGN_DRSR]
	ldr	r5, [r3, #MPU_RGN_DRACR]

	setup_region r0, r5, r6, MPU_DATA_SIDE
	beq	2f
	setup_region r0, r5, r6, MPU_INSTR_SIDE
2:	isb

	mrc	p15, 0, r0, c0, c0, 4		@ Reevaluate the MPUIR
	cmp	r4, #0
	bgt	1b

	/* Enable the MPU */
	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
@@ -258,7 +299,10 @@ ENTRY(__setup_mpu)
	orr	r0, r0, #CR_M			@ Set SCTRL.M (MPU on)
	mcr	p15, 0, r0, c1, c0, 0		@ Enable MPU
	isb

	ret	lr
ENDPROC(__setup_mpu)
#endif
ENDPROC(__secondary_setup_mpu)

#endif /* CONFIG_SMP */
#endif /* CONFIG_ARM_MPU */
#include "head-common.S"
+1 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
	 */
	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
#ifdef CONFIG_ARM_MPU
	secondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr;
	secondary_data.mpu_rgn_info = &mpu_rgn_info;
#endif

#ifdef CONFIG_MMU
Loading