mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH] ARM: mmu: set up vectors prior to full MMU setup
Date: Fri, 28 Nov 2025 18:22:05 +0100	[thread overview]
Message-ID: <20251128172206.36551-1-a.fatoum@pengutronix.de> (raw)

From: Ahmad Fatoum <a.fatoum@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@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




             reply	other threads:[~2025-11-28 17:22 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-28 17:22 Ahmad Fatoum [this message]
2025-12-01 11:04 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251128172206.36551-1-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox