[PATCH] ARM: mmu: set up vectors prior to full MMU setup
Ahmad Fatoum
a.fatoum at pengutronix.de
Fri Nov 28 09:22:05 PST 2025
From: Ahmad Fatoum <a.fatoum at barebox.org>
Interleaving vector table setup with zero page setup introduces an
unfortunate dependency: We need to call setup_pages after mapping the
SDRAM, so mapping the zero page as faulting is not overridden and we
need to do it before mapping the text area read-only, because the
vectors are relocated on ARM32.
Avoid this issue by setting up the vectors at core_initcall and only do
trap page setup during MMU init. This is already what is being done on
arm64.
Signed-off-by: Ahmad Fatoum <a.fatoum at barebox.org>
---
arch/arm/cpu/interrupts_32.c | 83 ++++++++++++++++++++++++++++++
arch/arm/cpu/mmu-common.c | 5 +-
arch/arm/cpu/mmu_32.c | 81 ++---------------------------
arch/arm/cpu/mmu_32.h | 2 +
arch/arm/include/asm/barebox-arm.h | 5 ++
5 files changed, 95 insertions(+), 81 deletions(-)
diff --git a/arch/arm/cpu/interrupts_32.c b/arch/arm/cpu/interrupts_32.c
index 185646e38195..0b88db10fe48 100644
--- a/arch/arm/cpu/interrupts_32.c
+++ b/arch/arm/cpu/interrupts_32.c
@@ -15,6 +15,8 @@
#include <asm/system_info.h>
#include <init.h>
+#include "mmu_32.h"
+
/* Avoid missing prototype warning, called from assembly */
void do_undefined_instruction (struct pt_regs *pt_regs);
void do_software_interrupt (struct pt_regs *pt_regs);
@@ -175,6 +177,87 @@ int data_abort_unmask(void)
return arm_data_abort_occurred != 0;
}
+static unsigned long arm_vbar = ~0;
+
+unsigned long arm_get_vector_table(void)
+{
+ return arm_vbar;
+}
+
+#define ARM_HIGH_VECTORS 0xffff0000
+#define ARM_LOW_VECTORS 0x0
+
+/**
+ * set_vector_table - let CPU use the vector table at given address
+ * @adr - The address of the vector table
+ *
+ * Depending on the CPU the possibilities differ. ARMv7 and later allow
+ * to map the vector table to arbitrary addresses. Other CPUs only allow
+ * vectors at 0xffff0000 or at 0x0.
+ */
+static int set_vector_table(unsigned long adr)
+{
+ u32 cr;
+
+ if (cpu_architecture() >= CPU_ARCH_ARMv7) {
+ set_vbar(adr);
+ } else if (adr == ARM_HIGH_VECTORS) {
+ cr = get_cr();
+ cr |= CR_V;
+ set_cr(cr);
+ cr = get_cr();
+ if (!(cr & CR_V))
+ return -EINVAL;
+ } else if (adr == ARM_LOW_VECTORS) {
+ cr = get_cr();
+ cr &= ~CR_V;
+ set_cr(cr);
+ cr = get_cr();
+ if (cr & CR_V)
+ return -EINVAL;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ pr_debug("Vectors are at 0x%08lx\n", adr);
+ arm_vbar = adr;
+
+ return 0;
+}
+
+static __maybe_unused int arm_init_vectors(void)
+{
+ /*
+ * First try to use the vectors where they actually are, works
+ * on ARMv7 and later.
+ */
+ if (!set_vector_table((unsigned long)__exceptions_start)) {
+ arm_fixup_vectors();
+ return 0;
+ }
+
+ /*
+ * Next try high vectors at 0xffff0000.
+ */
+ if (!set_vector_table(ARM_HIGH_VECTORS)) {
+ create_vector_table(ARM_HIGH_VECTORS);
+ return 0;
+ }
+
+ /*
+ * As a last resort use low vectors at 0x0. With this we can't
+ * set the zero page to faulting and can't catch NULL pointer
+ * exceptions.
+ */
+ set_vector_table(ARM_LOW_VECTORS);
+ create_vector_table(ARM_LOW_VECTORS);
+
+ return 0;
+}
+#ifdef CONFIG_MMU
+core_initcall(arm_init_vectors);
+#endif
+
#if IS_ENABLED(CONFIG_ARM_EXCEPTIONS_PBL)
void arm_pbl_init_exceptions(void)
{
diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
index 227ae4aa34e6..d193956ad359 100644
--- a/arch/arm/cpu/mmu-common.c
+++ b/arch/arm/cpu/mmu-common.c
@@ -157,11 +157,10 @@ static void mmu_remap_memory_banks(void)
remap_range_end_sans_text(pos, bank->res->end + 1, MAP_CACHED);
}
- /* Do this while interrupt vectors are still writable */
- setup_trap_pages();
-
remap_range((void *)code_start, code_size, MAP_CODE);
remap_range((void *)rodata_start, rodata_size, ARCH_MAP_CACHED_RO);
+
+ setup_trap_pages();
}
static int mmu_init(void)
diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
index 63c412873ec8..912d14e8cf82 100644
--- a/arch/arm/cpu/mmu_32.c
+++ b/arch/arm/cpu/mmu_32.c
@@ -489,9 +489,6 @@ void *map_io_sections(unsigned long phys, void *_start, size_t size)
return _start;
}
-#define ARM_HIGH_VECTORS 0xffff0000
-#define ARM_LOW_VECTORS 0x0
-
/**
* create_vector_table - create a vector table at given address
* @adr - The address where the vector table should be created
@@ -499,7 +496,7 @@ void *map_io_sections(unsigned long phys, void *_start, size_t size)
* After executing this function the vector table is found at the
* virtual address @adr.
*/
-static void create_vector_table(unsigned long adr)
+void create_vector_table(unsigned long adr)
{
struct resource *vectors_sdram;
void *vectors;
@@ -537,53 +534,6 @@ static void create_vector_table(unsigned long adr)
memcpy(vectors, __exceptions_start, __exceptions_stop - __exceptions_start);
}
-/**
- * set_vector_table - let CPU use the vector table at given address
- * @adr - The address of the vector table
- *
- * Depending on the CPU the possibilities differ. ARMv7 and later allow
- * to map the vector table to arbitrary addresses. Other CPUs only allow
- * vectors at 0xffff0000 or at 0x0.
- */
-static int set_vector_table(unsigned long adr)
-{
- u32 cr;
-
- if (cpu_architecture() >= CPU_ARCH_ARMv7) {
- pr_debug("Vectors are at 0x%08lx\n", adr);
- set_vbar(adr);
- return 0;
- }
-
- if (adr == ARM_HIGH_VECTORS) {
- cr = get_cr();
- cr |= CR_V;
- set_cr(cr);
- cr = get_cr();
- if (cr & CR_V) {
- pr_debug("Vectors are at 0x%08lx\n", adr);
- return 0;
- } else {
- return -EINVAL;
- }
- }
-
- if (adr == ARM_LOW_VECTORS) {
- cr = get_cr();
- cr &= ~CR_V;
- set_cr(cr);
- cr = get_cr();
- if (cr & CR_V) {
- return -EINVAL;
- } else {
- pr_debug("Vectors are at 0x%08lx\n", adr);
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
static void create_zero_page(void)
{
/*
@@ -616,34 +566,9 @@ static void create_guard_page(void)
*/
void setup_trap_pages(void)
{
+ if (arm_get_vector_table() != 0x0)
+ create_zero_page();
create_guard_page();
-
- /*
- * First try to use the vectors where they actually are, works
- * on ARMv7 and later.
- */
- if (!set_vector_table((unsigned long)__exceptions_start)) {
- arm_fixup_vectors();
- create_zero_page();
- return;
- }
-
- /*
- * Next try high vectors at 0xffff0000.
- */
- if (!set_vector_table(ARM_HIGH_VECTORS)) {
- create_zero_page();
- create_vector_table(ARM_HIGH_VECTORS);
- return;
- }
-
- /*
- * As a last resort use low vectors at 0x0. With this we can't
- * set the zero page to faulting and can't catch NULL pointer
- * exceptions.
- */
- set_vector_table(ARM_LOW_VECTORS);
- create_vector_table(ARM_LOW_VECTORS);
}
/*
diff --git a/arch/arm/cpu/mmu_32.h b/arch/arm/cpu/mmu_32.h
index 7a58a819f08a..195e677bad2e 100644
--- a/arch/arm/cpu/mmu_32.h
+++ b/arch/arm/cpu/mmu_32.h
@@ -71,4 +71,6 @@ static inline unsigned long attrs_uncached_mem(void)
return flags;
}
+void create_vector_table(unsigned long adr);
+
#endif /* __ARM_MMU_H */
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index 11be8b85837e..e1d89d5684d3 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -46,10 +46,15 @@ unsigned long arm_mem_endmem_get(void);
#ifdef CONFIG_ARM_EXCEPTIONS
void arm_fixup_vectors(void);
+ulong arm_get_vector_table(void);
#else
static inline void arm_fixup_vectors(void)
{
}
+static inline ulong arm_get_vector_table(void)
+{
+ return ~0;
+}
#endif
#if IS_ENABLED(CONFIG_ARM_EXCEPTIONS_PBL)
--
2.47.3
More information about the barebox
mailing list