All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Simek <monstr@monstr.eu>
To: u-boot@lists.denx.de, git@xilinx.com
Cc: Angelo Dureghello <angelo@sysam.it>, Heiko Schocher <hs@denx.de>,
	Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Huan Wang <alison.wang@nxp.com>, Marek Vasut <marex@denx.de>,
	Michal Simek <monstr@monstr.eu>,
	Ovidiu Panait <ovidiu.panait@windriver.com>,
	Rick Chen <rick@andestech.com>,
	Sean Anderson <sean.anderson@seco.com>,
	Simon Glass <sjg@chromium.org>
Subject: [PATCH v4 23/23] microblaze: Add support for run time relocation
Date: Wed, 15 Jun 2022 15:21:19 +0200	[thread overview]
Message-ID: <a845670b34925859b2e321875f7588a29f6655f9.1655299267.git.michal.simek@amd.com> (raw)
In-Reply-To: <cover.1655299267.git.michal.simek@amd.com>

Microblaze is using NEEDS_MANUAL_RELOC from the beginnging. This is causing
issues with function pointer arrays which need to be updated manually after
relocation. Building code with -fPIC and linking with -pic will remove this
limitation and there is no longer need to run manual update.

By default still old option is enabled but by disabling NEEDS_MANUAL_RELOC
code will be compiled for full relocation.

The patch does couple of things which are connected to each other.
- Define STATIC_RELA dependency to call relocate-rela to fill sections.
- REMAKE_ELF was already enabled but u-boot file can't be used because
  sections are empty. relocate-rela will fill them and output file is
  u-boot.elf which should be used.
- Add support for full relocation (u-boot.elf)
- Add support for early relocation when u-boot.bin is loaded to different
  address then CONFIG_SYS_TEXT_BASE
- Add rela.dyn and dynsym sections

Disabling NEEDS_MANUAL_RELOC U-Boot size increased by 10% of it's original
size (550kB to 608kB).

Signed-off-by: Michal Simek <michal.simek@amd.com>
---

Changes in v4:
- Aligned NEEDS_MANUAL_RELOC for m68k

 arch/Kconfig                   |   4 --
 arch/m68k/Kconfig              |   3 +
 arch/microblaze/Kconfig        |  14 +++++
 arch/microblaze/config.mk      |   5 ++
 arch/microblaze/cpu/Makefile   |   1 +
 arch/microblaze/cpu/relocate.c | 111 +++++++++++++++++++++++++++++++++
 arch/microblaze/cpu/start.S    |  66 ++++++++++++++++++++
 arch/microblaze/cpu/u-boot.lds |  14 +++++
 common/board_f.c               |   2 +
 9 files changed, 216 insertions(+), 4 deletions(-)
 create mode 100644 arch/microblaze/cpu/relocate.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 02de32f9c77f..d91475d24747 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -8,9 +8,6 @@ config CREATE_ARCH_SYMLINK
 config HAVE_ARCH_IOREMAP
 	bool
 
-config NEEDS_MANUAL_RELOC
-	bool
-
 config SYS_CACHE_SHIFT_4
 	bool
 
@@ -76,7 +73,6 @@ config M68K
 
 config MICROBLAZE
 	bool "MicroBlaze architecture"
-	select NEEDS_MANUAL_RELOC
 	select SUPPORT_OF_CONTROL
 	imply CMD_IRQ
 
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 7f6e4310f1f4..d501c4c97990 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -4,6 +4,9 @@ menu "M68000 architecture"
 config SYS_ARCH
 	default "m68k"
 
+config NEEDS_MANUAL_RELOC
+	def_bool y
+
 # processor family
 config MCF520x
 	select OF_CONTROL
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index d7d1b219704e..6f45d19330a1 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -4,6 +4,20 @@ menu "MicroBlaze architecture"
 config SYS_ARCH
 	default "microblaze"
 
+config NEEDS_MANUAL_RELOC
+	bool "Disable position-independent pre-relocation code"
+	default y
+	help
+	  U-Boot expects to be linked to a specific hard-coded address, and to
+	  be loaded to and run from that address. This option lifts that
+	  restriction, thus allowing the code to be loaded to and executed from
+	  almost any 4K aligned address. This logic relies on the relocation
+	  information that is embedded in the binary to support U-Boot
+	  relocating itself to the top-of-RAM later during execution.
+
+config STATIC_RELA
+	def_bool y if !NEEDS_MANUAL_RELOC
+
 choice
 	prompt "Target select"
 	optional
diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk
index 3e84a832fc12..d35b4f6db7a1 100644
--- a/arch/microblaze/config.mk
+++ b/arch/microblaze/config.mk
@@ -17,6 +17,11 @@ ifeq ($(CONFIG_SPL_BUILD),)
 PLATFORM_CPPFLAGS += -fPIC
 endif
 
