Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5bdbd4fa authored by Srinivas KANDAGATLA's avatar Srinivas KANDAGATLA Committed by Paul Mundt
Browse files

sh: Fix up xchg/cmpxchg corruption with gUSA RB.

gUSA special cases r15 for part of its login/out sequence, meaning that
any parameters need to be explicitly prohibited from accidentally being
assigned that particular register, and the compiler ultimately needs to
use a temporary instead.

Certain configurations have begun generating code paths that do indeed
get allocated r15, resulting in immediate corruption of the exchanged
value. This was observed in (amongst others) exit_mm() code generation
where the xchg_u32 call was immediately corrupting a structure address.

As this is a general gUSA restriction, the rest of the users likewise
need to be updated to ensure sensible constraints.

References: https://bugzilla.stlinux.com/show_bug.cgi?id=11229


Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@st.com>
Reviewed-by: default avatarStuart Menefy <stuart.menefy@st.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 363e9f05
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -15,8 +15,9 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
		"   mov.l   %2,   @%1     \n\t" /* store new value */
		"1: mov     r1,   r15     \n\t" /* LOGOUT */
		: "=&r" (retval),
		  "+r"  (m)
		: "r"   (val)
		  "+r"  (m),
		  "+r"  (val)		/* inhibit r15 overloading */
		:
		: "memory", "r0", "r1");

	return retval;
@@ -36,8 +37,9 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
		"   mov.b   %2,   @%1     \n\t" /* store new value */
		"1: mov     r1,   r15     \n\t" /* LOGOUT */
		: "=&r" (retval),
		  "+r"  (m)
		: "r"   (val)
		  "+r"  (m),
		  "+r"  (val)		/* inhibit r15 overloading */
		:
		: "memory" , "r0", "r1");

	return retval;
@@ -54,13 +56,14 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
		"   nop                   \n\t"
		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
		"   mov    #-8,   r15     \n\t" /* LOGIN */
		"   mov.l  @%1,   %0      \n\t" /* load  old value */
		"   cmp/eq  %0,   %2      \n\t"
		"   mov.l  @%3,   %0      \n\t" /* load  old value */
		"   cmp/eq  %0,   %1      \n\t"
		"   bf            1f      \n\t" /* if not equal */
		"   mov.l   %3,   @%1     \n\t" /* store new value */
		"   mov.l   %2,   @%3     \n\t" /* store new value */
		"1: mov     r1,   r15     \n\t" /* LOGOUT */
		: "=&r" (retval)
		:  "r"  (m), "r"  (old), "r"  (new)
		: "=&r" (retval),
		  "+r"  (old), "+r"  (new) /* old or new can be r15 */
		:  "r"  (m)
		: "memory" , "r0", "r1", "t");

	return retval;