powerpc/lib: fix unsafe register handling in wait_ticks
authorMats Kärrman <mats.karrman@tritech.se>
Tue, 9 Apr 2013 15:10:59 +0000 (17:10 +0200)
committerTom Rini <trini@ti.com>
Wed, 10 Apr 2013 14:31:02 +0000 (10:31 -0400)
If watchdog is enabled, the arch/powerpc/lib/ticks.S::wait_ticks() function
calls the function specified by the WATCHDOG_RESET macro.
The wait_ticks function depends on the registers r0, r6 and r7 being
preserved however that is not guaranteed, e.g. if the reset function is a
C function this will probably overwrite r0 and cause an endless loop.

The following patch changes to using r14+r15 instead of r6+r7 (to resemble
what would have been generated by a C compiler) and saves all necessary
registers on the stack.

The patch has been tested on a custom MPC5125 based machine using the 512x
powerpc architecture.

Signed-off-by: Mats Karrman <mats.karrman@tritech.se>
Cc: Wolfgang Denk <wd@denx.de>
Acked-by: Joakim Tjernlund <joakim.tjernlund@transmode.se>
Tested-by: Stefan Roese <sr@denx.de>
arch/powerpc/lib/ticks.S

index 17810395b81be36d26843c69292b102d5ce78dac..63114bb0c5aab624e974cfeb6ae22db477d2db9f 100644 (file)
@@ -50,19 +50,24 @@ wait_ticks:
        stwu    r1, -16(r1)
        mflr    r0              /* save link register */
        stw     r0, 20(r1)      /* Use r0 or GDB will be unhappy */
-       mr      r7, r3          /* save tick count */
+       stw     r14, 12(r1)     /* save used registers */
+       stw     r15, 8(r1)
+       mr      r14, r3         /* save tick count */
        bl      get_ticks       /* Get start time */
 
        /* Calculate end time */
-       addc    r7, r4, r7      /* Compute end time lower */
-       addze   r6, r3          /*     and end time upper */
+       addc    r14, r4, r14    /* Compute end time lower */
+       addze   r15, r3         /*     and end time upper */
 
        WATCHDOG_RESET          /* Trigger watchdog, if needed */
 1:     bl      get_ticks       /* Get current time */
-       subfc   r4, r4, r     /* Subtract current time from end time */
-       subfe.  r3, r3, r6
+       subfc   r4, r4, r14     /* Subtract current time from end time */
+       subfe.  r3, r3, r15
        bge     1b              /* Loop until time expired */
 
-       mtlr    r0              /* restore link register */
+       lwz     r15, 8(r1)      /* restore saved registers */
+       lwz     r14, 12(r1)
+       lwz     r0, 20(r1)
        addi    r1,r1,16
+       mtlr    r0
        blr