mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/4] MIPS: add relocation support
@ 2019-03-08 10:58 Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 1/4] MIPS: relocation: pass ram size to pbl_main_entry Oleksij Rempel
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Oleksij Rempel @ 2019-03-08 10:58 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

with this patches, same main binary version of barebox xan be reused
on different board with different RAM size.
The barebox will find best possible location for it self depending
on RAM size information provided by PBL.

changes v2:
- don't remove no-pic flag to avoid confusion.
- don't set ggdb flag for barebox tools.

Oleksij Rempel (4):
  MIPS: relocation: pass ram size to pbl_main_entry
  MIPS: relocation: add relocation support
  MIPS: relocation: do not use configurable memory layout
  MIPS: remove request_sdram_region "fdt"

 arch/mips/Kconfig                             |  19 +-
 arch/mips/Makefile                            |   9 +-
 arch/mips/boards/8devices-lima/lowlevel.S     |   3 +-
 arch/mips/boards/black-swift/lowlevel.S       |   3 +-
 arch/mips/boards/dlink-dir-320/lowlevel.S     |   3 +-
 .../boards/dptechnics-dpt-module/lowlevel.S   |   3 +-
 arch/mips/boards/img-ci20/lowlevel.S          |   3 +-
 arch/mips/boards/loongson-ls1b/lowlevel.S     |   3 +-
 arch/mips/boards/qemu-malta/lowlevel.S        |   3 +-
 arch/mips/boards/ritmix-rzx50/lowlevel.S      |   3 +-
 arch/mips/boards/tplink-mr3020/lowlevel.S     |   3 +-
 arch/mips/boards/tplink-wdr4300/lowlevel.S    |   3 +-
 arch/mips/boot/dtb.c                          |   4 -
 arch/mips/boot/main_entry-pbl.c               |  13 +-
 arch/mips/boot/main_entry.c                   |  17 +-
 arch/mips/boot/start.S                        |   4 +-
 arch/mips/include/asm/asm.h                   |   3 +-
 arch/mips/include/asm/pbl_macros.h            |   4 +-
 arch/mips/include/asm/relocs.h                |  23 +
 arch/mips/include/asm/sections.h              |  14 +
 arch/mips/lib/Makefile                        |   2 +
 arch/mips/lib/barebox.lds.S                   |  27 +-
 arch/mips/lib/cpu-probe.c                     |  14 +
 arch/mips/lib/pbl.lds.S                       |   2 +-
 arch/mips/lib/reloc.c                         | 182 ++++++++
 arch/mips/lib/sections.c                      |   9 +
 scripts/Makefile                              |   1 +
 scripts/mips-relocs.c                         | 426 ++++++++++++++++++
 28 files changed, 771 insertions(+), 32 deletions(-)
 create mode 100644 arch/mips/include/asm/relocs.h
 create mode 100644 arch/mips/lib/reloc.c
 create mode 100644 arch/mips/lib/sections.c
 create mode 100644 scripts/mips-relocs.c

