Re: [PATCH] MIPS: Fix inline assembly in uaccess.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 25 Mar 2022, Feiyang Chen wrote:

> The inline assembly of __put_data_asm() and __put_data_asm_ll32()
> treat memory addresses to be written as input operands, which may
> cause the compiler to incorrectly optimize.

 This part of the change seems conceptually right and qualifies as a bug 
fix.

> Treat these addresses as output operands. BTW, rewrite the inline
> assembly to improve readability.

 However combining it with improvements or clean-ups makes it impossible 
to accept.  We require that changes are self-contained and made one at a 
time.  So if you'd like to move forward with your proposal, then you need 
to split it into individual changes and post them as a patch series, with 
the bug fix first (so that it can be possibly backported as it is) with 
clean-ups following.

 Please have a look through Documentation/process/submitting-patches.rst 
for further details.

> diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
> index c0cede273c7c..dc5bca09f39a 100644
> --- a/arch/mips/include/asm/uaccess.h
> +++ b/arch/mips/include/asm/uaccess.h
> @@ -207,19 +207,19 @@ struct __large_struct { unsigned long buf[100]; };
>  	long __gu_tmp;							\
>  									\
>  	__asm__ __volatile__(						\
> -	"1:	"insn("%1", "%3")"				\n"	\
> +	"1:	"insn("%1", "%2")"				\n"	\
>  	"2:							\n"	\
>  	"	.insn						\n"	\
>  	"	.section .fixup,\"ax\"				\n"	\
> -	"3:	li	%0, %4					\n"	\
> +	"3:	li	%0, %3					\n"	\
>  	"	move	%1, $0					\n"	\
>  	"	j	2b					\n"	\
>  	"	.previous					\n"	\
>  	"	.section __ex_table,\"a\"			\n"	\
>  	"	"__UA_ADDR "\t1b, 3b				\n"	\
>  	"	.previous					\n"	\
> -	: "=r" (__gu_err), "=r" (__gu_tmp)				\
> -	: "0" (0), "o" (__m(addr)), "i" (-EFAULT));			\
> +	: "+r" (__gu_err), "=r" (__gu_tmp)				\
> +	: "m" (__m(addr)), "i" (-EFAULT));				\

 For example you remove input operand #2 by making operand #0 input/output 
one, which is just a syntactic change.  Many years ago GCC had issues with 
input/output operands, which is why we have a separate input and output 
operand here.  I am fairly sure we do not support versions of GCC anymore 
that had those issues, so it is a clean-up perhaps worth making, but such 
a change has to be made with a separate patch.

 You also change the `o' constraint here into `m'.  This actually changes 
the semantics, by permitting any memory reference to be used with `insn'.  
This change is probably invalid, as it could turn `insn' into an assembly 
macro.  Consequently the exception table won't work anymore as there will 
be no entry for the instruction at `1:', which could be a LUI in 32-bit 
code.

 However the use of the `o' constraint here isn't completely safe here 
either, because with the MIPS target it doesn't guarantee an assembly 
instruction will be used that produces a single machine instruction.  The 
reason for using `o' regardless is again GCC, which used not to provide 
better means or they were buggy.

 What we ought to use nowadays is `R' if non-EVA, and more problematically 
GCC doesn't actually provide a suitable constraint for the EVA case (where 
a 9-bit only offset is used in the regular MIPS instruction encoding; for 
microMIPS code `ZC would do), so we'd have to resort to a hack there until 
GCC has been improved.  Obviously our code has worked by chance and I find 
it rather interesting that nobody has noticed the lack of a suitable 
constraint for EVA operations in many years now.

 Overall given that these accesses, and certainly the user ones, will be 
made via pointers I think that for safety the change needs to go in the 
opposite direction and code the memory reference with an explicit base and 
offset like in `__get_data_asm_ll32'.

  Maciej



[Index of Archives]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux