[U-Boot-Users] [PATCH 0/5][MIPS] Fix several problems on relocation

I've pushed the following patchset on top of the upstream:
The following changes since commit 5441f61a3d8b7034f19fc1361183e936198e6dbb: Detlev Zundel (1): Fix two typos.
are available in the git repository at:
git://www.denx.de/git/u-boot-mips.git testing
Shinya Kuribayashi (5): [MIPS] u-boot.lds: Remove duplicated .sdata section [MIPS] u-boot.lds: Fix __got_start and __got_end [MIPS] Fix $gp usage [MIPS] u-boot.lds: Define _gp in a standard manner [MIPS] Add PIC-related switches to PLATFORM_{CPP,LD}FLAGS and cleanup
board/dbau1x00/u-boot.lds | 14 +++++++------- board/gth2/u-boot.lds | 14 +++++++------- board/incaip/u-boot.lds | 14 +++++++------- board/pb1x00/u-boot.lds | 14 +++++++------- board/purple/u-boot.lds | 14 +++++++------- board/tb0229/u-boot.lds | 14 +++++++------- cpu/mips/config.mk | 4 +--- cpu/mips/start.S | 19 +++++++++++++------ examples/mips.lds | 14 +++++++------- mips_config.mk | 25 +++++++++++++++++++++++++ 10 files changed, 88 insertions(+), 58 deletions(-)
These patches mainly try to fix an outstanding mips bug:
http://article.gmane.org/gmane.comp.boot-loaders.u-boot/25533 http://article.gmane.org/gmane.comp.boot-loaders.u-boot/22160 http://article.gmane.org/gmane.comp.boot-loaders.u-boot/19550 http://article.gmane.org/gmane.comp.boot-loaders.u-boot/18887 http://article.gmane.org/gmane.comp.boot-loaders.u-boot/14935
As already discussed, the cause of this bug is a misalignment between __got_start and _GLOBAL_OFFSET_TABLE_. The __got_start misalignment makes num_got_entries larger than needed. As a result, we update GOT entries too many and corrupt top of the u_boot_cmd data. This will be fixed by __got_{start,end} cleanups in linker scripts.
In addition to fixing above, I've takan $gp usage fix suggested by Vlad, and cleaned up linker scripts, etc. Please review and give it a try.
thanks,
Shinya

From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com ---
board/dbau1x00/u-boot.lds | 3 --- board/gth2/u-boot.lds | 3 --- board/incaip/u-boot.lds | 3 --- board/pb1x00/u-boot.lds | 3 --- board/purple/u-boot.lds | 3 --- board/tb0229/u-boot.lds | 3 --- examples/mips.lds | 3 --- 7 files changed, 0 insertions(+), 21 deletions(-)
diff --git a/board/dbau1x00/u-boot.lds b/board/dbau1x00/u-boot.lds index 10c9917..75a3af6 100644 --- a/board/dbau1x00/u-boot.lds +++ b/board/dbau1x00/u-boot.lds @@ -43,9 +43,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/board/gth2/u-boot.lds b/board/gth2/u-boot.lds index 8ba0b6d..69c8c9d 100644 --- a/board/gth2/u-boot.lds +++ b/board/gth2/u-boot.lds @@ -43,9 +43,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/board/incaip/u-boot.lds b/board/incaip/u-boot.lds index 10c9917..75a3af6 100644 --- a/board/incaip/u-boot.lds +++ b/board/incaip/u-boot.lds @@ -43,9 +43,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/board/pb1x00/u-boot.lds b/board/pb1x00/u-boot.lds index a2d19a8..865be77 100644 --- a/board/pb1x00/u-boot.lds +++ b/board/pb1x00/u-boot.lds @@ -43,9 +43,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/board/purple/u-boot.lds b/board/purple/u-boot.lds index 1bdac1f..6b3783f 100644 --- a/board/purple/u-boot.lds +++ b/board/purple/u-boot.lds @@ -53,9 +53,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/board/tb0229/u-boot.lds b/board/tb0229/u-boot.lds index 30a2bc5..26d8c81 100644 --- a/board/tb0229/u-boot.lds +++ b/board/tb0229/u-boot.lds @@ -43,9 +43,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .; diff --git a/examples/mips.lds b/examples/mips.lds index 9d9849b..6f31eb7 100644 --- a/examples/mips.lds +++ b/examples/mips.lds @@ -39,9 +39,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- . = ALIGN(4); - .sdata : { *(.sdata) } - _gp = ALIGN(16);
__got_start = .;