-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/4] MIPS: relocation: pass ram size to pbl_main_entry
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
@ 2019-03-08 10:58 ` Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 2/4] MIPS: relocation: add relocation support Oleksij Rempel
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Oleksij Rempel @ 2019-03-08 10:58 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

From: Oleksij Rempel <linux@rempel-privat.de>

To make barebox dynamically relocatable it should know
the RAM size to be able to calculate proper new location.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 arch/mips/boards/8devices-lima/lowlevel.S         | 3 ++-
 arch/mips/boards/black-swift/lowlevel.S           | 3 ++-
 arch/mips/boards/dlink-dir-320/lowlevel.S         | 3 ++-
 arch/mips/boards/dptechnics-dpt-module/lowlevel.S | 3 ++-
 arch/mips/boards/img-ci20/lowlevel.S              | 3 ++-
 arch/mips/boards/loongson-ls1b/lowlevel.S         | 3 ++-
 arch/mips/boards/qemu-malta/lowlevel.S            | 3 ++-
 arch/mips/boards/ritmix-rzx50/lowlevel.S          | 3 ++-
 arch/mips/boards/tplink-mr3020/lowlevel.S         | 3 ++-
 arch/mips/boards/tplink-wdr4300/lowlevel.S        | 3 ++-
 arch/mips/boot/main_entry-pbl.c                   | 5 +++--
 arch/mips/include/asm/asm.h                       | 3 ++-
 12 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/mips/boards/8devices-lima/lowlevel.S b/arch/mips/boards/8devices-lima/lowlevel.S
index b53b23b42a..dd1ab6247d 100644
--- a/arch/mips/boards/8devices-lima/lowlevel.S
+++ b/arch/mips/boards/8devices-lima/lowlevel.S
@@ -11,6 +11,7 @@
 #include <mach/pbl_macros.h>
 #include <mach/pbl_ll_init_qca4531.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -38,4 +39,4 @@ skip_flash_test:
 	dcache_enable
 skip_pll_ram_config:
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, qca4531_8devices_lima)
+ENTRY_FUNCTION_END(BOARD_PBL_START, qca4531_8devices_lima, SZ_64M)
diff --git a/arch/mips/boards/black-swift/lowlevel.S b/arch/mips/boards/black-swift/lowlevel.S
index 0ba77435f8..5c5afcdf09 100644
--- a/arch/mips/boards/black-swift/lowlevel.S
+++ b/arch/mips/boards/black-swift/lowlevel.S
@@ -11,9 +11,10 @@
 #include <asm/asm.h>
 #include <mach/pbl_macros.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
 	ar9331_pbl_generic_start
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, black_swift)
+ENTRY_FUNCTION_END(BOARD_PBL_START, black_swift, SZ_64M)
diff --git a/arch/mips/boards/dlink-dir-320/lowlevel.S b/arch/mips/boards/dlink-dir-320/lowlevel.S
index 9f3bd5dead..da969bc74e 100644
--- a/arch/mips/boards/dlink-dir-320/lowlevel.S
+++ b/arch/mips/boards/dlink-dir-320/lowlevel.S
@@ -9,6 +9,7 @@
 #include <asm/pbl_macros.h>
 #include <mach/debug_ll.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -19,4 +20,4 @@ ENTRY_FUNCTION(BOARD_PBL_START)
 	/* CPU/SoC specific setup ... */
 	/* ... absent */
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, dlink_dir_320)
+ENTRY_FUNCTION_END(BOARD_PBL_START, dlink_dir_320, SZ_32M)
diff --git a/arch/mips/boards/dptechnics-dpt-module/lowlevel.S b/arch/mips/boards/dptechnics-dpt-module/lowlevel.S
index 28b8f4fac7..b5621963c3 100644
--- a/arch/mips/boards/dptechnics-dpt-module/lowlevel.S
+++ b/arch/mips/boards/dptechnics-dpt-module/lowlevel.S
@@ -12,9 +12,10 @@
 #include <asm/pbl_macros.h>
 #include <mach/pbl_macros.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
 	ar9331_pbl_generic_start
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, ar9331_dptechnics_dpt_module)
+ENTRY_FUNCTION_END(BOARD_PBL_START, ar9331_dptechnics_dpt_module, SZ_64M)
diff --git a/arch/mips/boards/img-ci20/lowlevel.S b/arch/mips/boards/img-ci20/lowlevel.S
index 056df17bf8..0295e44d1a 100644
--- a/arch/mips/boards/img-ci20/lowlevel.S
+++ b/arch/mips/boards/img-ci20/lowlevel.S
@@ -10,6 +10,7 @@
 #include <asm/pbl_macros.h>
 #include <mach/debug_ll.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -23,4 +24,4 @@ ENTRY_FUNCTION(BOARD_PBL_START)
 	debug_ll_outc '.'
 	debug_ll_ns16550_outnl
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, img_ci20)
+ENTRY_FUNCTION_END(BOARD_PBL_START, img_ci20, SZ_1G)
diff --git a/arch/mips/boards/loongson-ls1b/lowlevel.S b/arch/mips/boards/loongson-ls1b/lowlevel.S
index 37744e9fac..c533df3ce5 100644
--- a/arch/mips/boards/loongson-ls1b/lowlevel.S
+++ b/arch/mips/boards/loongson-ls1b/lowlevel.S
@@ -9,6 +9,7 @@
 #include <mach/loongson1.h>
 #include <mach/debug_ll.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -21,4 +22,4 @@ ENTRY_FUNCTION(BOARD_PBL_START)
 	debug_ll_outc '.'
 	debug_ll_ns16550_outnl
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, loongson_ls1b)
+ENTRY_FUNCTION_END(BOARD_PBL_START, loongson_ls1b, SZ_64M)
diff --git a/arch/mips/boards/qemu-malta/lowlevel.S b/arch/mips/boards/qemu-malta/lowlevel.S
index 3861ae9e46..e4ecde45cf 100644
--- a/arch/mips/boards/qemu-malta/lowlevel.S
+++ b/arch/mips/boards/qemu-malta/lowlevel.S
@@ -10,6 +10,7 @@
 #include <asm/asm.h>
 #include <asm/pbl_macros.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 #include <asm/addrspace.h>
 #include <asm/gt64120.h>
@@ -82,4 +83,4 @@ __start:
 	li	t0, GT_LD(0x1bdfffff)
 	sw	t0, GT_PCI0M1HD_OFS(t1)
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, qemu_malta)
+ENTRY_FUNCTION_END(BOARD_PBL_START, qemu_malta, SZ_256M)
diff --git a/arch/mips/boards/ritmix-rzx50/lowlevel.S b/arch/mips/boards/ritmix-rzx50/lowlevel.S
index 7a9743835e..33810f67f5 100644
--- a/arch/mips/boards/ritmix-rzx50/lowlevel.S
+++ b/arch/mips/boards/ritmix-rzx50/lowlevel.S
@@ -10,6 +10,7 @@
 #include <asm/pbl_macros.h>
 #include <mach/debug_ll.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -23,4 +24,4 @@ ENTRY_FUNCTION(BOARD_PBL_START)
 	debug_ll_outc '.'
 	debug_ll_ns16550_outnl
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, rzx50)
+ENTRY_FUNCTION_END(BOARD_PBL_START, rzx50, SZ_64M)
diff --git a/arch/mips/boards/tplink-mr3020/lowlevel.S b/arch/mips/boards/tplink-mr3020/lowlevel.S
index 0a1c193c1e..b96292ecc4 100644
--- a/arch/mips/boards/tplink-mr3020/lowlevel.S
+++ b/arch/mips/boards/tplink-mr3020/lowlevel.S
@@ -11,9 +11,10 @@
 #include <asm/asm.h>
 #include <mach/pbl_macros.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
 	ar9331_pbl_generic_start
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, tplink_mr3020)
+ENTRY_FUNCTION_END(BOARD_PBL_START, tplink_mr3020, SZ_32M)
diff --git a/arch/mips/boards/tplink-wdr4300/lowlevel.S b/arch/mips/boards/tplink-wdr4300/lowlevel.S
index 461b257f41..8aed5ddcf1 100644
--- a/arch/mips/boards/tplink-wdr4300/lowlevel.S
+++ b/arch/mips/boards/tplink-wdr4300/lowlevel.S
@@ -11,6 +11,7 @@
 #include <mach/pbl_macros.h>
 #include <mach/pbl_ll_init_ar9344_1.1.h>
 #include <asm/pbl_nmon.h>
+#include <linux/sizes.h>
 
 ENTRY_FUNCTION(BOARD_PBL_START)
 
@@ -35,4 +36,4 @@ skip_flash_test:
 
 skip_pll_ram_config:
 
-ENTRY_FUNCTION_END(BOARD_PBL_START, ar9344_tl_wdr4300_v1.7)
+ENTRY_FUNCTION_END(BOARD_PBL_START, ar9344_tl_wdr4300_v1.7, SZ_128M)
diff --git a/arch/mips/boot/main_entry-pbl.c b/arch/mips/boot/main_entry-pbl.c
index b40887b064..28eaa8791f 100644
--- a/arch/mips/boot/main_entry-pbl.c
+++ b/arch/mips/boot/main_entry-pbl.c
@@ -18,7 +18,7 @@ extern void *input_data_end;
 unsigned long free_mem_ptr;
 unsigned long free_mem_end_ptr;
 
-void pbl_main_entry(void *fdt, void *fdt_end);
+void pbl_main_entry(void *fdt, void *fdt_end, u32 ram_size);
 
 static unsigned long *ttb;
 
@@ -33,7 +33,8 @@ static void barebox_uncompress(void *compressed_start, unsigned int len)
 	pbl_barebox_uncompress((void*)TEXT_BASE, compressed_start, len);
 }
 
-void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end)
+void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end,
+					   u32 ram_size)
 {
 	u32 pg_start, pg_end, pg_len, fdt_len;
 	void *fdt_new;
diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index 7d2b673bd9..a85467ceed 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -89,13 +89,14 @@ EXPORT(symbol)
 /*
  * ENTRY_FUNCTION_END - mark end of entry function
  */
-#define ENTRY_FUNCTION_END(symbol, dtb)			\
+#define ENTRY_FUNCTION_END(symbol, dtb, ram_size)	\
 	mips_nmon;					\
 	copy_to_link_location	symbol;			\
 	stack_setup;					\
 							\
 	la	a0, __dtb_ ## dtb##_start;		\
 	la	a1, __dtb_ ## dtb##_end;		\
+	li	a2, ram_size;				\
 	la	v0, pbl_main_entry;			\
 	jal	v0;					\
 	 nop;						\
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 2/4] MIPS: relocation: add relocation support
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 1/4] MIPS: relocation: pass ram size to pbl_main_entry Oleksij Rempel
@ 2019-03-08 10:58 ` Oleksij Rempel
  2019-04-09 11:48   ` Sascha Hauer
  2019-03-08 10:58 ` [PATCH v2 3/4] MIPS: relocation: do not use configurable memory layout Oleksij Rempel
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Oleksij Rempel @ 2019-03-08 10:58 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

From: Oleksij Rempel <linux@rempel-privat.de>

