nds32: Support relocation.
Enable pie option for relocation.
Signed-off-by: rick <rick@andestech.com>
Cc: Andes <uboot@andestech.com>
diff --git a/arch/nds32/cpu/n1213/ag101/lowlevel_init.S b/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
index 1a94868..abdd340 100644
--- a/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
+++ b/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
@@ -6,6 +6,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+.pic
+
.text
#include <common.h>
@@ -248,16 +250,11 @@
*/
li $r5, AHBC_BSR6_A
lwi $r8, [$r5]
- li $r4, 0xfff00000
+ li $r4, 0xfff00000 /* r4 = bank6 base */
and $r4, $r4, $r8
-
- li $r5, 0x0
- la $r1, relo_base /* get $pc or $lp */
- sub $r2, $r0, $r1
- sethi $r6, hi20(_end)
- ori $r6, $r6, lo12(_end)
- add $r6, $r6, $r2
+ la $r5, _start@GOTOFF
+ la $r6, _end@GOTOFF
1:
lwi.p $r7, [$r5], #4
swi.p $r7, [$r4], #4
diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S
index 8b7f8f4..7b2b637 100644
--- a/arch/nds32/cpu/n1213/start.S
+++ b/arch/nds32/cpu/n1213/start.S
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+.pic
+
#include <asm-offsets.h>
#include <config.h>
#include <common.h>
@@ -116,6 +118,18 @@
*/
reset:
+
+/*
+ * gp = ~0 for burn mode
+ * = ~load_address for load mode
+ */
+reset_gp:
+ .relax_hint 0
+ sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8)
+ .relax_hint 0
+ ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4)
+ add5.pc $gp
+
set_ivb:
li $r0, 0x0
@@ -124,20 +138,31 @@
/* set IVIC, vector size: 4 bytes, base: 0x0 */
mtsr $r0, $ivb
-load_lli:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
- jal load_lowlevel_init
- jral $p0
+ jal lowlevel_init
+/*
+ * gp = ~VMA for burn mode
+ * = ~load_address for load mode
+ */
+update_gp:
+ .relax_hint 0
+ sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8)
+ .relax_hint 0
+ ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4)
+ add5.pc $gp
#endif
/*
+ * do critical initializations first (shall be in short time)
+ * do self_relocation ASAP.
+ */
+
+/*
* Set the N1213 (Whitiger) core to superuser mode
* According to spec, it is already when reset
*/
-turnoff_wtdog:
#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
- jal load_turnoff_watchdog
- jral $p0
+ jal turnoff_watchdog
#endif
/*
@@ -145,7 +170,7 @@
* not when booting from ram
*/
#ifdef CONFIG_INIT_CRITICAL
- bal cpu_init_crit ! Do CPU critical regs init
+ jal cpu_init_crit ! Do CPU critical regs init
#endif
/*
@@ -174,6 +199,11 @@
* after relocating the monitor code.
*
*/
+
+/*
+ * gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode
+ */
+
.globl relocate_code
relocate_code:
move $r4, $r0 /* save addr_sp */
@@ -184,49 +214,43 @@
stack_setup:
move $sp, $r4
- la $r0, _start
-
+ la $r0, _start@GOTOFF
beq $r0, $r6, clear_bss /* skip relocation */
- move $r1, $r6 /* r1 <- scratch for copy_loop */
- la $r3, __bss_start
- sub $r3, $r3, $r0 /* r3 <- __bss_start_ofs */
- add $r2, $r0, $r3 /* r2 <- source end address */
+ la $r1, _end@GOTOFF
+ move $r2, $r6 /* r2 <- scratch for copy_loop */
copy_loop:
lwi.p $r7, [$r0], #4
- swi.p $r7, [$r1], #4
- blt $r0, $r2, copy_loop
+ swi.p $r7, [$r2], #4
+ blt $r0, $r1, copy_loop
/*
* fix relocations related issues
*/
fix_relocations:
- l.w $r0, _TEXT_BASE /* r0 <- Text base */
- sub $r9, $r6, $r0 /* r9 <- relocation offset */
+ l.w $r0, _TEXT_BASE@GOTOFF /* r0 <- Text base */
+ sub $r9, $r6, $r0 /* r9 <- relocation offset */
-fix_got:
-/*
- * Now we want to update GOT.
- *
- * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
- * generated by GNU ld. Skip these reserved entries from relocation.
- */
- la $r2, __got_start /* r2 <- rel __got_start in FLASH */
- add $r2, $r2, $r9 /* r2 <- rel __got_start in RAM */
- la $r3, __got_end /* r3 <- rel __got_end in FLASH */
- add $r3, $r3, $r9 /* r3 <- rel __got_end in RAM */
- addi $r2, $r2, #8 /* skipping first two entries */
-fix_got_loop:
- lwi $r0, [$r2] /* r0 <- location in FLASH to fix up */
- add $r0, $r0, $r9 /* r0 <- location fix up to RAM */
- swi.p $r0, [$r2], #4 /* r0 <- store fix into .got in RAM */
- blt $r2, $r3, fix_got_loop
+ la $r7, __rel_dyn_start@GOTOFF
+ add $r7, $r7, $r9 /* r2 <- rel __got_start in RAM */
+ la $r8, __rel_dyn_end@GOTOFF
+ add $r8, $r8, $r9 /* r2 <- rel __got_start in RAM */
+ li $r3, #0x2a /* R_NDS32_RELATIVE */
+1:
+ lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */
+ bne $r1, $r3, 2f
+
+ add $r0, $r0, $r9
+ add $r2, $r2, $r9
+ sw $r2, [$r0]
+2:
+ blt $r7, $r8, 1b
clear_bss:
- la $r0, __bss_start /* r0 <- rel __bss_start in FLASH */
+ la $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */
add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */
- la $r1, __bss_end /* r1 <- rel __bss_end in RAM */
+ la $r1, __bss_end@GOTOFF /* r1 <- rel __bss_end in RAM */
add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */
li $r2, 0x00000000 /* clear */
@@ -240,7 +264,7 @@
* initialization, now running from RAM.
*/
call_board_init_r:
- la $r0, board_init_r
+ la $r0, board_init_r@GOTOFF
move $lp, $r0 /* offset of board_init_r() */
add $lp, $lp, $r9 /* real address of board_init_r() */
/* setup parameters for board_init_r */
@@ -275,8 +299,8 @@
/* Flush caches and TLB */
/* Invalidate caches */
- bal invalidate_icac
- bal invalidate_dcac
+ jal invalidate_icac
+ jal invalidate_dcac
/* Flush TLB */
mfsr $p0, $MMU_CFG
@@ -299,24 +323,6 @@
2:
ret
-#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-load_lowlevel_init:
- la $r6, lowlevel_init
- la $r7, load_lli + 4
- sub $p0, $r6, $r7
- add $p0, $p0, $lp
-ret
-#endif
-
-#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
-load_turnoff_watchdog:
- la $r6, turnoff_watchdog
- la $r7, turnoff_wtdog + 4
- sub $p0, $r6, $r7
- add $p0, $p0, $lp
-ret
-#endif
-
/*
* Invalidate I$
*/
diff --git a/arch/nds32/cpu/n1213/u-boot.lds b/arch/nds32/cpu/n1213/u-boot.lds
index b88d742..40db0e6 100644
--- a/arch/nds32/cpu/n1213/u-boot.lds
+++ b/arch/nds32/cpu/n1213/u-boot.lds
@@ -31,25 +31,28 @@
.got : {
__got_start = .;
- *(.got.plt) *(.got)
+ *(.got.plt) *(.got)
__got_end = .;
}
- . = .;
-
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
-
+ /DISCARD/ : { *(.rela.plt*) }
+ .rela.dyn : {
+ __rel_dyn_start = .;
+ *(.rela*)
+ __rel_dyn_end = .;
+ }
_end = .;
.bss : {
__bss_start = .;
*(.bss)
- . = ALIGN(4);
+ . = ALIGN(4);
__bss_end = .;
}