[PATCH master 8/8] ARM: mmu: fix hang reserving memory after text area
Ahmad Fatoum
a.fatoum at barebox.org
Tue Aug 5 10:45:41 PDT 2025
The loop in mmu_remap_memory_banks first looks at reserved memory
regions and then maps everything eXecute Never up to the start of the
region. If the region happens to be in the same bank as the text area
and it comes after it, this means the text area is temporarily mapped
eXecute Never, while barebox is running from it, which results in a
hang.
Fix this by remapping only after both reserved memory regions and text
area have been considered.
Fixes: 5916385fae83 ("ARM: MMU: map text segment ro and data segments execute never")
Fixes: 03dfb3f142fb ("ARM: MMU64: map text segment ro and data segments execute never")
Signed-off-by: Ahmad Fatoum <a.fatoum at barebox.org>
---
arch/arm/cpu/mmu-common.c | 51 ++++++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 14 deletions(-)
diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
index 575fb32282d1..1de20d931876 100644
--- a/arch/arm/cpu/mmu-common.c
+++ b/arch/arm/cpu/mmu-common.c
@@ -70,21 +70,50 @@ void zero_page_faulting(void)
remap_range(0x0, PAGE_SIZE, MAP_FAULT);
}
+/**
+ * remap_range_end - remap a range identified by [start, end)
+ *
+ * @start: start of the range
+ * @end: end of the first range (exclusive)
+ * @map_type: mapping type to apply
+ */
+static inline void remap_range_end(unsigned long start, unsigned long end,
+ unsigned map_type)
+{
+ remap_range((void *)start, end - start, map_type);
+}
+
+static inline void remap_range_end_sans_text(unsigned long start, unsigned long end,
+ unsigned map_type)
+{
+ unsigned long text_start = (unsigned long)&_stext;
+ unsigned long text_end = (unsigned long)&_etext;
+
+ if (region_overlap_end_exclusive(start, end, text_start, text_end)) {
+ remap_range_end(start, text_start, MAP_CACHED);
+ /* skip barebox segments here, will be mapped later */
+ start = text_end;
+ }
+
+ remap_range_end(start, end, MAP_CACHED);
+}
+
static void mmu_remap_memory_banks(void)
{
struct memory_bank *bank;
- unsigned long text_start = (unsigned long)&_stext;
- unsigned long code_start = text_start;
+ unsigned long code_start = (unsigned long)&_stext;
unsigned long code_size = (unsigned long)&__start_rodata - (unsigned long)&_stext;
- unsigned long text_size = (unsigned long)&_etext - text_start;
unsigned long rodata_start = (unsigned long)&__start_rodata;
unsigned long rodata_size = (unsigned long)&__end_rodata - rodata_start;
/*
* Early mmu init will have mapped everything but the initial memory area
* (excluding final OPTEE_SIZE bytes) uncached. We have now discovered
- * all memory banks, so let's map all pages, excluding reserved memory areas,
- * cacheable and executable.
+ * all memory banks, so let's map all pages, excluding reserved memory areas
+ * and barebox text area cacheable.
+ *
+ * This code will become much less complex once we switch over to using
+ * CONFIG_MEMORY_ATTRIBUTES for MMU as well.
*/
for_each_memory_bank(bank) {
struct resource *rsv;
@@ -94,20 +123,14 @@ static void mmu_remap_memory_banks(void)
/* Skip reserved regions */
for_each_reserved_region(bank, rsv) {
- remap_range((void *)pos, rsv->start - pos, MAP_CACHED);
+ remap_range_end_sans_text(pos, rsv->start, MAP_CACHED);
pos = rsv->end + 1;
}
- if (region_overlap_size(pos, bank->start + bank->size - pos,
- text_start, text_size)) {
- remap_range((void *)pos, text_start - pos, MAP_CACHED);
- /* skip barebox segments here, will be mapped below */
- pos = text_start + text_size;
- }
-
- remap_range((void *)pos, bank->start + bank->size - pos, MAP_CACHED);
+ remap_range_end_sans_text(pos, bank->start + bank->size, MAP_CACHED);
}
+ /* Do this while interrupt vectors are still writable */
setup_trap_pages();
remap_range((void *)code_start, code_size, MAP_CODE);
--
2.39.5
More information about the barebox
mailing list