From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Ensure that __got_start points to top of the `.got', and __got_end points to bottom as well, so that we never fail to count num_got_entries.
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com ---
board/dbau1x00/u-boot.lds | 8 +++++--- board/gth2/u-boot.lds | 8 +++++--- board/incaip/u-boot.lds | 8 +++++--- board/pb1x00/u-boot.lds | 8 +++++--- board/purple/u-boot.lds | 8 +++++--- board/tb0229/u-boot.lds | 8 +++++--- examples/mips.lds | 8 +++++--- 7 files changed, 35 insertions(+), 21 deletions(-)
diff --git a/board/dbau1x00/u-boot.lds b/board/dbau1x00/u-boot.lds index 75a3af6..9c71ef7 100644 --- a/board/dbau1x00/u-boot.lds +++ b/board/dbau1x00/u-boot.lds @@ -45,9 +45,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/board/gth2/u-boot.lds b/board/gth2/u-boot.lds index 69c8c9d..0ab42db 100644 --- a/board/gth2/u-boot.lds +++ b/board/gth2/u-boot.lds @@ -45,9 +45,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/board/incaip/u-boot.lds b/board/incaip/u-boot.lds index 75a3af6..9c71ef7 100644 --- a/board/incaip/u-boot.lds +++ b/board/incaip/u-boot.lds @@ -45,9 +45,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/board/pb1x00/u-boot.lds b/board/pb1x00/u-boot.lds index 865be77..7329e6a 100644 --- a/board/pb1x00/u-boot.lds +++ b/board/pb1x00/u-boot.lds @@ -45,9 +45,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/board/purple/u-boot.lds b/board/purple/u-boot.lds index 6b3783f..aa51cbf 100644 --- a/board/purple/u-boot.lds +++ b/board/purple/u-boot.lds @@ -55,9 +55,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/board/tb0229/u-boot.lds b/board/tb0229/u-boot.lds index 26d8c81..148f5e6 100644 --- a/board/tb0229/u-boot.lds +++ b/board/tb0229/u-boot.lds @@ -45,9 +45,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }
diff --git a/examples/mips.lds b/examples/mips.lds index 6f31eb7..3bd573c 100644 --- a/examples/mips.lds +++ b/examples/mips.lds @@ -41,9 +41,11 @@ SECTIONS
_gp = ALIGN(16);
- __got_start = .; - .got : { *(.got) } - __got_end = .; + .got : { + __got_start = .; + *(.got) + __got_end = .; + }
.sdata : { *(.sdata) }

From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Now we load $gp with _GLOBAL_OFFSET_TABLE_, but this is incorrect use. As a general principle, we should use _gp for $gp.
Thanks to linker script's help we fortunately have _gp which equals to _GLOBAL_OFFSET_TABLE_. But once _gp gets out of alignment, we will not be able to access to GOT entires, global variables and procedure entry points. The right thing to do is to use _gp.
This patch also introduce a new symbol `.gpword _GLOBAL_OFFSET_TABLE_' which holds the offset from _gp. When updating GOT entries, we use this offset and _gp to calculate the final _GLOBAL_OFFSET_TABLE_.
This patch is originally submitted by Vlad Lungu vlad@comsys.ro, then I made some change to leave over num_got_entries.
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com Cc: Vlad Lungu vlad@comsys.ro ---
cpu/mips/start.S | 19 +++++++++++++------ 1 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/cpu/mips/start.S b/cpu/mips/start.S index e91e213..074d01d 100644 --- a/cpu/mips/start.S +++ b/cpu/mips/start.S @@ -234,11 +234,11 @@ reset: li t0, CONF_CM_UNCACHED mtc0 t0, CP0_CONFIG
- /* Initialize GOT pointer. + /* Initialize $gp. */ bal 1f nop - .word _GLOBAL_OFFSET_TABLE_ + .word _gp 1: move gp, ra lw t1, 0(ra) @@ -306,9 +306,9 @@ relocate_code: move t1, a2
/* - * Fix GOT pointer: + * Fix $gp: * - * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address + * New $gp = (Old $gp - CFG_MONITOR_BASE) + Destination Address */ move t6, gp sub gp, CFG_MONITOR_BASE @@ -341,15 +341,22 @@ relocate_code: j t0 nop
+ .gpword _GLOBAL_OFFSET_TABLE_ /* _GLOBAL_OFFSET_TABLE_ - _gp */ .word uboot_end_data .word uboot_end .word num_got_entries
in_ram: - /* Now we want to update 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. */ lw t3, -4(t0) /* t3 <-- num_got_entries */ - addi t4, gp, 8 /* Skipping first two entries. */ + lw t4, -16(t0) /* t4 <-- (_GLOBAL_OFFSET_TABLE_ - _gp) */ + add t4, t4, gp /* t4 now holds _GLOBAL_OFFSET_TABLE_ */ + addi t4, t4, 8 /* Skipping first two entries. */ li t2, 2 1: lw t1, 0(t4)

