summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2021-03-24 09:23:03 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-03-29 09:56:52 +0200
commit8384ab79e06c4b618db2a915e3e1a5a50e06cecc (patch)
tree5d5ce4dab76545cdccf4a30f7bb1b280130014a1
parentfef19e17f651a7f4b6063a76c506a67cabfe4a69 (diff)
downloadbarebox-8384ab79e06c4b618db2a915e3e1a5a50e06cecc.tar.gz
barebox-8384ab79e06c4b618db2a915e3e1a5a50e06cecc.tar.xz
RISC-V: board-dt-2nd: ensure FDT doesn't overlap with early mem regions
RISC-V PBL code currently reserves the last 2M of the memory for firmware and places the stack before that. This serves virt, as qemu places the FDT here, but negatively impacts normal targets with embedded device tree as it increases fragmentation. Add code to the generic DT entry point that cuts of a number of MiB from the end of RAM, so the PBL arrives at a stack top that doesn't overlap FDT. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/riscv/boot/board-dt-2nd.c20
-rw-r--r--arch/riscv/boot/uncompress.c5
-rw-r--r--arch/riscv/include/asm/sections.h9
3 files changed, 28 insertions, 6 deletions
diff --git a/arch/riscv/boot/board-dt-2nd.c b/arch/riscv/boot/board-dt-2nd.c
index 25fa7d4f2b..be28ea23cd 100644
--- a/arch/riscv/boot/board-dt-2nd.c
+++ b/arch/riscv/boot/board-dt-2nd.c
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
#include <common.h>
+#include <asm/sections.h>
+#include <linux/sizes.h>
#include <debug_ll.h>
#include <pbl.h>
+#include <fdt.h>
#if __riscv_xlen == 64
#define IMAGE_LOAD_OFFSET 0x200000 /* Image load offset(2MB) from start of RAM */
@@ -21,8 +24,8 @@
ENTRY_FUNCTION(start_dt_2nd, a0, _fdt, a2)
{
- unsigned long membase, memsize;
- void *fdt = (void *)_fdt;
+ unsigned long membase, memsize, endmem, endfdt, uncompressed_len;
+ struct fdt_header *fdt = (void *)_fdt;
if (!fdt)
hang();
@@ -31,6 +34,19 @@ ENTRY_FUNCTION(start_dt_2nd, a0, _fdt, a2)
setup_c();
fdt_find_mem(fdt, &membase, &memsize);
+ endmem = membase + memsize;
+ endfdt = _fdt + be32_to_cpu(fdt->totalsize);
+
+ /*
+ * QEMU likes to place the FDT at the end of RAM, where barebox
+ * would normally extract itself to. Accommodate this by moving
+ * memory end, so it doesn't overlap FDT
+ */
+ uncompressed_len = input_data_len() + MAX_BSS_SIZE;
+
+ if (riscv_mem_barebox_image(membase, endmem, uncompressed_len) < endfdt &&
+ _fdt < riscv_mem_stack_top(membase, endmem))
+ memsize = ALIGN_DOWN(_fdt - membase, SZ_1M);
barebox_riscv_entry(membase, memsize, fdt);
}
diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c
index cf268bece1..411cefb0e3 100644
--- a/arch/riscv/boot/uncompress.c
+++ b/arch/riscv/boot/uncompress.c
@@ -22,9 +22,6 @@
unsigned long free_mem_ptr;
unsigned long free_mem_end_ptr;
-extern unsigned char input_data[];
-extern unsigned char input_data_end[];
-
void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
void *fdt)
{
@@ -49,7 +46,7 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
relocate_to_adr(membase);
pg_len = pg_end - pg_start;
- uncompressed_len = get_unaligned((const u32 *)(pg_start + pg_len - 4));
+ uncompressed_len = input_data_len();
barebox_base = riscv_mem_barebox_image(membase, endmem,
uncompressed_len + MAX_BSS_SIZE);
diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
index b5fbba8f16..725fd8db47 100644
--- a/arch/riscv/include/asm/sections.h
+++ b/arch/riscv/include/asm/sections.h
@@ -5,12 +5,21 @@
#ifndef __ASSEMBLY__
#include <asm-generic/sections.h>
#include <linux/types.h>
+#include <asm/unaligned.h>
extern char __rel_dyn_start[];
extern char __rel_dyn_end[];
extern char __dynsym_start[];
extern char __dynsym_end[];
+extern char input_data[];
+extern char input_data_end[];
+
+static inline unsigned int input_data_len(void)
+{
+ return get_unaligned((const u32 *)(input_data_end - 4));
+}
+
#endif
#endif /* __ASM_SECTIONS_H */