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>
This commit is contained in:
@@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num);
|
|||||||
|
|
||||||
|
|
||||||
#ifdef __tilegx__
|
#ifdef __tilegx__
|
||||||
|
/* kernel/single_step.c */
|
||||||
void gx_singlestep_handle(struct pt_regs *, int fault_num);
|
void gx_singlestep_handle(struct pt_regs *, int fault_num);
|
||||||
|
|
||||||
|
/* kernel/intvec_64.S */
|
||||||
|
void fill_ra_stack(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_TILE_SYSCALLS_H */
|
#endif /* _ASM_TILE_TRAPS_H */
|
||||||
|
@@ -1156,6 +1156,18 @@ int_unalign:
|
|||||||
push_extra_callee_saves r0
|
push_extra_callee_saves r0
|
||||||
j do_trap
|
j do_trap
|
||||||
|
|
||||||
|
/* Fill the return address stack with nonzero entries. */
|
||||||
|
STD_ENTRY(fill_ra_stack)
|
||||||
|
{
|
||||||
|
move r0, lr
|
||||||
|
jal 1f
|
||||||
|
}
|
||||||
|
1: jal 2f
|
||||||
|
2: jal 3f
|
||||||
|
3: jal 4f
|
||||||
|
4: jrp r0
|
||||||
|
STD_ENDPROC(fill_ra_stack)
|
||||||
|
|
||||||
/* Include .intrpt1 array of interrupt vectors */
|
/* Include .intrpt1 array of interrupt vectors */
|
||||||
.section ".intrpt1", "ax"
|
.section ".intrpt1", "ax"
|
||||||
|
|
||||||
|
@@ -289,7 +289,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
address = regs->pc;
|
address = regs->pc;
|
||||||
break;
|
break;
|
||||||
#ifdef __tilegx__
|
#ifdef __tilegx__
|
||||||
case INT_ILL_TRANS:
|
case INT_ILL_TRANS: {
|
||||||
|
/* Avoid a hardware erratum with the return address stack. */
|
||||||
|
fill_ra_stack();
|
||||||
|
|
||||||
signo = SIGSEGV;
|
signo = SIGSEGV;
|
||||||
code = SEGV_MAPERR;
|
code = SEGV_MAPERR;
|
||||||
if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
|
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,
|
|||||||
else
|
else
|
||||||
address = 0; /* FIXME: GX: single-step for address */
|
address = 0; /* FIXME: GX: single-step for address */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
panic("Unexpected do_trap interrupt number %d", fault_num);
|
panic("Unexpected do_trap interrupt number %d", fault_num);
|
||||||
|
Reference in New Issue
Block a user