+ifeq ($(CONFIG_STATIC_RELA),y)
+PLATFORM_CPPFLAGS += -fPIC
+LDFLAGS_u-boot += -pic
+endif
+
 ifeq ($(CONFIG_SYS_LITTLE_ENDIAN),y)
 PLATFORM_ELFFLAGS += -B microblaze $(OBJCOPYFLAGS) -O elf32-microblazeel
 else
diff --git a/arch/microblaze/cpu/Makefile b/arch/microblaze/cpu/Makefile
index f7a83d07b6f6..1feffc6a97c0 100644
--- a/arch/microblaze/cpu/Makefile
+++ b/arch/microblaze/cpu/Makefile
@@ -6,4 +6,5 @@
 extra-y	= start.o
 obj-y	= irq.o
 obj-y	+= interrupts.o cache.o exception.o timer.o
+obj-$(CONFIG_STATIC_RELA)	+= relocate.o
 obj-$(CONFIG_SPL_BUILD)	+= spl.o
diff --git a/arch/microblaze/cpu/relocate.c b/arch/microblaze/cpu/relocate.c
new file mode 100644
index 000000000000..b00d02b1dfcc
--- /dev/null
+++ b/arch/microblaze/cpu/relocate.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2022 Advanced Micro Devices, Inc
+ * Michal Simek <michal.simek@amd.com>
+ */
+
+#include <common.h>
+#include <elf.h>
+
+#define R_MICROBLAZE_NONE	0
+#define R_MICROBLAZE_32		1
+#define R_MICROBLAZE_REL	16
+#define R_MICROBLAZE_GLOB_DAT	18
+
+/**
+ * mb_fix_rela - update relocation to new address
+ * @reloc_addr: new relocation address
+ * @verbose: enable version messages
+ * @rela_start: rela section start
+ * @rela_end: rela section end
+ * @dyn_start: dynamic section start
+ * @origin_addr: address where u-boot starts(doesn't need to be CONFIG_SYS_TEXT_BASE)
+ */
+void mb_fix_rela(u32 reloc_addr, u32 verbose, u32 rela_start,
+		 u32 rela_end, u32 dyn_start, u32 origin_addr)
+{
+	u32 num, type, mask, i, reloc_off;
+
+	/*
+	 * Return in case u-boot.elf is used directly.
+	 * Skip it when u-boot.bin is loaded to different address than
+	 * CONFIG_SYS_TEXT_BASE. In this case relocation is necessary to run.
+	 */
+	if (reloc_addr == CONFIG_SYS_TEXT_BASE) {
+		debug_cond(verbose,
+			   "Relocation address is the same - skip relocation\n");
+		return;
+	}
+
+	reloc_off = reloc_addr - origin_addr;
+
+	debug_cond(verbose, "Relocation address:\t0x%08x\n", reloc_addr);
+	debug_cond(verbose, "Relocation offset:\t0x%08x\n", reloc_off);
+	debug_cond(verbose, "Origin address:\t0x%08x\n", origin_addr);
+	debug_cond(verbose, "Rela start:\t0x%08x\n", rela_start);
+	debug_cond(verbose, "Rela end:\t0x%08x\n", rela_end);
+	debug_cond(verbose, "Dynsym start:\t0x%08x\n", dyn_start);
+
+	num = (rela_end - rela_start) / sizeof(Elf32_Rela);
+
+	debug_cond(verbose, "Number of entries:\t%u\n", num);
+
+	for (i = 0; i < num; i++) {
+		Elf32_Rela *rela;
+		u32 temp;
+
+		rela = (Elf32_Rela *)(rela_start + sizeof(Elf32_Rela) * i);
+
+		mask = 0xffULL; /* would be different on 32-bit */
+		type = rela->r_info & mask;
+
+		debug_cond(verbose, "\nRela possition:\t%d/0x%x\n",
+			   i, (u32)rela);
+
+		switch (type) {
+		case R_MICROBLAZE_REL:
+			temp = *(u32 *)rela->r_offset;
+
+			debug_cond(verbose, "Type:\tREL\n");
+			debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
+			debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
+			debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
+			debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
+
+			rela->r_offset += reloc_off;
+			rela->r_addend += reloc_off;
+
+			temp = *(u32 *)rela->r_offset;
+			temp += reloc_off;
+			*(u32 *)rela->r_offset = temp;
+
+			debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
+			debug_cond(verbose, "New:Rela r_addend:\t0x%x\n", rela->r_addend);
+			debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
+			break;
+		case R_MICROBLAZE_32:
+		case R_MICROBLAZE_GLOB_DAT:
+			debug_cond(verbose, "Type:\t(32/GLOB) %u\n", type);
+			debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
+			debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
+			debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
+			debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
+
+			rela->r_offset += reloc_off;
+
+			temp = *(u32 *)rela->r_offset;
+			temp += reloc_off;
+			*(u32 *)rela->r_offset = temp;
+
+			debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
+			debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
+			break;
+		case R_MICROBLAZE_NONE:
+			debug_cond(verbose, "R_MICROBLAZE_NONE - skip\n");
+			break;
+		default:
+			debug_cond(verbose, "warning: unsupported relocation type %d at %x\n",
+				   type, rela->r_offset);
+		}
+	}
+}
diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S
index 72b0f3354731..9a661e785f6d 100644
--- a/arch/microblaze/cpu/start.S
+++ b/arch/microblaze/cpu/start.S
@@ -10,8 +10,16 @@
 #include <asm-offsets.h>
 #include <config.h>
 