this patch i a port of following patch from u-boot with some additional
integration changes and fixes of original code:
| Subject: [PATCH] MIPS: Stop building position independent code
|
| U-Boot has up until now built with -fpic for the MIPS architecture,
| producing position independent code which uses indirection through a
| global offset table, making relocation fairly straightforward as it
| simply involves patching up GOT entries.
|
| Using -fpic does however have some downsides. The biggest of these is
| that generated code is bloated in various ways. For example, function
| calls are indirected through the GOT & the t9 register:
|
|   8f998064   lw     t9,-32668(gp)
|   0320f809   jalr   t9
|
| Without -fpic the call is simply:
|
|   0f803f01   jal    be00fc04 <puts>
|
| This is more compact & faster (due to the lack of the load & the
| dependency the jump has on its result). It is also easier to read &
| debug because the disassembly shows what function is being called,
| rather than just an offset from gp which would then have to be looked up
| in the ELF to discover the target function.
|
| Another disadvantage of -fpic is that each function begins with a
| sequence to calculate the value of the gp register, for example:
|
|   3c1c0004   lui    gp,0x4
|   279c3384   addiu  gp,gp,13188
|   0399e021   addu   gp,gp,t9
|
| Without using -fpic this sequence no longer appears at the start of each
| function, reducing code size considerably.
|
| This patch switches U-Boot from building with -fpic to building with
| -fno-pic, in order to gain the benefits described above. The cost of
| this is an extra step during the build process to extract relocation
| data from the ELF & write it into a new .rel section in a compact
| format, plus the added complexity of dealing with multiple types of
| relocation rather than the single type that applied to the GOT. The
| benefit is smaller, cleaner, more debuggable code. The relocate_code()
| function is reimplemented in C to handle the new relocation scheme,
| which also makes it easier to read & debug.
|
| Taking maltael_defconfig as an example the size of u-boot.bin built
| using the Codescape MIPS 2016.05-06 toolchain (gcc 4.9.2, binutils
| 2.24.90) shrinks from 254KiB to 224KiB.
|
| Signed-off-by: Paul Burton <paul.burton@imgtec.com>

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 arch/mips/Kconfig                |  18 ++
 arch/mips/Makefile               |   9 +-
 arch/mips/boot/main_entry-pbl.c  |   4 +-
 arch/mips/boot/start.S           |   4 +-
 arch/mips/include/asm/relocs.h   |  23 ++
 arch/mips/include/asm/sections.h |  14 +
 arch/mips/lib/Makefile           |   2 +
 arch/mips/lib/barebox.lds.S      |  27 +-
 arch/mips/lib/reloc.c            | 182 +++++++++++++
 arch/mips/lib/sections.c         |   9 +
 scripts/Makefile                 |   1 +
 scripts/mips-relocs.c            | 426 +++++++++++++++++++++++++++++++
 12 files changed, 712 insertions(+), 7 deletions(-)
 create mode 100644 arch/mips/include/asm/relocs.h
 create mode 100644 arch/mips/lib/reloc.c
 create mode 100644 arch/mips/lib/sections.c
 create mode 100644 scripts/mips-relocs.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index eab9452de9..49f238df58 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -32,6 +32,24 @@ config PHYS_ADDR_T_64BIT
 
 menu "Machine selection"
 
+config MIPS_RELOCATION_TABLE_SIZE
+	hex "Relocation table size"
+	range 0x100 0x10000
+	default "0x8000"
+	---help---
+	  A table of relocation data will be appended to the Barebox binary
+	  and parsed in relocate_code() to fix up all offsets in the relocated
+	  Barebox.
+
+	  This option allows the amount of space reserved for the table to be
+	  adjusted in a range from 256 up to 64k. The default is 32k and should
+	  be ok in most cases. Reduce this value to shrink the size of U-Boot
+	  binary.
+
+	  The build will fail and a valid size suggested if this is too small.
+
+	  If unsure, leave at the default value.
+
 config BUILTIN_DTB
 	bool "link a DTB into the barebox image"
 	depends on OFTREE
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 5fbd51ceee..7830f44be4 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -59,7 +59,7 @@ CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
 ifndef CONFIG_MODULES
 # Add cleanup flags
 CPPFLAGS += -fdata-sections -ffunction-sections
-LDFLAGS_barebox += -static --gc-sections
+LDFLAGS_barebox += -static --gc-sections --emit-relocs
 endif
 
 ifdef CONFIG_IMAGE_COMPRESSION
@@ -116,6 +116,13 @@ CFLAGS += $(cflags-y)
 
 lds-$(CONFIG_GENERIC_LINKER_SCRIPT)   := arch/mips/lib/barebox.lds
 
+cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \
+      -T $(barebox-lds)                         \
+      --start-group $(barebox-common) --end-group                  \
+      $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^);	\
+	$(srctree)/scripts/mips-relocs $@
+
+
 CLEAN_FILES    += arch/mips/lib/barebox.lds barebox.map barebox.S
 
 pbl := arch/mips/pbl
diff --git a/arch/mips/boot/main_entry-pbl.c b/arch/mips/boot/main_entry-pbl.c
index 28eaa8791f..60be645148 100644
--- a/arch/mips/boot/main_entry-pbl.c
+++ b/arch/mips/boot/main_entry-pbl.c
@@ -38,7 +38,7 @@ void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end,
 {
 	u32 pg_start, pg_end, pg_len, fdt_len;
 	void *fdt_new;
-	void (*barebox)(void *fdt, u32 fdt_len);
+	void (*barebox)(void *fdt, u32 fdt_len, u32 ram_size);
 
 	puts_ll("pbl_main_entry()\n");
 
@@ -56,5 +56,5 @@ void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end,
 	memcpy(fdt_new, fdt, fdt_len);
 
 	barebox = (void *)TEXT_BASE;
-	barebox(fdt_new, fdt_len);
+	barebox(fdt_new, fdt_len, ram_size);
 }
diff --git a/arch/mips/boot/start.S b/arch/mips/boot/start.S
index 6efe03e98d..c1cd2d9dd5 100644
--- a/arch/mips/boot/start.S
+++ b/arch/mips/boot/start.S
@@ -18,6 +18,7 @@ EXPORT(_start)
 	/* save dtb pointer */
 	move	s0, a0
 	move	s1, a1
+	move	s2, a2
 
 	/* disable watchpoints */
 	mtc0	zero, CP0_WATCHLO
@@ -32,7 +33,8 @@ EXPORT(_start)
 	/* restore dtb pointer */
 	move	a0, s0
 	move	a1, s1
-	la	v0, main_entry
+	move	a2, s2
+	la	v0, relocate_code
 	jal	v0
 	 nop
 
diff --git a/arch/mips/include/asm/relocs.h b/arch/mips/include/asm/relocs.h
new file mode 100644
index 0000000000..0987c4bb13
--- /dev/null
+++ b/arch/mips/include/asm/relocs.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MIPS Relocations
+ *
+ * Copyright (c) 2017 Imagination Technologies Ltd.
+ */
+
+#ifndef __ASM_MIPS_RELOCS_H__
+#define __ASM_MIPS_RELOCS_H__
+
+#define R_MIPS_NONE		0
+#define R_MIPS_32		2
+#define R_MIPS_26		4
+#define R_MIPS_HI16		5
+#define R_MIPS_LO16		6
+#define R_MIPS_PC16		10
+#define R_MIPS_64		18
+#define R_MIPS_HIGHER		28
+#define R_MIPS_HIGHEST		29
+#define R_MIPS_PC21_S2		60
+#define R_MIPS_PC26_S2		61
+
+#endif /* __ASM_MIPS_RELOCS_H__ */
diff --git a/arch/mips/include/asm/sections.h b/arch/mips/include/asm/sections.h
index 2b8c516038..8e004eaf34 100644
--- a/arch/mips/include/asm/sections.h
+++ b/arch/mips/include/asm/sections.h
@@ -1 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __ASM_MIPS_SECTIONS_H
+#define __ASM_MIPS_SECTIONS_H
+
 #include <asm-generic/sections.h>
+
+/**
+ * __rel_start: Relocation data generated by the mips-relocs tool
+ *
+ * See arch/mips/lib/reloc.c for details on the format & use of this data.
+ */
+extern uint8_t __rel_start[];
+
+#endif
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 7372e8dc27..4ba42e526e 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -4,6 +4,8 @@ obj-y += cpu-probe.o
 lwl-y += end.o
 obj-y += traps.o
 obj-y += genex.o
+obj-y  += reloc.o
+obj-y += sections.o 
 obj-y += shutdown.o
 obj-y += dma-default.o
 
diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S
index 8ddf954517..58b0c5919d 100644
--- a/arch/mips/lib/barebox.lds.S
+++ b/arch/mips/lib/barebox.lds.S
@@ -13,6 +13,8 @@ SECTIONS
 	. = TEXT_BASE;
 
 	. = ALIGN(4);
