]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
arch/tile: work around a hardware issue with the return-address stack
authorChris Metcalf <cmetcalf@tilera.com>
Thu, 29 Mar 2012 18:52:00 +0000 (14:52 -0400)
committerChris Metcalf <cmetcalf@tilera.com>
Fri, 30 Mar 2012 22:55:45 +0000 (18:55 -0400)
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>
arch/tile/include/asm/traps.h
arch/tile/kernel/intvec_64.S
arch/tile/kernel/traps.c

index 5f20f920f932b6c38e0a8971d1cedfb012dd729c..e28c3df4176a918c09fc56dfa702c17e0f48e401 100644 (file)
@@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num);
 
 
 #ifdef __tilegx__
+/* kernel/single_step.c */
 void gx_singlestep_handle(struct pt_regs *, int fault_num);
+
+/* kernel/intvec_64.S */
+void fill_ra_stack(void);
 #endif
 
-#endif /* _ASM_TILE_SYSCALLS_H */
+#endif /* _ASM_TILE_TRAPS_H */
index 3c1f626dad876963a8a10e2a593917f64e267070..709e2241e9aaf59fae72f26aac732e3f65397823 100644 (file)
@@ -1164,6 +1164,18 @@ int_unalign:
        push_extra_callee_saves r0
        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 */
        .section ".intrpt1", "ax"
 
index 4f47b8a356df68241ae61e459084fb3d5a3ea945..1e91fdac59ba700eb000fc001babb628f089576f 100644 (file)
@@ -288,7 +288,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                address = regs->pc;
                break;
 #ifdef __tilegx__
-       case INT_ILL_TRANS:
+       case INT_ILL_TRANS: {
+               /* Avoid a hardware erratum with the return address stack. */
+               fill_ra_stack();
+
                signo = SIGSEGV;
                code = SEGV_MAPERR;
                if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
@@ -296,6 +299,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                else
                        address = 0;  /* FIXME: GX: single-step for address */
                break;
+       }
 #endif
        default:
                panic("Unexpected do_trap interrupt number %d", fault_num);