[PARISC] Use FIXUP_BRANCH_CLOBBER to asm clobber list
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>
This commit is contained in:
Родитель
c8224e0074
Коммит
3fd3a74f45
|
@ -43,6 +43,8 @@
|
||||||
"\tldil L%%" #lbl ", %%r1\n" \
|
"\tldil L%%" #lbl ", %%r1\n" \
|
||||||
"\tldo R%%" #lbl "(%%r1), %%r1\n" \
|
"\tldo R%%" #lbl "(%%r1), %%r1\n" \
|
||||||
"\tbv,n %%r0(%%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 */
|
/* 1111 1100 0000 0000 0001 0011 1100 0000 */
|
||||||
#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6)
|
#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"
|
" .previous\n"
|
||||||
: "=r" (val), "=r" (ret)
|
: "=r" (val), "=r" (ret)
|
||||||
: "0" (val), "r" (saddr), "r" (regs->isr)
|
: "0" (val), "r" (saddr), "r" (regs->isr)
|
||||||
: "r20" );
|
: "r20", FIXUP_BRANCH_CLOBBER );
|
||||||
|
|
||||||
DPRINTF("val = 0x" RFMT "\n", val);
|
DPRINTF("val = 0x" RFMT "\n", val);
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (val), "=r" (ret)
|
: "=r" (val), "=r" (ret)
|
||||||
: "0" (val), "r" (saddr), "r" (regs->isr)
|
: "0" (val), "r" (saddr), "r" (regs->isr)
|
||||||
: "r19", "r20" );
|
: "r19", "r20", FIXUP_BRANCH_CLOBBER );
|
||||||
|
|
||||||
DPRINTF("val = 0x" RFMT "\n", val);
|
DPRINTF("val = 0x" RFMT "\n", val);
|
||||||
|
|
||||||
|
@ -253,7 +255,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (val), "=r" (ret)
|
: "=r" (val), "=r" (ret)
|
||||||
: "0" (val), "r" (saddr), "r" (regs->isr)
|
: "0" (val), "r" (saddr), "r" (regs->isr)
|
||||||
: "r19", "r20" );
|
: "r19", "r20", FIXUP_BRANCH_CLOBBER );
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
unsigned long valh=0,vall=0;
|
unsigned long valh=0,vall=0;
|
||||||
|
@ -287,7 +289,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (valh), "=r" (vall), "=r" (ret)
|
: "=r" (valh), "=r" (vall), "=r" (ret)
|
||||||
: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
|
: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
|
||||||
: "r19", "r20" );
|
: "r19", "r20", FIXUP_BRANCH_CLOBBER );
|
||||||
val=((__u64)valh<<32)|(__u64)vall;
|
val=((__u64)valh<<32)|(__u64)vall;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -335,7 +337,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (ret)
|
: "=r" (ret)
|
||||||
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
||||||
: "r19" );
|
: "r19", FIXUP_BRANCH_CLOBBER );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -389,7 +391,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (ret)
|
: "=r" (ret)
|
||||||
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
||||||
: "r19", "r20", "r21", "r22", "r1" );
|
: "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -450,7 +452,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
: "=r" (ret)
|
: "=r" (ret)
|
||||||
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
: "r" (val), "r" (regs->ior), "r" (regs->isr)
|
||||||
: "r19", "r20", "r21", "r22", "r1" );
|
: "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
unsigned long valh=(val>>32),vall=(val&0xffffffffl);
|
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"
|
" .previous\n"
|
||||||
: "=r" (ret)
|
: "=r" (ret)
|
||||||
: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
|
: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
|
||||||
: "r19", "r20", "r21", "r1" );
|
: "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,11 @@ struct exception_data {
|
||||||
/*
|
/*
|
||||||
* The "__put_user/kernel_asm()" macros tell gcc they read from memory
|
* 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
|
* 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__
|
#ifdef __LP64__
|
||||||
|
@ -183,7 +187,8 @@ struct exception_data {
|
||||||
"\t.dword\t1b,fixup_put_user_skip_1\n" \
|
"\t.dword\t1b,fixup_put_user_skip_1\n" \
|
||||||
"\t.previous" \
|
"\t.previous" \
|
||||||
: "=r"(__pu_err) \
|
: "=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) \
|
#define __put_user_asm(stx,x,ptr) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
|
|
Загрузка…
Ссылка в новой задаче