[PARISC] Use FIXUP_BRANCH_CLOBBER to asm clobber list
authorCarlos O'Donell <carlos@parisc-linux.org>
Sat, 22 Apr 2006 20:47:21 +0000 (14:47 -0600)
committerKyle McMartin <kyle@hera.kernel.org>
Tue, 27 Jun 2006 23:28:33 +0000 (23:28 +0000)
Joel Soete noticed correctly that the fixup's clobbers must be listed
as the ASM clobbers. FIXUP_BRANCH in unaligned.c has a new macro which
lists all the clobbers in the fixup, we use this throughout the file
to simplify the process of listing clobbers in the future.

A missing "r1" clobber is added to our uaccess.h for the 64-bit
__put_kernel_asm. Interestingly this is a pretty serious bug since gcc
generates pretty good use of r1 as a temporary and the uses of
__put_kernel_asm are varied and dangerous if r1 is scratched during
an invalid write.

Signed-off-by: Joel Soete <soete.joel@tiscali.be>
Signed-off-by: Carlos O'Donell <carlos@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
arch/parisc/kernel/unaligned.c
include/asm-parisc/uaccess.h

index de0a1b2..92328fb 100644 (file)
@@ -43,6 +43,8 @@
        "\tldil L%%" #lbl ", %%r1\n"                    \
        "\tldo R%%" #lbl "(%%r1), %%r1\n"               \
        "\tbv,n %%r0(%%r1)\n"
+/* If you use FIXUP_BRANCH, then you must list this clobber */
+#define FIXUP_BRANCH_CLOBBER "r1"
 
 /* 1111 1100 0000 0000 0001 0011 1100 0000 */
 #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) 
@@ -157,7 +159,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r20" );
+       : "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -202,7 +204,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -253,7 +255,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=0,vall=0;
@@ -287,7 +289,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (valh), "=r" (vall), "=r" (ret)
        : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
        val=((__u64)valh<<32)|(__u64)vall;
     }
 #endif
@@ -335,7 +337,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19" );
+       : "r19", FIXUP_BRANCH_CLOBBER );
 
        return ret;
 }
@@ -389,7 +391,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 
        return 0;
 }
@@ -450,7 +452,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=(val>>32),vall=(val&0xffffffffl);
@@ -495,7 +497,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r1" );
+       : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
     }
 #endif
 
index f6c417c..d973e8b 100644 (file)
@@ -172,7 +172,11 @@ struct exception_data {
 /*
  * The "__put_user/kernel_asm()" macros tell gcc they read from memory
  * instead of writing. This is because they do not write to any memory
- * gcc knows about, so there are no aliasing issues.
+ * gcc knows about, so there are no aliasing issues. These macros must
+ * also be aware that "fixup_put_user_skip_[12]" are executed in the
+ * context of the fault, and any registers used there must be listed
+ * as clobbers. In this case only "r1" is used by the current routines.
+ * r8/r9 are already listed as err/val.
  */
 
 #ifdef __LP64__
@@ -183,7 +187,8 @@ struct exception_data {
                "\t.dword\t1b,fixup_put_user_skip_1\n"      \
                "\t.previous"                               \
                : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(x), "0"(__pu_err))
+               : "r"(ptr), "r"(x), "0"(__pu_err)           \
+               : "r1")
 
 #define __put_user_asm(stx,x,ptr)                           \
        __asm__ __volatile__ (                              \