+
+	.image_start : { *(.__image_start) }
 	.text      :
 	{
 		_stext = .;
@@ -79,9 +81,28 @@ SECTIONS
 	.dtb : { BAREBOX_DTB() }
 
 	_edata = .;
+	.image_end : { *(.__image_end) }
+
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss : { *(.bss*) }
-	__bss_stop = .;
+	/*
+	 * .rel must come last so that the mips-relocs tool can shrink
+	 * the section size & the PT_LOAD program header filesz.
+	 */
+	.data.reloc : {
+		__rel_start = .;
+		BYTE(0x0)
+		. += (32 * 1024) - 1;
+	}
+
 	_end = .;
+
+	.bss __rel_start (OVERLAY) : {
+		__bss_start = .;
+		*(.sbss.*)
+		*(.bss.*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_stop = .;
+	}
+
 }
diff --git a/arch/mips/lib/reloc.c b/arch/mips/lib/reloc.c
new file mode 100644
index 0000000000..9756d61666
--- /dev/null
+++ b/arch/mips/lib/reloc.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MIPS Relocation
+ *
+ * Copyright (c) 2017 Imagination Technologies Ltd.
+ *
+ * Relocation data, found in the .rel section, is generated by the mips-relocs
+ * tool & contains a record of all locations in the Barebox binary that need to
+ * be fixed up during relocation.
+ *
+ * The data is a sequence of unsigned integers, which are of somewhat arbitrary
+ * size. This is achieved by encoding integers as a sequence of bytes, each of
+ * which contains 7 bits of data with the most significant bit indicating
+ * whether any further bytes need to be read. The least significant bits of the
+ * integer are found in the first byte - ie. it somewhat resembles little
+ * endian.
+ *
+ * Each pair of two integers represents a relocation that must be applied. The
+ * first integer represents the type of relocation as a standard ELF relocation
+ * type (ie. R_MIPS_*). The second integer represents the offset at which to
+ * apply the relocation, relative to the previous relocation or for the first
+ * relocation the start of the relocated .text section.
+ *
+ * The end of the relocation data is indicated when type R_MIPS_NONE (0) is
+ * read, at which point no further integers should be read. That is, the
+ * terminating R_MIPS_NONE reloc includes no offset.
+ */
+
+#include <common.h>
+
+#include <asm/bitops.h>
+#include <asm/cache.h>
+#include <asm/cacheops.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/relocs.h>
+#include <asm/sections.h>
+#include <linux/sizes.h>
+#include <asm-generic/memory_layout.h>
+
+#define MAX_BSS_SIZE SZ_1M
+
+void main_entry(void *fdt, u32 fdt_size);
+void relocate_code(void *fdt, u32 fdt_size, u32 relocaddr);
+
+/**
+ * read_uint() - Read an unsigned integer from the buffer
+ * @buf: pointer to a pointer to the reloc buffer
+ *
+ * Read one whole unsigned integer from the relocation data pointed to by @buf,
+ * advancing @buf past the bytes encoding the integer.
+ *
+ * Returns: the integer read from @buf
+ */
+static unsigned long read_uint(uint8_t **buf)
+{
+	unsigned long val = 0;
+	unsigned int shift = 0;
+	uint8_t new;
+
+	do {
+		new = *(*buf)++;
+		val |= (new & 0x7f) << shift;
+		shift += 7;
+	} while (new & 0x80);
+
+	return val;
+}
+
+/**
+ * apply_reloc() - Apply a single relocation
+ * @type: the type of reloc (R_MIPS_*)
+ * @addr: the address that the reloc should be applied to
+ * @off: the relocation offset, ie. number of bytes we're moving Barebox by
+ *
+ * Apply a single relocation of type @type at @addr. This function is
+ * intentionally simple, and does the bare minimum needed to fixup the
+ * relocated Barebox - in particular, it does not check for overflows.
+ */
+static void apply_reloc(unsigned int type, void *addr, long off)
+{
+	uint32_t u32;
+
+	switch (type) {
+	case R_MIPS_26:
+		u32 = *(uint32_t *)addr;
+		u32 = (u32 & GENMASK(31, 26)) |
+		      ((u32 + (off >> 2)) & GENMASK(25, 0));
+		*(uint32_t *)addr = u32;
+		break;
+
+	case R_MIPS_32:
+		*(uint32_t *)addr += off;
+		break;
+
+	case R_MIPS_64:
+		*(uint64_t *)addr += off;
+		break;
+
+	case R_MIPS_HI16:
+		*(uint32_t *)addr += off >> 16;
+		break;
+
+	default:
+		panic("Unhandled reloc type %u\n", type);
+	}
+}
+
+/**
+ * relocate_code() - Relocate Barebox, generally from flash to DDR
+ * @start_addr_sp: new stack pointer
+ * @new_gd: pointer to relocated global data
+ * @relocaddr: the address to relocate to
+ *
+ * Relocate Barebox from its current location (generally in flash) to a new one
+ * (generally in DDR). This function will copy the Barebox binary & apply
+ * relocations as necessary, then jump to board_init_r in the new build of
+ * Barebox. As such, this function does not return.
+ */
+void relocate_code(void *fdt, u32 fdt_size, u32 ram_size)
+{
+	unsigned long addr, length, bss_len;
+	u32 relocaddr, new_stack;
+	uint8_t *buf, *bss_start;
+	unsigned int type;
+	long off;
+
+	length = barebox_image_size + MAX_BSS_SIZE;
+	relocaddr = ALIGN_DOWN(ram_size - barebox_image_size, SZ_64K);
+	relocaddr = KSEG0ADDR(relocaddr);
+	new_stack = relocaddr - MALLOC_SIZE - 16;
+
+	/*
+	 * Ensure that we're relocating by an offset which is a multiple of
+	 * 64KiB, ie. doesn't change the least significant 16 bits of any
+	 * addresses. This allows us to discard R_MIPS_LO16 relocs, saving
+	 * space in the Barebox binary & complexity in handling them.
+	 */
+	off = relocaddr - (unsigned long)__image_start;
+	if (off & 0xffff)
+		panic("Mis-aligned relocation\n");
+
+	/* Copy Barebox to RAM */
+	memcpy((void *)relocaddr, __image_start, length);
+
+	/* Now apply relocations to the copy in RAM */
+	buf = __rel_start;
+	addr = relocaddr;
+	while (true) {
+		type = read_uint(&buf);
+		if (type == R_MIPS_NONE)
+			break;
+
+		addr += read_uint(&buf) << 2;
+		apply_reloc(type, (void *)addr, off);
+	}
+
+	/* Ensure the icache is coherent */
+	flush_cache_all();
+
+	/* Clear the .bss section */
+	bss_start = (uint8_t *)((unsigned long)__bss_start + off);
+	bss_len = (unsigned long)&__bss_stop - (unsigned long)__bss_start;
+	memset(bss_start, 0, bss_len);
+
+	 __asm__ __volatile__ (
+			"move	$a0, %0\n"
+		"	move	$a1, %1\n"
+		"	move	$31, $0\n"
+		"	move	$sp, %2\n"
+		"	jr	%3\n"
+		: /* no outputs */
+		: "r"(fdt),
+		  "r"(fdt_size),
+		  "r"(new_stack),
+		  "r"((unsigned long)main_entry + off));
+
+	/* Since we jumped to the new Barebox above, we won't get here */
+	unreachable();
+}
diff --git a/arch/mips/lib/sections.c b/arch/mips/lib/sections.c
new file mode 100644
index 0000000000..66d559f94a
--- /dev/null
+++ b/arch/mips/lib/sections.c
@@ -0,0 +1,9 @@
+#include <common.h>
+#include <asm/sections.h>
+#include <linux/types.h>
+
+char _text[0] __attribute__((section("._text")));
+char __bss_start[0] __attribute__((section(".__bss_start")));
+char __bss_stop[0] __attribute__((section(".__bss_stop")));
+char __image_start[0] __attribute__((section(".__image_start")));
+char __image_end[0] __attribute__((section(".__image_end")));
diff --git a/scripts/Makefile b/scripts/Makefile
index ff0a3c2a07..62d4ab20aa 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -12,6 +12,7 @@ hostprogs-y                      += bareboxcrc32
 hostprogs-y                      += kernel-install
 hostprogs-$(CONFIG_IMD)          += bareboximd
 hostprogs-$(CONFIG_KALLSYMS)     += kallsyms
+hostprogs-$(CONFIG_MIPS)         += mips-relocs
 hostprogs-$(CONFIG_MVEBU_HOSTTOOLS) += kwbimage kwboot
 hostprogs-$(CONFIG_ARCH_NETX)    += gen_netx_image
 hostprogs-$(CONFIG_ARCH_OMAP)    += omap_signGP mk-omap-image
diff --git a/scripts/mips-relocs.c b/scripts/mips-relocs.c
new file mode 100644
index 0000000000..7916159581
--- /dev/null
+++ b/scripts/mips-relocs.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MIPS Relocation Data Generator
+ *
+ * Copyright (c) 2017 Imagination Technologies Ltd.
+ */
+
+#include <assert.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <../../arch/mips/include/asm/relocs.h>
+
+#define hdr_field(pfx, idx, field) ({				\
+	uint64_t _val;						\
+	unsigned int _size;					\
+								\
+	if (is_64) {						\
+		_val = pfx##hdr64[idx].field;			\
+		_size = sizeof(pfx##hdr64[0].field);		\
+	} else {						\
+		_val = pfx##hdr32[idx].field;			\
+		_size = sizeof(pfx##hdr32[0].field);		\
+	}							\
+								\
+	switch (_size) {					\
+	case 1:							\
+		break;						\
+	case 2:							\
+		_val = is_be ? be16toh(_val) : le16toh(_val);	\
+		break;						\
+	case 4:							\
+		_val = is_be ? be32toh(_val) : le32toh(_val);	\
+		break;						\
+	case 8:							\
+		_val = is_be ? be64toh(_val) : le64toh(_val);	\
+		break;						\
+	}							\
+								\
+	_val;							\
+})
+
+#define set_hdr_field(pfx, idx, field, val) ({			\
+	uint64_t _val;						\
+	unsigned int _size;					\
+								\
+	if (is_64)						\
+		_size = sizeof(pfx##hdr64[0].field);		\
+	else							\
+		_size = sizeof(pfx##hdr32[0].field);		\
+								\
+	switch (_size) {					\
+	case 1:							\
+		_val = val;					\
+		break;						\
+	case 2:							\
+		_val = is_be ? htobe16(val) : htole16(val);	\
+		break;						\
+	case 4:							\
+		_val = is_be ? htobe32(val) : htole32(val);	\
+		break;						\
+	case 8:							\
+		_val = is_be ? htobe64(val) : htole64(val);	\
+		break;						\
+	default:						\
+		/* We should never reach here */		\
+		_val = 0;					\
+		assert(0);					\
+		break;						\
+	}							\
+								\
+	if (is_64)						\
+		pfx##hdr64[idx].field = _val;			\
+	else							\
+		pfx##hdr32[idx].field = _val;			\
+})
+
+#define ehdr_field(field) \
+	hdr_field(e, 0, field)
+#define phdr_field(idx, field) \
+	hdr_field(p, idx, field)
+#define shdr_field(idx, field) \
+	hdr_field(s, idx, field)
+
+#define set_phdr_field(idx, field, val) \
+	set_hdr_field(p, idx, field, val)
+#define set_shdr_field(idx, field, val) \
+	set_hdr_field(s, idx, field, val)
+
+#define shstr(idx) (&shstrtab[idx])
+
+bool is_64, is_be;
+uint64_t text_base;
+
+struct mips_reloc {
+	uint8_t type;
+	uint64_t offset;
+} *relocs;
+size_t relocs_sz, relocs_idx;
+
+static int add_reloc(unsigned int type, uint64_t off)
+{
+	struct mips_reloc *new;
+	size_t new_sz;
+
+	switch (type) {
+	case R_MIPS_NONE:
+	case R_MIPS_LO16:
+	case R_MIPS_PC16:
+	case R_MIPS_HIGHER:
+	case R_MIPS_HIGHEST:
+	case R_MIPS_PC21_S2:
+	case R_MIPS_PC26_S2:
+		/* Skip these relocs */
+		return 0;
+
+	default:
+		break;
+	}
+
+	if (relocs_idx == relocs_sz) {
+		new_sz = relocs_sz ? relocs_sz * 2 : 128;
+		new = realloc(relocs, new_sz * sizeof(*relocs));
+		if (!new) {
+			fprintf(stderr, "Out of memory\n");
+			return -ENOMEM;
+		}
+
+		relocs = new;
+		relocs_sz = new_sz;
+	}
+
+	relocs[relocs_idx++] = (struct mips_reloc){
+		.type = type,
+		.offset = off,
+	};
+
+	return 0;
+}
+
+static int parse_mips32_rel(const void *_rel)
+{
+	const Elf32_Rel *rel = _rel;
+	uint32_t off, type;
+
+	off = is_be ? be32toh(rel->r_offset) : le32toh(rel->r_offset);
+	off -= text_base;
+
+	type = is_be ? be32toh(rel->r_info) : le32toh(rel->r_info);
+	type = ELF32_R_TYPE(type);
+
+	return add_reloc(type, off);
+}
+
+static int parse_mips64_rela(const void *_rel)
+{
+	const Elf64_Rela *rel = _rel;
+	uint64_t off, type;
+
+	off = is_be ? be64toh(rel->r_offset) : le64toh(rel->r_offset);
+	off -= text_base;
+
+	type = rel->r_info >> (64 - 8);
+
+	return add_reloc(type, off);
+}
+
+static void output_uint(uint8_t **buf, uint64_t val)
+{
+	uint64_t tmp;
+
+	do {
+		tmp = val & 0x7f;
+		val >>= 7;
+		tmp |= !!val << 7;
+		*(*buf)++ = tmp;
+	} while (val);
+}
+
+static int compare_relocs(const void *a, const void *b)
+{
+	const struct mips_reloc *ra = a, *rb = b;
+
+	return ra->offset - rb->offset;
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned int i, j, i_rel_shdr, sh_type, sh_entsize, sh_entries;
+	size_t rel_size, rel_actual_size;
+	const char *shstrtab, *sh_name, *rel_pfx;
+	int (*parse_fn)(const void *rel);
+	uint8_t *buf_start, *buf;
+	const Elf32_Ehdr *ehdr32;
+	const Elf64_Ehdr *ehdr64;
+	uintptr_t sh_offset;
+	Elf32_Shdr *shdr32;
+	Elf64_Shdr *shdr64;
+	struct stat st;
+	int err, fd;
+	void *elf;
+	bool skip;
+
+	fd = open(argv[1], O_RDWR);
+	if (fd == -1) {
+		fprintf(stderr, "Unable to open input file %s\n", argv[1]);
+		err = errno;
+		goto out_ret;
+	}
+
+	err = fstat(fd, &st);
+	if (err) {
+		fprintf(stderr, "Unable to fstat() input file\n");
+		goto out_close_fd;
+	}
+
+	elf = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	if (elf == MAP_FAILED) {
+		fprintf(stderr, "Unable to mmap() input file\n");
+		err = errno;
+		goto out_close_fd;
+	}
+
+	ehdr32 = elf;
+	ehdr64 = elf;
+
+	if (memcmp(&ehdr32->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
+		fprintf(stderr, "Input file is not an ELF\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	if (ehdr32->e_ident[EI_VERSION] != EV_CURRENT) {
+		fprintf(stderr, "Unrecognised ELF version\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	switch (ehdr32->e_ident[EI_CLASS]) {
+	case ELFCLASS32:
+		is_64 = false;
+		break;
+	case ELFCLASS64:
+		is_64 = true;
+		break;
+	default:
+		fprintf(stderr, "Unrecognised ELF class\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	switch (ehdr32->e_ident[EI_DATA]) {
+	case ELFDATA2LSB:
+		is_be = false;
+		break;
+	case ELFDATA2MSB:
+		is_be = true;
+		break;
+	default:
+		fprintf(stderr, "Unrecognised ELF data encoding\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	if (ehdr_field(e_type) != ET_EXEC) {
+		fprintf(stderr, "Input ELF is not an executable\n");
+		printf("type 0x%lx\n", ehdr_field(e_type));
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	if (ehdr_field(e_machine) != EM_MIPS) {
+		fprintf(stderr, "Input ELF does not target MIPS\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	shdr32 = elf + ehdr_field(e_shoff);
+	shdr64 = elf + ehdr_field(e_shoff);
+	shstrtab = elf + shdr_field(ehdr_field(e_shstrndx), sh_offset);
+
+	i_rel_shdr = UINT_MAX;
+	for (i = 0; i < ehdr_field(e_shnum); i++) {
+		sh_name = shstr(shdr_field(i, sh_name));
+
+		if (!strcmp(sh_name, ".data.reloc")) {
+			i_rel_shdr = i;
+			continue;
+		}
+
+		if (!strcmp(sh_name, ".text")) {
+			text_base = shdr_field(i, sh_addr);
+			continue;
+		}
+	}
+	if (i_rel_shdr == UINT_MAX) {
+		fprintf(stderr, "Unable to find .rel section\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+	if (!text_base) {
+		fprintf(stderr, "Unable to find .text base address\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	rel_pfx = is_64 ? ".rela." : ".rel.";
+
+	for (i = 0; i < ehdr_field(e_shnum); i++) {
+		sh_type = shdr_field(i, sh_type);
+		if ((sh_type != SHT_REL) && (sh_type != SHT_RELA))
+			continue;
+
+		sh_name = shstr(shdr_field(i, sh_name));
+		if (strncmp(sh_name, rel_pfx, strlen(rel_pfx))) {
+			if (strcmp(sh_name, ".rel") && strcmp(sh_name, ".rel.dyn"))
+				fprintf(stderr, "WARNING: Unexpected reloc section name '%s'\n", sh_name);
+			continue;
+		}
+
+		/*
+		 * Skip reloc sections which either don't correspond to another
+		 * section in the ELF, or whose corresponding section isn't
+		 * loaded as part of the U-Boot binary (ie. doesn't have the
+		 * alloc flags set).
+		 */
+		skip = true;
+		for (j = 0; j < ehdr_field(e_shnum); j++) {
+			if (strcmp(&sh_name[strlen(rel_pfx) - 1], shstr(shdr_field(j, sh_name))))
+				continue;
+
+			skip = !(shdr_field(j, sh_flags) & SHF_ALLOC);
+			break;
+		}
+		if (skip)
+			continue;
+
+		sh_offset = shdr_field(i, sh_offset);
+		sh_entsize = shdr_field(i, sh_entsize);
+		sh_entries = shdr_field(i, sh_size) / sh_entsize;
+
+		if (sh_type == SHT_REL) {
+			if (is_64) {
+				fprintf(stderr, "REL-style reloc in MIPS64 ELF?\n");
+				err = -EINVAL;
+				goto out_free_relocs;
+			} else {
+				parse_fn = parse_mips32_rel;
+			}
+		} else {
+			if (is_64) {
+				parse_fn = parse_mips64_rela;
+			} else {
+				fprintf(stderr, "RELA-style reloc in MIPS32 ELF?\n");
+				err = -EINVAL;
+				goto out_free_relocs;
+			}
+		}
+
+		for (j = 0; j < sh_entries; j++) {
+			err = parse_fn(elf + sh_offset + (j * sh_entsize));
+			if (err)
+				goto out_free_relocs;
+		}
+	}
+
+	if (!relocs) {
+		fprintf(stderr, "No relocs was found. Try to configure linker with --emit-relocs\n");
+		err = -EINVAL;
+		goto out_free_relocs;
+	}
+
+	/* Sort relocs in ascending order of offset */
+	qsort(relocs, relocs_idx, sizeof(*relocs), compare_relocs);
+
+	/* Make reloc offsets relative to their predecessor */
+	for (i = relocs_idx - 1; i > 0; i--) {
+		relocs[i].offset -= relocs[i - 1].offset;
+	}
+
+	/* Write the relocations to the .rel section */
+	buf = buf_start = elf + shdr_field(i_rel_shdr, sh_offset);
+	for (i = 0; i < relocs_idx; i++) {
+		output_uint(&buf, relocs[i].type);
+		output_uint(&buf, relocs[i].offset >> 2);
+	}
+
+	/* Write a terminating R_MIPS_NONE (0) */
+	output_uint(&buf, R_MIPS_NONE);
+
+	/* Ensure the relocs didn't overflow the .rel section */
+	rel_size = shdr_field(i_rel_shdr, sh_size);
+	rel_actual_size = buf - buf_start;
+	if (rel_actual_size > rel_size) {
+		fprintf(stderr, "Relocations overflow available space of 0x%lx (required 0x%lx)!\n",
+			rel_size, rel_actual_size);
+		fprintf(stderr, "Please adjust CONFIG_MIPS_RELOCATION_TABLE_SIZE to at least 0x%lx\n",
+			(rel_actual_size + 0x100) & ~0xFF);
+		err = -ENOMEM;
+		goto out_free_relocs;
+	}
+
+	/* Make sure data is written back to the file */
+	err = msync(elf, st.st_size, MS_SYNC);
+	if (err) {
+		fprintf(stderr, "Failed to msync: %d\n", errno);
+		goto out_free_relocs;
+	}
+
+out_free_relocs:
+	free(relocs);
+	munmap(elf, st.st_size);
+out_close_fd:
+	close(fd);
+out_ret:
+	return err;
+}
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 3/4] MIPS: relocation: do not use configurable memory layout
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 1/4] MIPS: relocation: pass ram size to pbl_main_entry Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 2/4] MIPS: relocation: add relocation support Oleksij Rempel
@ 2019-03-08 10:58 ` Oleksij Rempel
  2019-03-08 10:58 ` [PATCH v2 4/4] MIPS: remove request_sdram_region "fdt" Oleksij Rempel
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Oleksij Rempel @ 2019-03-08 10:58 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

The relocator is not able to patch properly new location of
the stack. To make it work properly it is better to disable
HAVE_CONFIGURABLE_MEMORY_LAYOUT.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/mips/Kconfig                  |  1 -
 arch/mips/boot/main_entry-pbl.c    |  4 ++--
 arch/mips/boot/main_entry.c        | 17 +++++++++++++++--
 arch/mips/include/asm/pbl_macros.h |  4 ++--
 arch/mips/lib/cpu-probe.c          | 14 ++++++++++++++
 arch/mips/lib/pbl.lds.S            |  2 +-
 6 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 49f238df58..b59c3a9e87 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -7,7 +7,6 @@ config MIPS
 	select GENERIC_LIB_ASHRDI3
 	select GENERIC_LIB_LSHRDI3
 	select HAS_KALLSYMS
-	select HAVE_CONFIGURABLE_MEMORY_LAYOUT
 	select HAVE_CONFIGURABLE_TEXT_BASE
 	select HAVE_PBL_MULTI_IMAGES
 	select HAS_DMA
diff --git a/arch/mips/boot/main_entry-pbl.c b/arch/mips/boot/main_entry-pbl.c
index 60be645148..02ddd5ec24 100644
--- a/arch/mips/boot/main_entry-pbl.c
+++ b/arch/mips/boot/main_entry-pbl.c
@@ -25,7 +25,7 @@ static unsigned long *ttb;
 static void barebox_uncompress(void *compressed_start, unsigned int len)
 {
 	/* set 128 KiB at the end of the MALLOC_BASE for early malloc */
-	free_mem_ptr = MALLOC_BASE + MALLOC_SIZE - SZ_128K;
+	free_mem_ptr = TEXT_BASE - SZ_128K;
 	free_mem_end_ptr = free_mem_ptr + SZ_128K;
 
 	ttb = (void *)((free_mem_ptr - 0x4000) & ~0x3fff);
@@ -52,7 +52,7 @@ void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end,
 	barebox_uncompress(&input_data, pg_len);
 
 	fdt_len = (u32)fdt_end - (u32)fdt;
-	fdt_new = (void *)PAGE_ALIGN_DOWN(STACK_BASE - fdt_len);
+	fdt_new = (void *)PAGE_ALIGN_DOWN(TEXT_BASE - MALLOC_SIZE - STACK_SIZE - fdt_len);
 	memcpy(fdt_new, fdt, fdt_len);
 
 	barebox = (void *)TEXT_BASE;
diff --git a/arch/mips/boot/main_entry.c b/arch/mips/boot/main_entry.c
index 84325da93a..5b88730b07 100644
--- a/arch/mips/boot/main_entry.c
+++ b/arch/mips/boot/main_entry.c
@@ -12,6 +12,7 @@
 #include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
+#include <linux/sizes.h>
 
 extern void handle_reserved(void);
 
@@ -61,6 +62,7 @@ static void trap_init(void)
 
 extern void *glob_fdt;
 extern u32 glob_fdt_size;
+extern unsigned long mips_stack_top;
 
 /**
  * Called plainly from assembler code
@@ -69,6 +71,7 @@ extern u32 glob_fdt_size;
  */
 void __bare_init main_entry(void *fdt, u32 fdt_size)
 {
+	unsigned long malloc_start, malloc_end;
 	/* clear the BSS first */
 	memset(__bss_start, 0x00, __bss_stop - __bss_start);
 
@@ -82,8 +85,18 @@ void __bare_init main_entry(void *fdt, u32 fdt_size)
 
 	trap_init();
 
-	mem_malloc_init((void *)MALLOC_BASE,
-			(void *)(MALLOC_BASE + MALLOC_SIZE - 1));
+	malloc_end = _stext;
+
+	if (MALLOC_SIZE > 0)
+		malloc_start = malloc_end - MALLOC_SIZE;
+	else
+		malloc_start = malloc_end - SZ_8M;
+
+	pr_debug("initializing malloc pool at 0x%08lx (size 0x%08lx)\n",
+			malloc_start, malloc_end - malloc_start);
+
+	mem_malloc_init((void *)malloc_start, (void *)_stext - 1);
+	mips_stack_top = malloc_start;
 
 	glob_fdt = fdt;
 	glob_fdt_size = fdt_size;
diff --git a/arch/mips/include/asm/pbl_macros.h b/arch/mips/include/asm/pbl_macros.h
index e78d1afe6a..c62910ff60 100644
--- a/arch/mips/include/asm/pbl_macros.h
+++ b/arch/mips/include/asm/pbl_macros.h
@@ -187,7 +187,7 @@ copy_loop_exit:
 	 *
 	 */
 
-#if (STACK_BASE + STACK_SIZE) % 16 != 0
+#if (TEXT_BASE - MALLOC_SIZE) % 16 != 0
 #error stack pointer must be 16-byte-aligned
 #endif
 
@@ -196,7 +196,7 @@ copy_loop_exit:
 	.set	noreorder
 
 	/* set stack pointer; reserve four 32-bit argument slots */
-	la	sp, STACK_BASE + STACK_SIZE - 16
+	la	sp, (TEXT_BASE - MALLOC_SIZE - 16)
 
 	.set	pop
 	.endm
diff --git a/arch/mips/lib/cpu-probe.c b/arch/mips/lib/cpu-probe.c
index cf63849743..2556a8b240 100644
--- a/arch/mips/lib/cpu-probe.c
+++ b/arch/mips/lib/cpu-probe.c
@@ -11,6 +11,9 @@
 #include <asm/mipsregs.h>
 #include <asm/cpu-info.h>
 #include <asm/cpu.h>
+#include <memory.h>
+#include <asm-generic/memory_layout.h>
+#include <init.h>
 
 const char *__cpu_name;
 struct cpuinfo_mips cpu_data[1];
@@ -161,3 +164,14 @@ void cpu_probe(void)
 		break;
 	}
 }
+
+unsigned long mips_stack_top;
+
+static int mips_request_stack(void)
+{
+	if (!request_sdram_region("stack", mips_stack_top - STACK_SIZE, STACK_SIZE))
+		pr_err("Error: Cannot request SDRAM region for stack\n");
+
+	return 0;
+}
+coredevice_initcall(mips_request_stack);
diff --git a/arch/mips/lib/pbl.lds.S b/arch/mips/lib/pbl.lds.S
index 1f0285dd6f..2be90b8e5f 100644
--- a/arch/mips/lib/pbl.lds.S
+++ b/arch/mips/lib/pbl.lds.S
@@ -10,7 +10,7 @@
 OUTPUT_ARCH("mips")
 SECTIONS
 {
-	. = HEAD_TEXT_BASE;
+	. = TEXT_BASE - MALLOC_SIZE;
 
 	PRE_IMAGE
 
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 4/4] MIPS: remove request_sdram_region "fdt"
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
                   ` (2 preceding siblings ...)
  2019-03-08 10:58 ` [PATCH v2 3/4] MIPS: relocation: do not use configurable memory layout Oleksij Rempel
@ 2019-03-08 10:58 ` Oleksij Rempel
  2019-03-18  9:41 ` [PATCH v2 0/4] MIPS: add relocation support Sascha Hauer
  2019-04-09 11:51 ` Sascha Hauer
  5 siblings, 0 replies; 8+ messages in thread
From: Oleksij Rempel @ 2019-03-08 10:58 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

It is actually not needed at barebox runtime

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/mips/boot/dtb.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/mips/boot/dtb.c b/arch/mips/boot/dtb.c
index ea30e16f21..5e316270f6 100644
--- a/arch/mips/boot/dtb.c
+++ b/arch/mips/boot/dtb.c
@@ -29,10 +29,6 @@ void of_add_memory_bank(struct device_node *node, bool dump, int r,
 
 	if (dump)
 		pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base);
-
-	if (glob_fdt && glob_fdt_size)
-		request_sdram_region("fdt", (resource_size_t)glob_fdt,
-				     glob_fdt_size);
 }
 
 extern char __dtb_start[];
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/4] MIPS: add relocation support
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
                   ` (3 preceding siblings ...)
  2019-03-08 10:58 ` [PATCH v2 4/4] MIPS: remove request_sdram_region "fdt" Oleksij Rempel
@ 2019-03-18  9:41 ` Sascha Hauer
  2019-04-09 11:51 ` Sascha Hauer
  5 siblings, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2019-03-18  9:41 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Fri, Mar 08, 2019 at 11:58:50AM +0100, Oleksij Rempel wrote:
> with this patches, same main binary version of barebox xan be reused
> on different board with different RAM size.
> The barebox will find best possible location for it self depending
> on RAM size information provided by PBL.
> 
> changes v2:
> - don't remove no-pic flag to avoid confusion.
> - don't set ggdb flag for barebox tools.
> 
> Oleksij Rempel (4):
>   MIPS: relocation: pass ram size to pbl_main_entry
>   MIPS: relocation: add relocation support
>   MIPS: relocation: do not use configurable memory layout
>   MIPS: remove request_sdram_region "fdt"

Applied for now. Antony, if you have objections feel free to comment.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/4] MIPS: relocation: add relocation support
  2019-03-08 10:58 ` [PATCH v2 2/4] MIPS: relocation: add relocation support Oleksij Rempel
@ 2019-04-09 11:48   ` Sascha Hauer
  0 siblings, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2019-04-09 11:48 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox, Oleksij Rempel

On Fri, Mar 08, 2019 at 11:58:52AM +0100, Oleksij Rempel wrote:
> From: Oleksij Rempel <linux@rempel-privat.de>
> 
> this patch i a port of following patch from u-boot with some additional
> integration changes and fixes of original code:
> | Subject: [PATCH] MIPS: Stop building position independent code
> |
> | U-Boot has up until now built with -fpic for the MIPS architecture,
> | producing position independent code which uses indirection through a
> | global offset table, making relocation fairly straightforward as it
> | simply involves patching up GOT entries.
> |
> | Using -fpic does however have some downsides. The biggest of these is
> | that generated code is bloated in various ways. For example, function
> | calls are indirected through the GOT & the t9 register:
> |
> |   8f998064   lw     t9,-32668(gp)
> |   0320f809   jalr   t9
> |
> | Without -fpic the call is simply:
> |
> |   0f803f01   jal    be00fc04 <puts>
> |
> | This is more compact & faster (due to the lack of the load & the
> | dependency the jump has on its result). It is also easier to read &
> | debug because the disassembly shows what function is being called,
> | rather than just an offset from gp which would then have to be looked up
> | in the ELF to discover the target function.
> |
> | Another disadvantage of -fpic is that each function begins with a
> | sequence to calculate the value of the gp register, for example:
> |
> |   3c1c0004   lui    gp,0x4
> |   279c3384   addiu  gp,gp,13188
> |   0399e021   addu   gp,gp,t9
> |
> | Without using -fpic this sequence no longer appears at the start of each
> | function, reducing code size considerably.
> |
> | This patch switches U-Boot from building with -fpic to building with
> | -fno-pic, in order to gain the benefits described above. The cost of
> | this is an extra step during the build process to extract relocation
> | data from the ELF & write it into a new .rel section in a compact
> | format, plus the added complexity of dealing with multiple types of
> | relocation rather than the single type that applied to the GOT. The
> | benefit is smaller, cleaner, more debuggable code. The relocate_code()
> | function is reimplemented in C to handle the new relocation scheme,
> | which also makes it easier to read & debug.
> |
> | Taking maltael_defconfig as an example the size of u-boot.bin built
> | using the Codescape MIPS 2016.05-06 toolchain (gcc 4.9.2, binutils
> | 2.24.90) shrinks from 254KiB to 224KiB.
> |
> | Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> 
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  arch/mips/Kconfig                |  18 ++
>  arch/mips/Makefile               |   9 +-
>  arch/mips/boot/main_entry-pbl.c  |   4 +-
>  arch/mips/boot/start.S           |   4 +-
>  arch/mips/include/asm/relocs.h   |  23 ++
>  arch/mips/include/asm/sections.h |  14 +
>  arch/mips/lib/Makefile           |   2 +
>  arch/mips/lib/barebox.lds.S      |  27 +-
>  arch/mips/lib/reloc.c            | 182 +++++++++++++
>  arch/mips/lib/sections.c         |   9 +
>  scripts/Makefile                 |   1 +
>  scripts/mips-relocs.c            | 426 +++++++++++++++++++++++++++++++
>  12 files changed, 712 insertions(+), 7 deletions(-)
>  create mode 100644 arch/mips/include/asm/relocs.h
>  create mode 100644 arch/mips/lib/reloc.c
>  create mode 100644 arch/mips/lib/sections.c
>  create mode 100644 scripts/mips-relocs.c
> 
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index eab9452de9..49f238df58 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -32,6 +32,24 @@ config PHYS_ADDR_T_64BIT
>  
>  menu "Machine selection"
>  
> +config MIPS_RELOCATION_TABLE_SIZE
> +	hex "Relocation table size"
> +	range 0x100 0x10000
> +	default "0x8000"
> +	---help---
> +	  A table of relocation data will be appended to the Barebox binary
> +	  and parsed in relocate_code() to fix up all offsets in the relocated
> +	  Barebox.
> +
> +	  This option allows the amount of space reserved for the table to be
> +	  adjusted in a range from 256 up to 64k. The default is 32k and should
> +	  be ok in most cases. Reduce this value to shrink the size of U-Boot
> +	  binary.
> +
> +	  The build will fail and a valid size suggested if this is too small.
> +
> +	  If unsure, leave at the default value.
> +
>  config BUILTIN_DTB
>  	bool "link a DTB into the barebox image"
>  	depends on OFTREE
> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index 5fbd51ceee..7830f44be4 100644
> --- a/arch/mips/Makefile
> +++ b/arch/mips/Makefile
> @@ -59,7 +59,7 @@ CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
>  ifndef CONFIG_MODULES
>  # Add cleanup flags
>  CPPFLAGS += -fdata-sections -ffunction-sections
> -LDFLAGS_barebox += -static --gc-sections
> +LDFLAGS_barebox += -static --gc-sections --emit-relocs
>  endif
>  
>  ifdef CONFIG_IMAGE_COMPRESSION
> @@ -116,6 +116,13 @@ CFLAGS += $(cflags-y)
>  
>  lds-$(CONFIG_GENERIC_LINKER_SCRIPT)   := arch/mips/lib/barebox.lds
>  
> +cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \
> +      -T $(barebox-lds)                         \
> +      --start-group $(barebox-common) --end-group                  \
> +      $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^);	\
> +	$(srctree)/scripts/mips-relocs $@

This should be $(objtree), otherwise it breaks out of tree build.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/4] MIPS: add relocation support
  2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
                   ` (4 preceding siblings ...)
  2019-03-18  9:41 ` [PATCH v2 0/4] MIPS: add relocation support Sascha Hauer
@ 2019-04-09 11:51 ` Sascha Hauer
  5 siblings, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2019-04-09 11:51 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Fri, Mar 08, 2019 at 11:58:50AM +0100, Oleksij Rempel wrote:
> with this patches, same main binary version of barebox xan be reused
> on different board with different RAM size.
> The barebox will find best possible location for it self depending
> on RAM size information provided by PBL.
> 
> changes v2:
> - don't remove no-pic flag to avoid confusion.
> - don't set ggdb flag for barebox tools.
> 
> Oleksij Rempel (4):
>   MIPS: relocation: pass ram size to pbl_main_entry
>   MIPS: relocation: add relocation support
>   MIPS: relocation: do not use configurable memory layout
>   MIPS: remove request_sdram_region "fdt"

I had to drop this series for now. When merging with the other branches
in previous next branch I got several:

images/pbl.lds:24: undefined symbol `MALLOC_BASE' referenced in expression

Could you have a look into it and resend?

Also There's one minor problem I commented inline to this series.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-04-09 11:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-08 10:58 [PATCH v2 0/4] MIPS: add relocation support Oleksij Rempel
2019-03-08 10:58 ` [PATCH v2 1/4] MIPS: relocation: pass ram size to pbl_main_entry Oleksij Rempel
2019-03-08 10:58 ` [PATCH v2 2/4] MIPS: relocation: add relocation support Oleksij Rempel
2019-04-09 11:48   ` Sascha Hauer
2019-03-08 10:58 ` [PATCH v2 3/4] MIPS: relocation: do not use configurable memory layout Oleksij Rempel
2019-03-08 10:58 ` [PATCH v2 4/4] MIPS: remove request_sdram_region "fdt" Oleksij Rempel
2019-03-18  9:41 ` [PATCH v2 0/4] MIPS: add relocation support Sascha Hauer
2019-04-09 11:51 ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox