Commit d785610f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull powerpc fixes from Michael Ellerman:

 - Ensure we never emit lwarx with EH=1 on 32-bit, because some 32-bit
   CPUs trap on it rather than ignoring it as they should.

 - Fix ftrace when building with clang, which was broken by some
   refactoring.

 - A couple of other minor fixes.

Thanks to Christophe Leroy, Naveen N.  Rao, Nick Desaulniers, Ondrej
Mosnacek, Pali Rohár, Russell Currey, and Segher Boessenkool.

* tag 'powerpc-6.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/kexec: Fix build failure from uninitialised variable
  powerpc/ppc-opcode: Fix PPC_RAW_TW()
  powerpc64/ftrace: Fix ftrace for clang builds
  powerpc: Make eh value more explicit when using lwarx
  powerpc: Don't hide eh field of lwarx behind a macro
  powerpc: Fix eh field when calling lwarx on PPC32
parents aea23e7c 83ee9f23
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -140,9 +140,10 @@ static __always_inline bool
arch_atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new)
{
	int r, o = *old;
	unsigned int eh = IS_ENABLED(CONFIG_PPC64);

	__asm__ __volatile__ (
"1:	lwarx	%0,0,%2,%5	# atomic_try_cmpxchg_acquire		\n"
"1:	lwarx	%0,0,%2,%[eh]	# atomic_try_cmpxchg_acquire		\n"
"	cmpw	0,%0,%3							\n"
"	bne-	2f							\n"
"	stwcx.	%4,0,%2							\n"
@@ -150,7 +151,7 @@ arch_atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new)
"\t"	PPC_ACQUIRE_BARRIER "						\n"
"2:									\n"
	: "=&r" (r), "+m" (v->counter)
	: "r" (&v->counter), "r" (o), "r" (new), "i" (IS_ENABLED(CONFIG_PPC64) ? 1 : 0)
	: "r" (&v->counter), "r" (o), "r" (new), [eh] "n" (eh)
	: "cr0", "memory");

	if (unlikely(r != o))
+2 −2
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ static inline unsigned long fn( \
	"bne- 1b\n"					\
	postfix						\
	: "=&r" (old), "=&r" (t)			\
	: "rK" (mask), "r" (p), "i" (IS_ENABLED(CONFIG_PPC64) ? eh : 0)	\
	: "rK" (mask), "r" (p), "n" (eh)		\
	: "cc", "memory");				\
	return (old & mask);				\
}
@@ -171,7 +171,7 @@ static inline unsigned long fn( \
DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
	      PPC_ATOMIC_EXIT_BARRIER, 0)
DEFINE_TESTOP(test_and_set_bits_lock, or, "",
	      PPC_ACQUIRE_BARRIER, 1)
	      PPC_ACQUIRE_BARRIER, IS_ENABLED(CONFIG_PPC64))
DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
	      PPC_ATOMIC_EXIT_BARRIER, 0)

+2 −11
Original line number Diff line number Diff line
@@ -343,6 +343,7 @@
#define __PPC_SPR(r)	((((r) & 0x1f) << 16) | ((((r) >> 5) & 0x1f) << 11))
#define __PPC_RC21	(0x1 << 10)
#define __PPC_PRFX_R(r)	(((r) & 0x1) << 20)
#define __PPC_EH(eh)	(((eh) & 0x1) << 0)

/*
 * Both low and high 16 bits are added as SIGNED additions, so if low 16 bits
@@ -359,16 +360,6 @@
#define PPC_LI_MASK	0x03fffffc
#define PPC_LI(v)	((v) & PPC_LI_MASK)

/*
 * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
 * larx with EH set as an illegal instruction.
 */
#ifdef CONFIG_PPC64
#define __PPC_EH(eh)	(((eh) & 0x1) << 0)
#else
#define __PPC_EH(eh)	0
#endif

