diff options
author | Andreas Bießmann <andreas@biessmann.de> | 2013-10-24 06:31:04 -0400 |
---|---|---|
committer | Hans-Christian Egtvedt <hegtvedt@cisco.com> | 2013-11-20 03:53:21 -0500 |
commit | d617b338bbfdd77e9cbd8e7dc949cee3dd73d575 (patch) | |
tree | fb8f14a63ccc6338ec5acc89dfdeb8b449461ff2 /arch/avr32 | |
parent | 7a2a74f4b856993218aa7cdeeb6c3103101340db (diff) |
avr32: fix out-of-range jump in large kernels
This patch fixes following error (for big kernels):
---8<---
arch/avr32/boot/u-boot/head.o: In function `no_tag_table':
(.init.text+0x44): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `bad_return':
(.ex.text+0x236): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o
--->8---
It comes up when the kernel increases and 'panic()' is too far away to fit in
the +/- 2MiB range. Which in turn issues from the 21-bit displacement in
'br{cond4}' mnemonic which is one of the two ways to do jumps (rjmp has just
10-bit displacement and therefore a way smaller range). This fact was stated
before in 8d29b7b9f81d6b83d869ff054e6c189d6da73f1f.
One solution to solve this is to add a local storage for the symbol address
and just load the $pc with that value.
Signed-off-by: Andreas Bießmann <andreas@biessmann.de>
Acked-by: Hans-Christian Egtvedt <egtvedt@samfundet.no>
Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/boot/u-boot/head.S | 5 | ||||
-rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 3 |
2 files changed, 6 insertions, 2 deletions
diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S index d36d865308df..2ffc298f061b 100644 --- a/arch/avr32/boot/u-boot/head.S +++ b/arch/avr32/boot/u-boot/head.S | |||
@@ -73,8 +73,11 @@ init_sr: | |||
73 | .long 0x007f0000 /* Supervisor mode, everything masked */ | 73 | .long 0x007f0000 /* Supervisor mode, everything masked */ |
74 | stack_addr: | 74 | stack_addr: |
75 | .long init_thread_union | 75 | .long init_thread_union |
76 | panic_addr: | ||
77 | .long panic | ||
76 | 78 | ||
77 | no_tag_table: | 79 | no_tag_table: |
78 | sub r12, pc, (. - 2f) | 80 | sub r12, pc, (. - 2f) |
79 | bral panic | 81 | /* branch to panic() which can be far away with that construct */ |
82 | lddpc pc, panic_addr | ||
80 | 2: .asciz "Boot loader didn't provide correct magic number\n" | 83 | 2: .asciz "Boot loader didn't provide correct magic number\n" |
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 9899d3cc6f03..7301f4806bbe 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -401,9 +401,10 @@ handle_critical: | |||
401 | /* We should never get here... */ | 401 | /* We should never get here... */ |
402 | bad_return: | 402 | bad_return: |
403 | sub r12, pc, (. - 1f) | 403 | sub r12, pc, (. - 1f) |
404 | bral panic | 404 | lddpc pc, 2f |
405 | .align 2 | 405 | .align 2 |
406 | 1: .asciz "Return from critical exception!" | 406 | 1: .asciz "Return from critical exception!" |
407 | 2: .long panic | ||
407 | 408 | ||
408 | .align 1 | 409 | .align 1 |
409 | do_bus_error_write: | 410 | do_bus_error_write: |