From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com ---
board/dbau1x00/u-boot.lds | 3 ++- board/gth2/u-boot.lds | 3 ++- board/incaip/u-boot.lds | 3 ++- board/pb1x00/u-boot.lds | 3 ++- board/purple/u-boot.lds | 3 ++- board/tb0229/u-boot.lds | 3 ++- examples/mips.lds | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/board/dbau1x00/u-boot.lds b/board/dbau1x00/u-boot.lds index 9c71ef7..9639b81 100644 --- a/board/dbau1x00/u-boot.lds +++ b/board/dbau1x00/u-boot.lds @@ -43,7 +43,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/board/gth2/u-boot.lds b/board/gth2/u-boot.lds index 0ab42db..90432cb 100644 --- a/board/gth2/u-boot.lds +++ b/board/gth2/u-boot.lds @@ -43,7 +43,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/board/incaip/u-boot.lds b/board/incaip/u-boot.lds index 9c71ef7..9639b81 100644 --- a/board/incaip/u-boot.lds +++ b/board/incaip/u-boot.lds @@ -43,7 +43,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/board/pb1x00/u-boot.lds b/board/pb1x00/u-boot.lds index 7329e6a..363d974 100644 --- a/board/pb1x00/u-boot.lds +++ b/board/pb1x00/u-boot.lds @@ -43,7 +43,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/board/purple/u-boot.lds b/board/purple/u-boot.lds index aa51cbf..e7ec012 100644 --- a/board/purple/u-boot.lds +++ b/board/purple/u-boot.lds @@ -53,7 +53,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/board/tb0229/u-boot.lds b/board/tb0229/u-boot.lds index 148f5e6..b2fa9f2 100644 --- a/board/tb0229/u-boot.lds +++ b/board/tb0229/u-boot.lds @@ -43,7 +43,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .; diff --git a/examples/mips.lds b/examples/mips.lds index 3bd573c..a770728 100644 --- a/examples/mips.lds +++ b/examples/mips.lds @@ -39,7 +39,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data) }
- _gp = ALIGN(16); + . = .; + _gp = ALIGN(16) + 0x7ff0;
.got : { __got_start = .;

From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com ---
cpu/mips/config.mk | 4 +--- mips_config.mk | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/cpu/mips/config.mk b/cpu/mips/config.mk index b29986e..1f2860e 100644 --- a/cpu/mips/config.mk +++ b/cpu/mips/config.mk @@ -35,6 +35,4 @@ else ENDIANNESS = -EB endif
-MIPSFLAGS += $(ENDIANNESS) -mabicalls - -PLATFORM_CPPFLAGS += $(MIPSFLAGS) +PLATFORM_CPPFLAGS += $(ENDIANNESS) diff --git a/mips_config.mk b/mips_config.mk index d8aa5fa..67fb67d 100644 --- a/mips_config.mk +++ b/mips_config.mk @@ -22,3 +22,28 @@ #
PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__ + +# +# From Linux arch/mips/Makefile +# +# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel +# code since it only slows down the whole thing. At some point we might make +# use of global pointer optimizations but their use of $28 conflicts with +# the current pointer optimization. +# +# The DECStation requires an ECOFF kernel for remote booting, other MIPS +# machines may also. Since BFD is incredibly buggy with respect to +# crossformat linking we rely on the elf2ecoff tool for format conversion. +# +# cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +# cflags-y += -msoft-float +# LDFLAGS_vmlinux += -G 0 -static -n -nostdlib +# MODFLAGS += -mlong-calls +# + +# +# Meanwhile, U-Boot rely on PIC. We add proper switches explicitly. +# +PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic -pipe +PLATFORM_CPPFLAGS += -msoft-float +PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib

In message 471A230F.9050209@ruby.dti.ne.jp you wrote:
From: Shinya Kuribayashi shinya.kuribayashi@necel.com
Signed-off-by: Shinya Kuribayashi shinya.kuribayashi@necel.com
Re this and your other MIPS patches: I would like to relesase U-Boot 1.3.0 soon. Will you send a pull request for all these patches soon? Then I would wait...
Best regards,
Wolfgang Denk

Shinya Kuribayashi wrote:
diff --git a/cpu/mips/config.mk b/cpu/mips/config.mk index b29986e..1f2860e 100644 --- a/cpu/mips/config.mk +++ b/cpu/mips/config.mk @@ -35,6 +35,4 @@ else ENDIANNESS = -EB endif
-MIPSFLAGS += $(ENDIANNESS) -mabicalls
-PLATFORM_CPPFLAGS += $(MIPSFLAGS) +PLATFORM_CPPFLAGS += $(ENDIANNESS)
Err, I should have fixed like this:
-MIPSFLAGS += $(ENDIANNESS) -mabicalls +MIPSFLAGS += $(ENDIANNESS)
already fixed.
Shinya
diff --git a/mips_config.mk b/mips_config.mk index d8aa5fa..67fb67d 100644 --- a/mips_config.mk +++ b/mips_config.mk @@ -22,3 +22,28 @@ #
PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__
+# +# From Linux arch/mips/Makefile +# +# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel +# code since it only slows down the whole thing. At some point we might make +# use of global pointer optimizations but their use of $28 conflicts with +# the current pointer optimization. +# +# The DECStation requires an ECOFF kernel for remote booting, other MIPS +# machines may also. Since BFD is incredibly buggy with respect to +# crossformat linking we rely on the elf2ecoff tool for format conversion. +# +# cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +# cflags-y += -msoft-float +# LDFLAGS_vmlinux += -G 0 -static -n -nostdlib +# MODFLAGS += -mlong-calls +#
+# +# Meanwhile, U-Boot rely on PIC. We add proper switches explicitly. +# +PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic -pipe +PLATFORM_CPPFLAGS += -msoft-float +PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib
participants (2)
-
Shinya Kuribayashi
-
Wolfgang Denk