/* Base instruction encoding */
#define PPC_RAW_CP_ABORT		(0x7c00068c)
#define PPC_RAW_COPY(a, b)		(PPC_INST_COPY | ___PPC_RA(a) | ___PPC_RB(b))
@@ -580,7 +571,7 @@

#define PPC_RAW_BRANCH(offset)		(0x48000000 | PPC_LI(offset))
#define PPC_RAW_BL(offset)		(0x48000001 | PPC_LI(offset))
#define PPC_RAW_TW(t0, a, b)		(0x7f000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
#define PPC_RAW_TW(t0, a, b)		(0x7c000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
#define PPC_RAW_TRAP()			PPC_RAW_TW(31, 0, 0)
#define PPC_RAW_SETB(t, bfa)		(0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2))

+9 −6
Original line number Diff line number Diff line
@@ -48,10 +48,11 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock)
{
	unsigned long tmp, token;
	unsigned int eh = IS_ENABLED(CONFIG_PPC64);

	token = LOCK_TOKEN;
	__asm__ __volatile__(
"1:	lwarx		%0,0,%2,1\n\
"1:	lwarx		%0,0,%2,%[eh]\n\
	cmpwi		0,%0,0\n\
	bne-		2f\n\
	stwcx.		%1,0,%2\n\
@@ -59,7 +60,7 @@ static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock)
	PPC_ACQUIRE_BARRIER
"2:"
	: "=&r" (tmp)
	: "r" (token), "r" (&lock->slock)
	: "r" (token), "r" (&lock->slock), [eh] "n" (eh)
	: "cr0", "memory");

	return tmp;
@@ -156,9 +157,10 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
static inline long __arch_read_trylock(arch_rwlock_t *rw)
{
	long tmp;
	unsigned int eh = IS_ENABLED(CONFIG_PPC64);

	__asm__ __volatile__(
"1:	lwarx		%0,0,%1,1\n"
"1:	lwarx		%0,0,%1,%[eh]\n"
	__DO_SIGN_EXTEND
"	addic.		%0,%0,1\n\
	ble-		2f\n"
@@ -166,7 +168,7 @@ static inline long __arch_read_trylock(arch_rwlock_t *rw)
	bne-		1b\n"
	PPC_ACQUIRE_BARRIER
"2:"	: "=&r" (tmp)
	: "r" (&rw->lock)
	: "r" (&rw->lock), [eh] "n" (eh)
	: "cr0", "xer", "memory");

	return tmp;
@@ -179,17 +181,18 @@ static inline long __arch_read_trylock(arch_rwlock_t *rw)
static inline long __arch_write_trylock(arch_rwlock_t *rw)
{
	long tmp, token;
	unsigned int eh = IS_ENABLED(CONFIG_PPC64);

	token = WRLOCK_TOKEN;
	__asm__ __volatile__(
"1:	lwarx		%0,0,%2,1\n\
"1:	lwarx		%0,0,%2,%[eh]\n\
	cmpwi		0,%0,0\n\
	bne-		2f\n"
"	stwcx.		%1,0,%2\n\
	bne-		1b\n"
	PPC_ACQUIRE_BARRIER
"2:"	: "=&r" (tmp)
	: "r" (token), "r" (&rw->lock)
	: "r" (token), "r" (&rw->lock), [eh] "n" (eh)
	: "cr0", "memory");

	return tmp;
+4 −4
Original line number Diff line number Diff line
@@ -393,11 +393,11 @@ int ftrace_make_nop(struct module *mod,
 */
static bool expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1)
{
	if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1))
	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
		return ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP()));
	else
		return ppc_inst_equal(op0, ppc_inst(PPC_RAW_BRANCH(8))) &&
		       ppc_inst_equal(op1, ppc_inst(PPC_INST_LD_TOC));
	else
		return ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP()));
}

static int
@@ -412,7 +412,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
	if (copy_inst_from_kernel_nofault(op, ip))
		return -EFAULT;

	if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1) &&
	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) &&
	    copy_inst_from_kernel_nofault(op + 1, ip + 4))
		return -EFAULT;

Loading