aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2012-03-29 14:52:00 -0400
committerChris Metcalf <cmetcalf@tilera.com>2012-04-02 12:12:48 -0400
commite17235382dbb05f70146e141e4b780fd069050dc (patch)
treed4da45df23c48ac7e0e4f61821125174a39e436a
parent5f639fdcd8c186c8128c616e94a7e7b159c968ae (diff)
arch/tile: work around a hardware issue with the return-address stack
In certain circumstances we need to do a bunch of jump-and-link instructions to fill the hardware return-address stack with nonzero values. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
-rw-r--r--arch/tile/include/asm/traps.h6
-rw-r--r--arch/tile/kernel/intvec_64.S12
-rw-r--r--arch/tile/kernel/traps.c6
3 files changed, 22 insertions, 2 deletions
diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h
index 5f20f920f932..e28c3df4176a 100644
--- a/arch/tile/include/asm/traps.h
+++ b/arch/tile/include/asm/traps.h
@@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num);
64 64
65 65
66#ifdef __tilegx__ 66#ifdef __tilegx__
67/* kernel/single_step.c */
67void gx_singlestep_handle(struct pt_regs *, int fault_num); 68void gx_singlestep_handle(struct pt_regs *, int fault_num);
69
70/* kernel/intvec_64.S */
71void fill_ra_stack(void);
68#endif 72#endif
69 73
70#endif /* _ASM_TILE_SYSCALLS_H */ 74#endif /* _ASM_TILE_TRAPS_H */
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 79c93e10ba27..2c181c864ef7 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -1156,6 +1156,18 @@ int_unalign:
1156 push_extra_callee_saves r0 1156 push_extra_callee_saves r0
1157 j do_trap 1157 j do_trap
1158 1158
1159/* Fill the return address stack with nonzero entries. */
1160STD_ENTRY(fill_ra_stack)
1161 {
1162 move r0, lr
1163 jal 1f
1164 }
11651: jal 2f
11662: jal 3f
11673: jal 4f
11684: jrp r0
1169 STD_ENDPROC(fill_ra_stack)
1170
1159/* Include .intrpt1 array of interrupt vectors */ 1171/* Include .intrpt1 array of interrupt vectors */
1160 .section ".intrpt1", "ax" 1172 .section ".intrpt1", "ax"
1161 1173
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 2bb6602a1ee7..32acfd9e23d0 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -289,7 +289,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
289 address = regs->pc; 289 address = regs->pc;
290 break; 290 break;
291#ifdef __tilegx__ 291#ifdef __tilegx__
292 case INT_ILL_TRANS: 292 case INT_ILL_TRANS: {
293 /* Avoid a hardware erratum with the return address stack. */
294 fill_ra_stack();
295
293 signo = SIGSEGV; 296 signo = SIGSEGV;
294 code = SEGV_MAPERR; 297 code = SEGV_MAPERR;
295 if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK) 298 if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
@@ -297,6 +300,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
297 else 300 else
298 address = 0; /* FIXME: GX: single-step for address */ 301 address = 0; /* FIXME: GX: single-step for address */
299 break; 302 break;
303 }
300#endif 304#endif
301 default: 305 default:
302 panic("Unexpected do_trap interrupt number %d", fault_num); 306 panic("Unexpected do_trap interrupt number %d", fault_num);