+#if defined(CONFIG_STATIC_RELA)
+#define SYM_ADDR(reg, reg_add, symbol)	\
+	mfs	r20, rpc; \
+	addik	r20, r20, _GLOBAL_OFFSET_TABLE_ + 8; \
+	lwi	reg, r20, symbol@GOT; \
+	addk	reg, reg reg_add;
+#else
 #define SYM_ADDR(reg, reg_add, symbol)	\
 	addi	reg, reg_add, symbol
+#endif
 
 	.text
 	.global _start
@@ -27,6 +35,39 @@ _start:
 	addi	r1, r0, CONFIG_SPL_STACK_ADDR
 #else
 	add	r1, r0, r20
+#if defined(CONFIG_STATIC_RELA)
+	bri	1f
+
+	/* Force alignment for easier ASM code below */
+#define ALIGNMENT_ADDR	0x20
+	.align	4
+uboot_dyn_start:
+	.word	__rel_dyn_start
+
+uboot_dyn_end:
+	.word	__rel_dyn_end
+
+uboot_sym_start:
+	.word	__dyn_sym_start
+1:
+
+	addi	r5, r20, 0
+	add	r6, r0, r0
+
+	lwi	r7, r20, ALIGNMENT_ADDR
+	addi	r7, r7, -CONFIG_SYS_TEXT_BASE
+	add	r7, r7, r5
+	lwi	r8, r20, ALIGNMENT_ADDR + 0x4
+	addi	r8, r8, -CONFIG_SYS_TEXT_BASE
+	add	r8, r8, r5
+	lwi	r9, r20, ALIGNMENT_ADDR + 0x8
+	addi	r9, r9, -CONFIG_SYS_TEXT_BASE
+	add	r9, r9, r5
+	addi	r10, r0, CONFIG_SYS_TEXT_BASE
+
+	brlid	r15, mb_fix_rela
+	nop
+#endif
 #endif
 
 	addi	r1, r1, -4	/* Decrement SP to top of memory */
@@ -297,6 +338,30 @@ relocate_code:
 	brlid	r15, __setup_exceptions
 	nop
 
+#if defined(CONFIG_STATIC_RELA)
+	/* reloc_offset is current location */
+	SYM_ADDR(r10, r0, _start)
+
+	/* r5 new address where I should copy code */
+	add	r5, r0, r7 /* Move reloc addr to r5 */
+
+	/* Verbose message */
+	addi	r6, r0, 0
+
+	SYM_ADDR(r7, r0, __rel_dyn_start)
+	rsub	r7, r10, r7
+	add	r7, r7, r5
+	SYM_ADDR(r8, r0, __rel_dyn_end)
+	rsub	r8, r10, r8
+	add	r8, r8, r5
+	SYM_ADDR(r9, r0, __dyn_sym_start)
+	rsub	r9, r10, r9
+	add	r9, r9, r5
+	brlid	r15, mb_fix_rela
+	nop
+
+	/* end of code which does relocation */
+#else
 	/* Check if GOT exist */
 	addik	r21, r23, _got_start
 	addik	r22, r23, _got_end
@@ -314,6 +379,7 @@ relocate_code:
 	cmpu	r12, r21, r22 /* Check if this cross boundary */
 	bneid	r12, 3b
 	addik	r21. r21, 4
+#endif
 
 	/* Flush caches to ensure consistency */
 	addik	r5, r0, 0
diff --git a/arch/microblaze/cpu/u-boot.lds b/arch/microblaze/cpu/u-boot.lds
index 2b316cc7f5a5..821cc55d7b30 100644
--- a/arch/microblaze/cpu/u-boot.lds
+++ b/arch/microblaze/cpu/u-boot.lds
@@ -46,6 +46,20 @@ SECTIONS
 	}
 	__init_end = . ;
 
+	. = ALIGN(4);
+	__rel_dyn_start = .;
+	.rela.dyn : {
+		*(.rela.dyn)
+	}
+	__rel_dyn_end = .;
+
+	. = ALIGN(4);
+	__dyn_sym_start = .;
+	.dynsym : {
+		*(.dynsym)
+	}
+	__dyn_sym_end = .;
+
 	.bss ALIGN(0x4):
 	{
 		__bss_start = .;
diff --git a/common/board_f.c b/common/board_f.c
index 51d2f3c365e9..a5666ca77c24 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -684,6 +684,8 @@ static int setup_reloc(void)
 #ifdef CONFIG_SYS_TEXT_BASE
 #ifdef ARM
 		gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start;
+#elif defined(CONFIG_MICROBLAZE)
+		gd->reloc_off = gd->relocaddr - (u32)_start;
 #elif defined(CONFIG_M68K)
 		/*
 		 * On all ColdFire arch cpu, monitor code starts always
-- 
2.36.1


  parent reply	other threads:[~2022-06-15 13:25 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-15 13:20 [PATCH v4 00/23] microblaze: Add support for full relocation Michal Simek
2022-06-15 13:20 ` [PATCH v4 01/23] tools: relocate-rela: Open binary u-boot file later Michal Simek
2022-06-15 13:20 ` [PATCH v4 02/23] Makefile: Fix description for relocate-rela parameters Michal Simek
2022-06-15 13:20 ` [PATCH v4 03/23] tools: relocate-rela: Use global variables Michal Simek
2022-06-15 13:21 ` [PATCH v4 04/23] tools: relocate-rela: Read rela start/end directly from ELF Michal Simek
2022-06-15 13:21 ` [PATCH v4 05/23] microblaze: Switch absolute branches to relative Michal Simek
2022-06-15 13:21 ` [PATCH v4 06/23] microblaze: Fix stack protection behavior Michal Simek
2022-06-15 13:21 ` [PATCH v4 07/23] microblaze: Fix early stack allocation Michal Simek
2022-06-15 13:21 ` [PATCH v4 08/23] microblaze: Remove CONFIG_TEXT_BASE from code Michal Simek
2022-06-15 13:21 ` [PATCH v4 09/23] microblaze: Fix typo in exception.c Michal Simek
2022-06-15 13:21 ` [PATCH v4 10/23] mips: Move endianness selection to arch/Kconfig Michal Simek
2022-06-15 13:21 ` [PATCH v4 11/23] microblaze: Enable REMAKE_ELF Michal Simek
2022-06-15 13:21 ` [PATCH v4 12/23] microblaze: Separate code end substraction Michal Simek
2022-06-15 13:21 ` [PATCH v4 13/23] microblaze: Change stack protection address to new stack address Michal Simek
2022-06-15 13:21 ` [PATCH v4 14/23] microblaze: Optimize register usage in relocate_code Michal Simek
2022-06-15 13:21 ` [PATCH v4 15/23] microblaze: Remove code around r20 in relocate_code() Michal Simek
2022-06-15 13:21 ` [PATCH v4 16/23] microblaze: Remove _start symbol handling at U-Boot start Michal Simek
2022-06-15 13:21 ` [PATCH v4 17/23] microblaze: Add comment about reset location Michal Simek
2022-06-15 13:21 ` [PATCH v4 18/23] microblaze: Create SYM_ADDR macro to deal with symbols Michal Simek
2022-06-15 13:21 ` [PATCH v4 19/23] tools: relocate-rela: Extract elf64 reloc to special function Michal Simek
2022-06-15 13:21 ` [PATCH v4 20/23] tools: relocate-rela: Check that relocation works only for EM_AARCH64 Michal Simek
2022-06-15 13:21 ` [PATCH v4 21/23] tools: relocate-rela: Add support for elf32 decoding Michal Simek
2022-06-15 13:21 ` [PATCH v4 22/23] tools: relocate-rela: Add support for 32bit Microblaze relocation Michal Simek
2022-06-15 13:21 ` Michal Simek [this message]
2022-06-24 12:15 ` [PATCH v4 00/23] microblaze: Add support for full relocation Michal Simek

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=a845670b34925859b2e321875f7588a29f6655f9.1655299267.git.michal.simek@amd.com \
    --to=monstr@monstr.eu \
    --cc=alison.wang@nxp.com \
    --cc=angelo@sysam.it \
    --cc=git@xilinx.com \
    --cc=hs@denx.de \
    --cc=marex@denx.de \
    --cc=ovidiu.panait@windriver.com \
    --cc=rick@andestech.com \
    --cc=sean.anderson@seco.com \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.