* [PATCH v3 3/6] powerpc: move spinlock implementation to simple_spinlock
From: Nicholas Piggin @ 2020-07-06 4:35 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-arch, Peter Zijlstra, Boqun Feng, linux-kernel,
Nicholas Piggin, virtualization, Ingo Molnar, kvm-ppc,
Waiman Long, Will Deacon
In-Reply-To: <20200706043540.1563616-1-npiggin@gmail.com>
To prepare for queued spinlocks. This is a simple rename except to update
preprocessor guard name and a file reference.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/simple_spinlock.h | 292 ++++++++++++++++++
.../include/asm/simple_spinlock_types.h | 21 ++
arch/powerpc/include/asm/spinlock.h | 285 +----------------
arch/powerpc/include/asm/spinlock_types.h | 12 +-
4 files changed, 315 insertions(+), 295 deletions(-)
create mode 100644 arch/powerpc/include/asm/simple_spinlock.h
create mode 100644 arch/powerpc/include/asm/simple_spinlock_types.h
diff --git a/arch/powerpc/include/asm/simple_spinlock.h b/arch/powerpc/include/asm/simple_spinlock.h
new file mode 100644
index 000000000000..e048c041c4a9
--- /dev/null
+++ b/arch/powerpc/include/asm/simple_spinlock.h
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef __ASM_SIMPLE_SPINLOCK_H
+#define __ASM_SIMPLE_SPINLOCK_H
+#ifdef __KERNEL__
+
+/*
+ * Simple spin lock operations.
+ *
+ * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
+ * Rework to support virtual processors
+ *
+ * Type of int is used as a full 64b word is not necessary.
+ *
+ * (the type definitions are in asm/simple_spinlock_types.h)
+ */
+#include <linux/irqflags.h>
+#include <asm/paravirt.h>
+#ifdef CONFIG_PPC64
+#include <asm/paca.h>
+#endif
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+
+#ifdef CONFIG_PPC64
+/* use 0x800000yy when locked, where yy == CPU number */
+#ifdef __BIG_ENDIAN__
+#define LOCK_TOKEN (*(u32 *)(&get_paca()->lock_token))
+#else
+#define LOCK_TOKEN (*(u32 *)(&get_paca()->paca_index))
+#endif
+#else
+#define LOCK_TOKEN 1
+#endif
+
+static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+ return lock.slock == 0;
+}
+
+static inline int arch_spin_is_locked(arch_spinlock_t *lock)
+{
+ smp_mb();
+ return !arch_spin_value_unlocked(*lock);
+}
+
+/*
+ * This returns the old value in the lock, so we succeeded
+ * in getting the lock if the return value is 0.
+ */
+static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock)
+{
+ unsigned long tmp, token;
+
+ token = LOCK_TOKEN;
+ __asm__ __volatile__(
+"1: " PPC_LWARX(%0,0,%2,1) "\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" (&lock->slock)
+ : "cr0", "memory");
+
+ return tmp;
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ return __arch_spin_trylock(lock) == 0;
+}
+
+/*
+ * On a system with shared processors (that is, where a physical
+ * processor is multiplexed between several virtual processors),
+ * there is no point spinning on a lock if the holder of the lock
+ * isn't currently scheduled on a physical processor. Instead
+ * we detect this situation and ask the hypervisor to give the
+ * rest of our timeslice to the lock holder.
+ *
+ * So that we can tell which virtual processor is holding a lock,
+ * we put 0x80000000 | smp_processor_id() in the lock when it is
+ * held. Conveniently, we have a word in the paca that holds this
+ * value.
+ */
+
+#if defined(CONFIG_PPC_SPLPAR)
+/* We only yield to the hypervisor if we are in shared processor mode */
+void splpar_spin_yield(arch_spinlock_t *lock);
+void splpar_rw_yield(arch_rwlock_t *lock);
+#else /* SPLPAR */
+static inline void splpar_spin_yield(arch_spinlock_t *lock) {};
+static inline void splpar_rw_yield(arch_rwlock_t *lock) {};
+#endif
+
+static inline void spin_yield(arch_spinlock_t *lock)
+{
+ if (is_shared_processor())
+ splpar_spin_yield(lock);
+ else
+ barrier();
+}
+
+static inline void rw_yield(arch_rwlock_t *lock)
+{
+ if (is_shared_processor())
+ splpar_rw_yield(lock);
+ else
+ barrier();
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ while (1) {
+ if (likely(__arch_spin_trylock(lock) == 0))
+ break;
+ do {
+ HMT_low();
+ if (is_shared_processor())
+ splpar_spin_yield(lock);
+ } while (unlikely(lock->slock != 0));
+ HMT_medium();
+ }
+}
+
+static inline
+void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
+{
+ unsigned long flags_dis;
+
+ while (1) {
+ if (likely(__arch_spin_trylock(lock) == 0))
+ break;
+ local_save_flags(flags_dis);
+ local_irq_restore(flags);
+ do {
+ HMT_low();
+ if (is_shared_processor())
+ splpar_spin_yield(lock);
+ } while (unlikely(lock->slock != 0));
+ HMT_medium();
+ local_irq_restore(flags_dis);
+ }
+}
+#define arch_spin_lock_flags arch_spin_lock_flags
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ __asm__ __volatile__("# arch_spin_unlock\n\t"
+ PPC_RELEASE_BARRIER: : :"memory");
+ lock->slock = 0;
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+
+#ifdef CONFIG_PPC64
+#define __DO_SIGN_EXTEND "extsw %0,%0\n"
+#define WRLOCK_TOKEN LOCK_TOKEN /* it's negative */
+#else
+#define __DO_SIGN_EXTEND
+#define WRLOCK_TOKEN (-1)
+#endif
+
+/*
+ * This returns the old value in the lock + 1,
+ * so we got a read lock if the return value is > 0.
+ */
+static inline long __arch_read_trylock(arch_rwlock_t *rw)
+{
+ long tmp;
+
+ __asm__ __volatile__(
+"1: " PPC_LWARX(%0,0,%1,1) "\n"
+ __DO_SIGN_EXTEND
+" addic. %0,%0,1\n\
+ ble- 2f\n"
+" stwcx. %0,0,%1\n\
+ bne- 1b\n"
+ PPC_ACQUIRE_BARRIER
+"2:" : "=&r" (tmp)
+ : "r" (&rw->lock)
+ : "cr0", "xer", "memory");
+
+ return tmp;
+}
+
+/*
+ * This returns the old value in the lock,
+ * so we got the write lock if the return value is 0.
+ */
+static inline long __arch_write_trylock(arch_rwlock_t *rw)
+{
+ long tmp, token;
+
+ token = WRLOCK_TOKEN;
+ __asm__ __volatile__(
+"1: " PPC_LWARX(%0,0,%2,1) "\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)
+ : "cr0", "memory");
+
+ return tmp;
+}
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+ while (1) {
+ if (likely(__arch_read_trylock(rw) > 0))
+ break;
+ do {
+ HMT_low();
+ if (is_shared_processor())
+ splpar_rw_yield(rw);
+ } while (unlikely(rw->lock < 0));
+ HMT_medium();
+ }
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ while (1) {
+ if (likely(__arch_write_trylock(rw) == 0))
+ break;
+ do {
+ HMT_low();
+ if (is_shared_processor())
+ splpar_rw_yield(rw);
+ } while (unlikely(rw->lock != 0));
+ HMT_medium();
+ }
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+ return __arch_read_trylock(rw) > 0;
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ return __arch_write_trylock(rw) == 0;
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+ long tmp;
+
+ __asm__ __volatile__(
+ "# read_unlock\n\t"
+ PPC_RELEASE_BARRIER
+"1: lwarx %0,0,%1\n\
+ addic %0,%0,-1\n"
+" stwcx. %0,0,%1\n\
+ bne- 1b"
+ : "=&r"(tmp)
+ : "r"(&rw->lock)
+ : "cr0", "xer", "memory");
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+ __asm__ __volatile__("# write_unlock\n\t"
+ PPC_RELEASE_BARRIER: : :"memory");
+ rw->lock = 0;
+}
+
+#define arch_spin_relax(lock) spin_yield(lock)
+#define arch_read_relax(lock) rw_yield(lock)
+#define arch_write_relax(lock) rw_yield(lock)
+
+/* See include/linux/spinlock.h */
+#define smp_mb__after_spinlock() smp_mb()
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SIMPLE_SPINLOCK_H */
diff --git a/arch/powerpc/include/asm/simple_spinlock_types.h b/arch/powerpc/include/asm/simple_spinlock_types.h
new file mode 100644
index 000000000000..7c2b48ce62dc
--- /dev/null
+++ b/arch/powerpc/include/asm/simple_spinlock_types.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_SIMPLE_SPINLOCK_TYPES_H
+#define _ASM_POWERPC_SIMPLE_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int slock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile signed int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
index 79be9bb10bbb..21357fe05fe0 100644
--- a/arch/powerpc/include/asm/spinlock.h
+++ b/arch/powerpc/include/asm/spinlock.h
@@ -3,290 +3,7 @@
#define __ASM_SPINLOCK_H
#ifdef __KERNEL__
-/*
- * Simple spin lock operations.
- *
- * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
- * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
- * Rework to support virtual processors
- *
- * Type of int is used as a full 64b word is not necessary.
- *
- * (the type definitions are in asm/spinlock_types.h)
- */
-#include <linux/irqflags.h>
-#include <asm/paravirt.h>
-#ifdef CONFIG_PPC64
-#include <asm/paca.h>
-#endif
-#include <asm/synch.h>
-#include <asm/ppc-opcode.h>
-
-#ifdef CONFIG_PPC64
-/* use 0x800000yy when locked, where yy == CPU number */
-#ifdef __BIG_ENDIAN__
-#define LOCK_TOKEN (*(u32 *)(&get_paca()->lock_token))
-#else
-#define LOCK_TOKEN (*(u32 *)(&get_paca()->paca_index))
-#endif
-#else
-#define LOCK_TOKEN 1
-#endif
-
-static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
-{
- return lock.slock == 0;
-}
-
-static inline int arch_spin_is_locked(arch_spinlock_t *lock)
-{
- smp_mb();
- return !arch_spin_value_unlocked(*lock);
-}
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock)
-{
- unsigned long tmp, token;
-
- token = LOCK_TOKEN;
- __asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%2,1) "\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" (&lock->slock)
- : "cr0", "memory");
-
- return tmp;
-}
-
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
- return __arch_spin_trylock(lock) == 0;
-}
-
-/*
- * On a system with shared processors (that is, where a physical
- * processor is multiplexed between several virtual processors),
- * there is no point spinning on a lock if the holder of the lock
- * isn't currently scheduled on a physical processor. Instead
- * we detect this situation and ask the hypervisor to give the
- * rest of our timeslice to the lock holder.
- *
- * So that we can tell which virtual processor is holding a lock,
- * we put 0x80000000 | smp_processor_id() in the lock when it is
- * held. Conveniently, we have a word in the paca that holds this
- * value.
- */
-
-#if defined(CONFIG_PPC_SPLPAR)
-/* We only yield to the hypervisor if we are in shared processor mode */
-void splpar_spin_yield(arch_spinlock_t *lock);
-void splpar_rw_yield(arch_rwlock_t *lock);
-#else /* SPLPAR */
-static inline void splpar_spin_yield(arch_spinlock_t *lock) {};
-static inline void splpar_rw_yield(arch_rwlock_t *lock) {};
-#endif
-
-static inline void spin_yield(arch_spinlock_t *lock)
-{
- if (is_shared_processor())
- splpar_spin_yield(lock);
- else
- barrier();
-}
-
-static inline void rw_yield(arch_rwlock_t *lock)
-{
- if (is_shared_processor())
- splpar_rw_yield(lock);
- else
- barrier();
-}
-
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
- while (1) {
- if (likely(__arch_spin_trylock(lock) == 0))
- break;
- do {
- HMT_low();
- if (is_shared_processor())
- splpar_spin_yield(lock);
- } while (unlikely(lock->slock != 0));
- HMT_medium();
- }
-}
-
-static inline
-void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
-{
- unsigned long flags_dis;
-
- while (1) {
- if (likely(__arch_spin_trylock(lock) == 0))
- break;
- local_save_flags(flags_dis);
- local_irq_restore(flags);
- do {
- HMT_low();
- if (is_shared_processor())
- splpar_spin_yield(lock);
- } while (unlikely(lock->slock != 0));
- HMT_medium();
- local_irq_restore(flags_dis);
- }
-}
-#define arch_spin_lock_flags arch_spin_lock_flags
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
- __asm__ __volatile__("# arch_spin_unlock\n\t"
- PPC_RELEASE_BARRIER: : :"memory");
- lock->slock = 0;
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers
- * but only one writer.
- *
- * NOTE! it is quite common to have readers in interrupts
- * but no interrupt writers. For those circumstances we
- * can "mix" irq-safe locks - any writer needs to get a
- * irq-safe write-lock, but readers can get non-irqsafe
- * read-locks.
- */
-
-#ifdef CONFIG_PPC64
-#define __DO_SIGN_EXTEND "extsw %0,%0\n"
-#define WRLOCK_TOKEN LOCK_TOKEN /* it's negative */
-#else
-#define __DO_SIGN_EXTEND
-#define WRLOCK_TOKEN (-1)
-#endif
-
-/*
- * This returns the old value in the lock + 1,
- * so we got a read lock if the return value is > 0.
- */
-static inline long __arch_read_trylock(arch_rwlock_t *rw)
-{
- long tmp;
-
- __asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%1,1) "\n"
- __DO_SIGN_EXTEND
-" addic. %0,%0,1\n\
- ble- 2f\n"
-" stwcx. %0,0,%1\n\
- bne- 1b\n"
- PPC_ACQUIRE_BARRIER
-"2:" : "=&r" (tmp)
- : "r" (&rw->lock)
- : "cr0", "xer", "memory");
-
- return tmp;
-}
-
-/*
- * This returns the old value in the lock,
- * so we got the write lock if the return value is 0.
- */
-static inline long __arch_write_trylock(arch_rwlock_t *rw)
-{
- long tmp, token;
-
- token = WRLOCK_TOKEN;
- __asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%2,1) "\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)
- : "cr0", "memory");
-
- return tmp;
-}
-
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
- while (1) {
- if (likely(__arch_read_trylock(rw) > 0))
- break;
- do {
- HMT_low();
- if (is_shared_processor())
- splpar_rw_yield(rw);
- } while (unlikely(rw->lock < 0));
- HMT_medium();
- }
-}
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
- while (1) {
- if (likely(__arch_write_trylock(rw) == 0))
- break;
- do {
- HMT_low();
- if (is_shared_processor())
- splpar_rw_yield(rw);
- } while (unlikely(rw->lock != 0));
- HMT_medium();
- }
-}
-
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
- return __arch_read_trylock(rw) > 0;
-}
-
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
- return __arch_write_trylock(rw) == 0;
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
- long tmp;
-
- __asm__ __volatile__(
- "# read_unlock\n\t"
- PPC_RELEASE_BARRIER
-"1: lwarx %0,0,%1\n\
- addic %0,%0,-1\n"
-" stwcx. %0,0,%1\n\
- bne- 1b"
- : "=&r"(tmp)
- : "r"(&rw->lock)
- : "cr0", "xer", "memory");
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
- __asm__ __volatile__("# write_unlock\n\t"
- PPC_RELEASE_BARRIER: : :"memory");
- rw->lock = 0;
-}
-
-#define arch_spin_relax(lock) spin_yield(lock)
-#define arch_read_relax(lock) rw_yield(lock)
-#define arch_write_relax(lock) rw_yield(lock)
-
-/* See include/linux/spinlock.h */
-#define smp_mb__after_spinlock() smp_mb()
+#include <asm/simple_spinlock.h>
#endif /* __KERNEL__ */
#endif /* __ASM_SPINLOCK_H */
diff --git a/arch/powerpc/include/asm/spinlock_types.h b/arch/powerpc/include/asm/spinlock_types.h
index 87adaf13b7e8..3906f52dae65 100644
--- a/arch/powerpc/include/asm/spinlock_types.h
+++ b/arch/powerpc/include/asm/spinlock_types.h
@@ -6,16 +6,6 @@
# error "please don't include this file directly"
#endif
-typedef struct {
- volatile unsigned int slock;
-} arch_spinlock_t;
-
-#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
-
-typedef struct {
- volatile signed int lock;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+#include <asm/simple_spinlock_types.h>
#endif
--
2.23.0
^ permalink raw reply related
* [PATCH v3 4/6] powerpc/64s: implement queued spinlocks and rwlocks
From: Nicholas Piggin @ 2020-07-06 4:35 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-arch, Peter Zijlstra, Boqun Feng, linux-kernel,
Nicholas Piggin, virtualization, Ingo Molnar, kvm-ppc,
Waiman Long, Will Deacon
In-Reply-To: <20200706043540.1563616-1-npiggin@gmail.com>
These have shown significantly improved performance and fairness when
spinlock contention is moderate to high on very large systems.
[ Numbers hopefully forthcoming after more testing, but initial
results look good ]
Thanks to the fast path, single threaded performance is not noticably
hurt.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/Kconfig | 13 ++++++++++++
arch/powerpc/include/asm/Kbuild | 2 ++
arch/powerpc/include/asm/qspinlock.h | 25 +++++++++++++++++++++++
arch/powerpc/include/asm/spinlock.h | 5 +++++
arch/powerpc/include/asm/spinlock_types.h | 5 +++++
arch/powerpc/lib/Makefile | 3 +++
include/asm-generic/qspinlock.h | 2 ++
7 files changed, 55 insertions(+)
create mode 100644 arch/powerpc/include/asm/qspinlock.h
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 24ac85c868db..17663ea57697 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -146,6 +146,8 @@ config PPC
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
+ select ARCH_USE_QUEUED_RWLOCKS if PPC_QUEUED_SPINLOCKS
+ select ARCH_USE_QUEUED_SPINLOCKS if PPC_QUEUED_SPINLOCKS
select ARCH_WANT_IPC_PARSE_VERSION
select ARCH_WEAK_RELEASE_ACQUIRE
select BINFMT_ELF
@@ -492,6 +494,17 @@ config HOTPLUG_CPU
Say N if you are unsure.
+config PPC_QUEUED_SPINLOCKS
+ bool "Queued spinlocks"
+ depends on SMP
+ default "y" if PPC_BOOK3S_64
+ help
+ Say Y here to use to use queued spinlocks which are more complex
+ but give better salability and fairness on large SMP and NUMA
+ systems.
+
+ If unsure, say "Y" if you have lots of cores, otherwise "N".
+
config ARCH_CPU_PROBE_RELEASE
def_bool y
depends on HOTPLUG_CPU
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index dadbcf3a0b1e..1dd8b6adff5e 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -6,5 +6,7 @@ generated-y += syscall_table_spu.h
generic-y += export.h
generic-y += local64.h
generic-y += mcs_spinlock.h
+generic-y += qrwlock.h
+generic-y += qspinlock.h
generic-y += vtime.h
generic-y += early_ioremap.h
diff --git a/arch/powerpc/include/asm/qspinlock.h b/arch/powerpc/include/asm/qspinlock.h
new file mode 100644
index 000000000000..c49e33e24edd
--- /dev/null
+++ b/arch/powerpc/include/asm/qspinlock.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_QSPINLOCK_H
+#define _ASM_POWERPC_QSPINLOCK_H
+
+#include <asm-generic/qspinlock_types.h>
+
+#define _Q_PENDING_LOOPS (1 << 9) /* not tuned */
+
+#define smp_mb__after_spinlock() smp_mb()
+
+static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
+{
+ /*
+ * This barrier was added to simple spinlocks by commit 51d7d5205d338,
+ * but it should now be possible to remove it, asm arm64 has done with
+ * commit c6f5d02b6a0f.
+ */
+ smp_mb();
+ return atomic_read(&lock->val);
+}
+#define queued_spin_is_locked queued_spin_is_locked
+
+#include <asm-generic/qspinlock.h>
+
+#endif /* _ASM_POWERPC_QSPINLOCK_H */
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
index 21357fe05fe0..434615f1d761 100644
--- a/arch/powerpc/include/asm/spinlock.h
+++ b/arch/powerpc/include/asm/spinlock.h
@@ -3,7 +3,12 @@
#define __ASM_SPINLOCK_H
#ifdef __KERNEL__
+#ifdef CONFIG_PPC_QUEUED_SPINLOCKS
+#include <asm/qspinlock.h>
+#include <asm/qrwlock.h>
+#else
#include <asm/simple_spinlock.h>
+#endif
#endif /* __KERNEL__ */
#endif /* __ASM_SPINLOCK_H */
diff --git a/arch/powerpc/include/asm/spinlock_types.h b/arch/powerpc/include/asm/spinlock_types.h
index 3906f52dae65..c5d742f18021 100644
--- a/arch/powerpc/include/asm/spinlock_types.h
+++ b/arch/powerpc/include/asm/spinlock_types.h
@@ -6,6 +6,11 @@
# error "please don't include this file directly"
#endif
+#ifdef CONFIG_PPC_QUEUED_SPINLOCKS
+#include <asm-generic/qspinlock_types.h>
+#include <asm-generic/qrwlock_types.h>
+#else
#include <asm/simple_spinlock_types.h>
+#endif
#endif
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 5e994cda8e40..d66a645503eb 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -41,7 +41,10 @@ obj-$(CONFIG_PPC_BOOK3S_64) += copyuser_power7.o copypage_power7.o \
obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \
memcpy_64.o memcpy_mcsafe_64.o
+ifndef CONFIG_PPC_QUEUED_SPINLOCKS
obj64-$(CONFIG_SMP) += locks.o
+endif
+
obj64-$(CONFIG_ALTIVEC) += vmx-helper.o
obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o \
test_emulate_step_exec_instr.o
diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h
index fde943d180e0..fb0a814d4395 100644
--- a/include/asm-generic/qspinlock.h
+++ b/include/asm-generic/qspinlock.h
@@ -12,6 +12,7 @@
#include <asm-generic/qspinlock_types.h>
+#ifndef queued_spin_is_locked
/**
* queued_spin_is_locked - is the spinlock locked?
* @lock: Pointer to queued spinlock structure
@@ -25,6 +26,7 @@ static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
*/
return atomic_read(&lock->val);
}
+#endif
/**
* queued_spin_value_unlocked - is the spinlock structure unlocked?
--
2.23.0
^ permalink raw reply related
* [PATCH v3 5/6] powerpc/pseries: implement paravirt qspinlocks for SPLPAR
From: Nicholas Piggin @ 2020-07-06 4:35 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-arch, Peter Zijlstra, Boqun Feng, linux-kernel,
Nicholas Piggin, virtualization, Ingo Molnar, kvm-ppc,
Waiman Long, Will Deacon
In-Reply-To: <20200706043540.1563616-1-npiggin@gmail.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/paravirt.h | 28 ++++++++
arch/powerpc/include/asm/qspinlock.h | 66 +++++++++++++++++++
arch/powerpc/include/asm/qspinlock_paravirt.h | 7 ++
arch/powerpc/platforms/pseries/Kconfig | 5 ++
arch/powerpc/platforms/pseries/setup.c | 6 +-
include/asm-generic/qspinlock.h | 2 +
6 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/include/asm/qspinlock_paravirt.h
diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h
index 7a8546660a63..f2d51f929cf5 100644
--- a/arch/powerpc/include/asm/paravirt.h
+++ b/arch/powerpc/include/asm/paravirt.h
@@ -29,6 +29,16 @@ static inline void yield_to_preempted(int cpu, u32 yield_count)
{
plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(cpu), yield_count);
}
+
+static inline void prod_cpu(int cpu)
+{
+ plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
+}
+
+static inline void yield_to_any(void)
+{
+ plpar_hcall_norets(H_CONFER, -1, 0);
+}
#else
static inline bool is_shared_processor(void)
{
@@ -45,6 +55,19 @@ static inline void yield_to_preempted(int cpu, u32 yield_count)
{
___bad_yield_to_preempted(); /* This would be a bug */
}
+
+extern void ___bad_yield_to_any(void);
+static inline void yield_to_any(void)
+{
+ ___bad_yield_to_any(); /* This would be a bug */
+}
+
+extern void ___bad_prod_cpu(void);
+static inline void prod_cpu(int cpu)
+{
+ ___bad_prod_cpu(); /* This would be a bug */
+}
+
#endif
#define vcpu_is_preempted vcpu_is_preempted
@@ -57,5 +80,10 @@ static inline bool vcpu_is_preempted(int cpu)
return false;
}
+static inline bool pv_is_native_spin_unlock(void)
+{
+ return !is_shared_processor();
+}
+
#endif /* __KERNEL__ */
#endif /* __ASM_PARAVIRT_H */
diff --git a/arch/powerpc/include/asm/qspinlock.h b/arch/powerpc/include/asm/qspinlock.h
index c49e33e24edd..f5066f00a08c 100644
--- a/arch/powerpc/include/asm/qspinlock.h
+++ b/arch/powerpc/include/asm/qspinlock.h
@@ -3,9 +3,47 @@
#define _ASM_POWERPC_QSPINLOCK_H
#include <asm-generic/qspinlock_types.h>
+#include <asm/paravirt.h>
#define _Q_PENDING_LOOPS (1 << 9) /* not tuned */
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+extern void native_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
+extern void __pv_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
+extern void __pv_queued_spin_unlock(struct qspinlock *lock);
+
+static __always_inline void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
+{
+ if (!is_shared_processor())
+ native_queued_spin_lock_slowpath(lock, val);
+ else
+ __pv_queued_spin_lock_slowpath(lock, val);
+}
+
+#define queued_spin_unlock queued_spin_unlock
+static inline void queued_spin_unlock(struct qspinlock *lock)
+{
+ if (!is_shared_processor())
+ smp_store_release(&lock->locked, 0);
+ else
+ __pv_queued_spin_unlock(lock);
+}
+
+#else
+extern void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
+#endif
+
+static __always_inline void queued_spin_lock(struct qspinlock *lock)
+{
+ u32 val = 0;
+
+ if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL)))
+ return;
+
+ queued_spin_lock_slowpath(lock, val);
+}
+#define queued_spin_lock queued_spin_lock
+
#define smp_mb__after_spinlock() smp_mb()
static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
@@ -20,6 +58,34 @@ static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
}
#define queued_spin_is_locked queued_spin_is_locked
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+#define SPIN_THRESHOLD (1<<15) /* not tuned */
+
+static __always_inline void pv_wait(u8 *ptr, u8 val)
+{
+ if (*ptr != val)
+ return;
+ yield_to_any();
+ /*
+ * We could pass in a CPU here if waiting in the queue and yield to
+ * the previous CPU in the queue.
+ */
+}
+
+static __always_inline void pv_kick(int cpu)
+{
+ prod_cpu(cpu);
+}
+
+extern void __pv_init_lock_hash(void);
+
+static inline void pv_spinlocks_init(void)
+{
+ __pv_init_lock_hash();
+}
+
+#endif
+
#include <asm-generic/qspinlock.h>
#endif /* _ASM_POWERPC_QSPINLOCK_H */
diff --git a/arch/powerpc/include/asm/qspinlock_paravirt.h b/arch/powerpc/include/asm/qspinlock_paravirt.h
new file mode 100644
index 000000000000..750d1b5e0202
--- /dev/null
+++ b/arch/powerpc/include/asm/qspinlock_paravirt.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef __ASM_QSPINLOCK_PARAVIRT_H
+#define __ASM_QSPINLOCK_PARAVIRT_H
+
+EXPORT_SYMBOL(__pv_queued_spin_unlock);
+
+#endif /* __ASM_QSPINLOCK_PARAVIRT_H */
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 24c18362e5ea..756e727b383f 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -25,9 +25,14 @@ config PPC_PSERIES
select SWIOTLB
default y
+config PARAVIRT_SPINLOCKS
+ bool
+ default n
+
config PPC_SPLPAR
depends on PPC_PSERIES
bool "Support for shared-processor logical partitions"
+ select PARAVIRT_SPINLOCKS if PPC_QUEUED_SPINLOCKS
help
Enabling this option will make the kernel run more efficiently
on logically-partitioned pSeries systems which use shared
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 2db8469e475f..747a203d9453 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -771,8 +771,12 @@ static void __init pSeries_setup_arch(void)
if (firmware_has_feature(FW_FEATURE_LPAR)) {
vpa_init(boot_cpuid);
- if (lppaca_shared_proc(get_lppaca()))
+ if (lppaca_shared_proc(get_lppaca())) {
static_branch_enable(&shared_processor);
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+ pv_spinlocks_init();
+#endif
+ }
ppc_md.power_save = pseries_lpar_idle;
ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h
index fb0a814d4395..38ca14e79a86 100644
--- a/include/asm-generic/qspinlock.h
+++ b/include/asm-generic/qspinlock.h
@@ -69,6 +69,7 @@ static __always_inline int queued_spin_trylock(struct qspinlock *lock)
extern void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
+#ifndef queued_spin_lock
/**
* queued_spin_lock - acquire a queued spinlock
* @lock: Pointer to queued spinlock structure
@@ -82,6 +83,7 @@ static __always_inline void queued_spin_lock(struct qspinlock *lock)
queued_spin_lock_slowpath(lock, val);
}
+#endif
#ifndef queued_spin_unlock
/**
--
2.23.0
^ permalink raw reply related
* [PATCH v3 6/6] powerpc/qspinlock: optimised atomic_try_cmpxchg_lock that adds the lock hint
From: Nicholas Piggin @ 2020-07-06 4:35 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-arch, Peter Zijlstra, Boqun Feng, linux-kernel,
Nicholas Piggin, virtualization, Ingo Molnar, kvm-ppc,
Waiman Long, Will Deacon
In-Reply-To: <20200706043540.1563616-1-npiggin@gmail.com>
This brings the behaviour of the uncontended fast path back to
roughly equivalent to simple spinlocks -- a single atomic op with
lock hint.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/atomic.h | 28 ++++++++++++++++++++++++++++
arch/powerpc/include/asm/qspinlock.h | 2 +-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 498785ffc25f..f6a3d145ffb7 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -193,6 +193,34 @@ static __inline__ int atomic_dec_return_relaxed(atomic_t *v)
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_xchg_relaxed(v, new) xchg_relaxed(&((v)->counter), (new))
+/*
+ * Don't want to override the generic atomic_try_cmpxchg_acquire, because
+ * we add a lock hint to the lwarx, which may not be wanted for the
+ * _acquire case (and is not used by the other _acquire variants so it
+ * would be a surprise).
+ */
+static __always_inline bool
+atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new)
+{
+ int r, o = *old;
+
+ __asm__ __volatile__ (
+"1:\t" PPC_LWARX(%0,0,%2,1) " # atomic_try_cmpxchg_acquire \n"
+" cmpw 0,%0,%3 \n"
+" bne- 2f \n"
+" stwcx. %4,0,%2 \n"
+" bne- 1b \n"
+"\t" PPC_ACQUIRE_BARRIER " \n"
+"2: \n"
+ : "=&r" (r), "+m" (v->counter)
+ : "r" (&v->counter), "r" (o), "r" (new)
+ : "cr0", "memory");
+
+ if (unlikely(r != o))
+ *old = r;
+ return likely(r == o);
+}
+
/**
* atomic_fetch_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
diff --git a/arch/powerpc/include/asm/qspinlock.h b/arch/powerpc/include/asm/qspinlock.h
index f5066f00a08c..b752d34517b3 100644
--- a/arch/powerpc/include/asm/qspinlock.h
+++ b/arch/powerpc/include/asm/qspinlock.h
@@ -37,7 +37,7 @@ static __always_inline void queued_spin_lock(struct qspinlock *lock)
{
u32 val = 0;
- if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL)))
+ if (likely(atomic_try_cmpxchg_lock(&lock->val, &val, _Q_LOCKED_VAL)))
return;
queued_spin_lock_slowpath(lock, val);
--
2.23.0
^ permalink raw reply related
* Re: Using Firefox hangs system
From: Paul Menzel @ 2020-07-06 5:20 UTC (permalink / raw)
To: Nicholas Piggin, Benjamin Herrenschmidt, Michael Ellerman,
Paul Mackerras
Cc: linuxppc-dev
In-Reply-To: <1593995628.78zg3dfzk8.astroid@bobo.none>
Dear Nicholas,
Thank you for the quick response.
Am 06.07.20 um 02:41 schrieb Nicholas Piggin:
> Excerpts from Paul Menzel's message of July 5, 2020 8:30 pm:
>> Am 05.07.20 um 11:22 schrieb Paul Menzel:
>>
>>> With an IBM S822LC with Ubuntu 20.04, after updating to Firefox 78.0,
>>> using Firefox seems to hang the system. This happened with self-built
>>> Linux 5.7-rc5+ and now with 5.8-rc3+.
>>>
>>> (At least I believe the Firefox update is causing this.)
>>>
>>> Log in is impossible, and using the Serial over LAN over IPMI shows the
>>> messages below.
>>>
>>>> [ 2620.579187] watchdog: BUG: soft lockup - CPU#125 stuck for 22s!
>>>> [swapper/125:0]
>>>> [ 2620.579378] Modules linked in: tcp_diag inet_diag unix_diag
>>>> xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4
>>>> xt_tcpudp ip6table_mangle ip6table_nat iptable_mangle iptable_nat
>>>> nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables nfnetlink
>>>> ip6table_filter ip6_tables iptable_filter bridge stp llc overlay xfs
>>>> kvm_hv kvm joydev binfmt_misc uas usb_storage vmx_crypto ofpart
>>>> cmdlinepart bnx2x powernv_flash mtd mdio crct10dif_vpmsum at24
>>>> ibmpowernv ipmi_powernv ipmi_devintf powernv_rng ipmi_msghandler
>>>> opal_prd sch_fq_codel parport_pc nfsd ppdev lp auth_rpcgss nfs_acl
>>>> parport lockd grace sunrpc ip_tables x_tables autofs4 btrfs
>>>> blake2b_generic libcrc32c xor zstd_compress raid6_pq input_leds
>>>> mac_hid hid_generic ast drm_vram_helper drm_ttm_helper i2c_algo_bit
>>>> ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm
>>>> drm_panel_orientation_quirks ahci libahci usbhid hid crc32c_vpmsum
>>>> uio_pdrv_genirq uio
>>>> [ 2620.579537] CPU: 125 PID: 0 Comm: swapper/125 Tainted: G D
>>>> W L 5.8.0-rc3+ #1
>>>> [ 2620.579552] NIP: c0000000010dad38 LR: c0000000010dad30 CTR:
>>>> c000000000237830
>>>> [ 2620.579568] REGS: c00000ffcb8c7600 TRAP: 0900 Tainted: G D
>>>> W L (5.8.0-rc3+)
>>>> [ 2620.579582] MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR:
>>>> 44004228 XER: 00000000
>>>> [ 2620.579599] CFAR: c0000000010dad44 IRQMASK: 0 [ 2620.579599] GPR00:
>>>> c00000000023718c c00000ffcb8c7890 c000000001f9a900 0000000000000000 [
>>>> 2620.579599] GPR04: c000000001fce438 0000000000000078 000000010008c1f2
>>>> 0000000000000000 [ 2620.579599] GPR08: 000000ffd96a0000
>>>> 0000000080000087 0000000000000000 c000000001fd25e0 [ 2620.579599]
>>>> GPR12: 0000000000004400 c00000ffff72f680 c000000001ea36d8
>>>> c00000ffcb859800 [ 2620.579599] GPR16: c00000000166c880
>>>> c0000000016f8e00 000000000000000a c00000ffcb859800 [ 2620.579599]
>>>> GPR20: 0000000000000100 c00000000166c918 c000000001fd21e8
>>>> c00000ffcb859800 [ 2620.579599] GPR24: 000000ffd96a0000
>>>> c000000001d44b80 c000000001d53780 0000000000000008 [ 2620.579599]
>>>> GPR28: c000000001fd21e0 0000000000000001 0000000000000000
>>>> c000000001d44b80 [ 2620.579711] NIP [c0000000010dad38]
>>>> _raw_spin_lock_irqsave+0x98/0x120
>>>> [ 2620.579724] LR [c0000000010dad30] _raw_spin_lock_irqsave+0x90/0x120
>>>> [ 2620.579737] Call Trace:
>>>> [ 2620.579746] [c00000ffcb8c7890] [c0000000013c84a0]
>>>> ncsi_ops+0x209f50/0x2dc1d8 (unreliable)
>>>> [ 2620.579763] [c00000ffcb8c78d0] [c00000000023718c] rcu_core+0xfc/0x7a0
>>>> [ 2620.579777] [c00000ffcb8c7970] [c0000000010db81c]
>>>> __do_softirq+0x17c/0x534
>>>> [ 2620.579791] [c00000ffcb8c7aa0] [c0000000001786f4] irq_exit+0xd4/0x130
>>>> [ 2620.579805] [c00000ffcb8c7ad0] [c000000000025eec]
>>>> timer_interrupt+0x13c/0x370
>>>> [ 2620.579821] [c00000ffcb8c7b40] [c0000000000165c0]
>>>> replay_soft_interrupts+0x320/0x3f0
>>>> [ 2620.579837] [c00000ffcb8c7d30] [c0000000000166d8]
>>>> arch_local_irq_restore+0x48/0xa0
>>>> [ 2620.579853] [c00000ffcb8c7d50] [c000000000de2fe0]
>>>> cpuidle_enter_state+0x100/0x780
>
> [snip]
>
>>> I have to warm reset the system to get it working again.
>>
>> I am unable to reproduce this with Ubuntu’s Linux
>
> Okay, not sure what that would be from, looks like RCU perhaps. Anyway
> if it comes up again, let us know.
Ah, it’s a different trace. I think it’s just an effect of the first
error (as below), as some CPUs lock up. I wasn’t able to capture the
start of the trace above. In the attachment for the hang *below* you can
also see
[ 664.705193] watchdog: BUG: soft lockup - CPU#134 stuck for 26s!
[swapper/134:0]
after the first Oops.
>> With Linux 5.8-rc3+, I got now the beginning of the Linux messages.
>>
>>> [ 572.253008] Oops: Exception in kernel mode, sig: 5 [#1]
>>> [ 572.253198] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
>>> [ 572.253232] Modules linked in: tcp_diag inet_diag unix_diag xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp ip6table_mangle ip6table_nat iptable_mangle iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables nfnetlink ip6table_filter ip6_tables iptable_filter bridge stp llc overlay xfs kvm_hv kvm binfmt_misc joydev uas usb_storage vmx_crypto bnx2x crct10dif_vpmsum ofpart cmdlinepart powernv_flash mtd mdio ibmpowernv at24 ipmi_powernv ipmi_devintf ipmi_msghandler opal_prd powernv_rng sch_fq_codel parport_pc ppdev lp nfsd parport auth_rpcgss nfs_acl lockd grace sunrpc ip_tables x_tables autofs4 btrfs blake2b_generic libcrc32c xor zstd_compress raid6_pq input_leds mac_hid hid_generic ast drm_vram_helper drm_ttm_helper i2c_algo_bit ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci drm_panel_orientation_quirks libahci usbhid hid crc32c_vpmsum uio_pdrv_genirq uio
>>> [ 572.253639] CPU: 4 PID: 6728 Comm: Web Content Not tainted 5.8.0-rc3+ #1
>>> [ 572.253659] NIP: c00000000000ff5c LR: c00000000001a8f8 CTR: c0000000001d5f00
>>> [ 572.253835] REGS: c000007f31f0f420 TRAP: 1500 Not tainted (5.8.0-rc3+)
>>> [ 572.253854] MSR: 900000000290b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 28c48482 XER: 20000000
>>> [ 572.253888] CFAR: c00000000000fecc IRQMASK: 1
>>> [ 572.253888] GPR00: c00000000001b228 c000007f31f0f6b0 c000000001f9a900 c000007f351544d0
>>> [ 572.253888] GPR04: 0000000000000000 c000007f31f0fe90 c000007f351544f0 c000007f32e522b0
>>> [ 572.253888] GPR08: 0000000000000000 0000000000002000 9000000000009033 c000007fbcd85800
>>> [ 572.253888] GPR12: 0000000000008800 c000007fffffb680 0000000000000005 0000000000000004
>>> [ 572.253888] GPR16: c000007f35153800 c000007f35154130 0000000000000005 0000000000000001
>>> [ 572.253888] GPR20: 0000000000000024 c000007f32e51e68 c000007f35154028 0000007fd8da0000
>>> [ 572.253888] GPR24: 0000007fd8da0000 c000007f351544d0 c000007e9a4024d0 c000000001665f18
>>> [ 572.253888] GPR28: c000007f351544d0 c000007f35153800 900000000290f033 c000007f35153800
>>> [ 572.254079] NIP [c00000000000ff5c] save_fpu+0xa8/0x2ac
>>> [ 572.254098] LR [c00000000001a8f8] __giveup_fpu+0x28/0x80
>>> [ 572.254114] Call Trace:
>>> [ 572.254128] [c000007f31f0f6b0] [c000007f35153980] 0xc000007f35153980 (unreliable)
>>> [ 572.254156] [c000007f31f0f6e0] [c00000000001b228] giveup_all+0x128/0x150
>>> [ 572.254327] [c000007f31f0f710] [c00000000001c124] __switch_to+0x104/0x490
>>> [ 572.254352] [c000007f31f0f770] [c0000000010d2e34] __schedule+0x2e4/0xa10
>>> [ 572.254374] [c000007f31f0f840] [c0000000010d35d4] schedule+0x74/0x140
>>> [ 572.254397] [c000007f31f0f870] [c0000000010d9478] schedule_timeout+0x358/0x5d0
>>> [ 572.254424] [c000007f31f0f980] [c0000000010d5638] wait_for_completion+0xc8/0x210
>>> [ 572.254451] [c000007f31f0fa00] [c000000000608ed4] do_coredump+0x3a4/0xd60
>>> [ 572.254625] [c000007f31f0fba0] [c00000000018d1cc] get_signal+0x1dc/0xd00
>>> [ 572.254648] [c000007f31f0fcc0] [c00000000001f088] do_notify_resume+0x158/0x450
>>> [ 572.254672] [c000007f31f0fda0] [c000000000037d04] interrupt_exit_user_prepare+0x1c4/0x230
>>> [ 572.254699] [c000007f31f0fe20] [c00000000000f2b4] interrupt_return+0x14/0x1c0
>>> [ 572.254720] Instruction dump:
>>> [ 572.254882] dae60170 db060180 db260190 db4601a0 db6601b0 db8601c0 dba601d0 dbc601e0
>>> [ 572.254912] dbe601f0 48000204 38800000 f0000250 <7c062798> f0000250 38800010 f0210a50
>>> [ 572.254946] ---[ end trace ba4452ee5c77d58e ]---
>>
>> Please find all the messages attached.
>
> "Oops: Exception in kernel mode, sig: 5 [#1]"
>
> Unfortunately it's a very poor error message. I think it is a 0x1500
> exception triggering in the kernel FP register saving. Do you have the
> CONFIG_PPC_DENORMALISATION config option set?
Yes, as it’s set in the Ubuntu Linux kernel configuration, I have it set
too.
$ grep DENORMALI /boot/config-*
/boot/config-4.15.0-23-generic:CONFIG_PPC_DENORMALISATION=y
/boot/config-5.4.0-40-generic:CONFIG_PPC_DENORMALISATION=y
/boot/config-5.7.0-rc5+:CONFIG_PPC_DENORMALISATION=y
/boot/config-5.8.0-rc3+:CONFIG_PPC_DENORMALISATION=y
Kind regards,
Paul
^ permalink raw reply
* [PATCH] cpuidle/powernv : Remove dead code block
From: Abhishek Goel @ 2020-07-06 5:32 UTC (permalink / raw)
To: linux-pm, linuxppc-dev, linux-kernel
Cc: Abhishek Goel, daniel.lezcano, rjw, ego
Commit 1961acad2f88559c2cdd2ef67c58c3627f1f6e54 removes usage of
function "validate_dt_prop_sizes". This patch removes this unused
function.
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
drivers/cpuidle/cpuidle-powernv.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 1b299e801f74..addaa6e6718b 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -244,20 +244,6 @@ static inline void add_powernv_state(int index, const char *name,
stop_psscr_table[index].mask = psscr_mask;
}
-/*
- * Returns 0 if prop1_len == prop2_len. Else returns -1
- */
-static inline int validate_dt_prop_sizes(const char *prop1, int prop1_len,
- const char *prop2, int prop2_len)
-{
- if (prop1_len == prop2_len)
- return 0;
-
- pr_warn("cpuidle-powernv: array sizes don't match for %s and %s\n",
- prop1, prop2);
- return -1;
-}
-
extern u32 pnv_get_supported_cpuidle_states(void);
static int powernv_add_idle_states(void)
{
--
2.17.1
^ permalink raw reply related
* [RFC v2 1/2] powerpc/powernv : Add support for pre-entry and post-exit of stop state using OPAL V4 OS services
From: Abhishek Goel @ 2020-07-06 4:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: ego, mikey, npiggin, oohall, psampat, Abhishek Goel
This patch provides kernel framework fro opal support of save restore
of sprs in idle stop loop. Opal support for stop states is needed to
selectively enable stop states or to introduce a quirk quickly in case
a buggy stop state is present.
We make a opal call from kernel if firmware-stop-support for stop
states is present and enabled. All the quirks for pre-entry of stop
state is handled inside opal. A call from opal is made into kernel
where we execute stop afer saving of NVGPRs.
After waking up from 0x100 vector in kernel, we enter back into opal.
All the quirks in post exit path, if any, are then handled in opal,
from where we return successfully back to kernel.
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
v1->v2 : Rebased the patch on Nick's Opal V4 OS patchset
arch/powerpc/include/asm/opal-api.h | 4 +++-
arch/powerpc/include/asm/opal.h | 1 +
arch/powerpc/platforms/powernv/idle.c | 12 ++++++++++++
arch/powerpc/platforms/powernv/opal-call.c | 1 +
arch/powerpc/platforms/powernv/opal.c | 15 +++++++++++++++
5 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 97c5e5423827..437b6937685d 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -219,7 +219,8 @@
#define OPAL_REPORT_TRAP 183
#define OPAL_FIND_VM_AREA 184
#define OPAL_REGISTER_OS_OPS 185
-#define OPAL_LAST 185
+#define OPAL_CPU_IDLE 186
+#define OPAL_LAST 186
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1207,6 +1208,7 @@ struct opal_os_ops {
__be64 os_printf; /* void printf(int32_t level, const char *str) */
__be64 os_vm_map; /* int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags) */
__be64 os_vm_unmap; /* void os_vm_unmap(uint64_t ea) */
+ __be64 os_idle_stop; /* void os_idle_stop(uint64_t srr1_addr, uint64_t psscr) */
};
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 09985b7718b3..1774c056acb8 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -407,6 +407,7 @@ void opal_sensor_groups_init(void);
int64_t opal_find_vm_area(uint64_t addr, struct opal_vm_area *opal_vm_area);
int64_t opal_register_os_ops(struct opal_os_ops *ops, uint64_t size);
+int64_t opal_cpu_idle(uint64_t srr1_addr, uint64_t psscr);
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 78599bca66c2..3afd4293f729 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -805,6 +805,18 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
return srr1;
}
+static unsigned long power9_firmware_idle_stop(unsigned long psscr, bool mmu_on)
+{
+ unsigned long srr1;
+ int rc;
+
+ rc = opal_cpu_idle(cpu_to_be64(&srr1), (uint64_t) psscr);
+
+ if (mmu_on)
+ mtmsr(MSR_KERNEL);
+ return srr1;
+}
+
#ifdef CONFIG_HOTPLUG_CPU
static unsigned long power9_offline_stop(unsigned long psscr)
{
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 11f419e76059..79076ca2de03 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -351,3 +351,4 @@ OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
OPAL_CALL(opal_report_trap, OPAL_REPORT_TRAP);
OPAL_CALL(opal_find_vm_area, OPAL_FIND_VM_AREA);
OPAL_CALL(opal_register_os_ops, OPAL_REGISTER_OS_OPS);
+OPAL_CALL(opal_cpu_idle, OPAL_CPU_IDLE);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 93b9afaf33b3..1fbf7065f918 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -1150,6 +1150,20 @@ static void os_vm_unmap(uint64_t ea)
local_flush_tlb_mm(mm);
}
+int64_t os_idle_stop(uint64_t srr1_addr, uint64_t psscr)
+{
+ /*
+ * For lite state which does not lose even GPRS we call
+ * idle_stop_noloss while for all other states we call
+ * idle_stop_mayloss. Saving and restoration of other additional
+ * SPRs if required is handled in OPAL. All the quirks are also
+ * handled in OPAL.
+ */
+ if (!(psscr & (PSSCR_EC|PSSCR_ESL)))
+ return isa300_idle_stop_noloss(psscr);
+ return isa300_idle_stop_mayloss(psscr);
+}
+
static int __init opal_init_mm(void)
{
struct mm_struct *mm;
@@ -1231,6 +1245,7 @@ static int __init opal_init_early(void)
opal_os_ops.os_printf = cpu_to_be64(&os_printf);
opal_os_ops.os_vm_map = cpu_to_be64(&os_vm_map);
opal_os_ops.os_vm_unmap = cpu_to_be64(&os_vm_unmap);
+ opal_os_ops.os_idle_stop = cpu_to_be64(&os_idle_stop);
if (opal_register_os_ops(&opal_os_ops, sizeof(opal_os_ops))) {
pr_warn("OPAL register OS ops failed, firmware will run in v3 mode.\n");
} else {
--
2.17.1
^ permalink raw reply related
* [RFC v2 2/2] powerpc/powernv : Introduce capability for firmware-enabled-stop
From: Abhishek Goel @ 2020-07-06 4:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: ego, mikey, npiggin, oohall, psampat, Abhishek Goel
In-Reply-To: <20200706045001.77039-1-huntbag@linux.vnet.ibm.com>
This patch introduces the capability for firmware to handle the stop
states instead. A bit is set based on the discovery of the feature
and correspondingly also the responsibility to handle the stop states.
If Kernel does not know about stop version, it can fallback to opal for
idle stop support if firmware-stop-supported property is present.
Earlier part of this patch was posted in this series :
https://lkml.org/lkml/2020/3/4/589
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com>
---
v1->v2 : Combined patch 2 and 3 from previous iteration and rebased it.
arch/powerpc/include/asm/processor.h | 18 ++++++++++++++++++
arch/powerpc/kernel/dt_cpu_ftrs.c | 13 +++++++++++++
arch/powerpc/platforms/powernv/idle.c | 20 ++++++++++++++++----
drivers/cpuidle/cpuidle-powernv.c | 3 ++-
4 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index bfa336fbcfeb..b8de7146387c 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -428,6 +428,24 @@ extern void power4_idle_nap(void);
extern unsigned long cpuidle_disable;
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
+#define STOP_ENABLE 0x00000001
+#define FIRMWARE_STOP_ENABLE 0x00000010
+
+#define STOP_VERSION_P9 0x1
+
+/*
+ * Classify the dependencies of the stop states
+ * @idle_stop: function handler to handle the quirk stop version
+ * @cpuidle_prop: Signify support for stop states through kernel and/or firmware
+ * @stop_version: Classify quirk versions for stop states
+ */
+typedef struct {
+ unsigned long (*idle_stop)(unsigned long psscr, bool mmu_on);
+ uint8_t cpuidle_prop;
+ uint8_t stop_version;
+} stop_deps_t;
+extern stop_deps_t stop_dep;
+
extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern void power7_idle_type(unsigned long type);
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 36bc0d5c4f3a..737686fae3c7 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -291,6 +291,15 @@ static int __init feat_enable_idle_stop(struct dt_cpu_feature *f)
lpcr |= LPCR_PECE1;
lpcr |= LPCR_PECE2;
mtspr(SPRN_LPCR, lpcr);
+ stop_dep.cpuidle_prop |= STOP_ENABLE;
+ stop_dep.stop_version = STOP_VERSION_P9;
+
+ return 1;
+}
+
+static int __init feat_enable_firmware_stop(struct dt_cpu_feature *f)
+{
+ stop_dep.cpuidle_prop |= FIRMWARE_STOP_ENABLE;
return 1;
}
@@ -589,6 +598,7 @@ static struct dt_cpu_feature_match __initdata
{"idle-nap", feat_enable_idle_nap, 0},
{"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0},
{"idle-stop", feat_enable_idle_stop, 0},
+ {"firmware-stop-supported", feat_enable_firmware_stop, 0},
{"machine-check-power8", feat_enable_mce_power8, 0},
{"performance-monitor-power8", feat_enable_pmu_power8, 0},
{"data-stream-control-register", feat_enable_dscr, CPU_FTR_DSCR},
@@ -656,6 +666,9 @@ static void __init cpufeatures_setup_start(u32 isa)
}
}
+stop_deps_t stop_dep = {NULL, 0x0, 0x0};
+EXPORT_SYMBOL(stop_dep);
+
static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
{
const struct dt_cpu_feature_match *m;
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 3afd4293f729..3602950f6c08 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -824,7 +824,7 @@ static unsigned long power9_offline_stop(unsigned long psscr)
#ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, true);
+ srr1 = stop_dep.idle_stop(psscr, true);
__ppc64_runlatch_on();
#else
/*
@@ -840,7 +840,7 @@ static unsigned long power9_offline_stop(unsigned long psscr)
local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_IDLE;
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, false);
+ srr1 = stop_dep.idle_stop(psscr, true);
__ppc64_runlatch_on();
local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_KERNEL;
@@ -868,7 +868,7 @@ void power9_idle_type(unsigned long stop_psscr_val,
psscr = (psscr & ~stop_psscr_mask) | stop_psscr_val;
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, true);
+ srr1 = stop_dep.idle_stop(psscr, true);
__ppc64_runlatch_on();
fini_irq_for_idle_irqsoff();
@@ -1365,8 +1365,20 @@ static int __init pnv_init_idle_states(void)
nr_pnv_idle_states = 0;
supported_cpuidle_states = 0;
- if (cpuidle_disable != IDLE_NO_OVERRIDE)
+ if (cpuidle_disable != IDLE_NO_OVERRIDE ||
+ !(stop_dep.cpuidle_prop & STOP_ENABLE))
goto out;
+
+ /* Check for supported version in kernel or fallback to opal*/
+ if (stop_dep.stop_version & STOP_VERSION_P9) {
+ stop_dep.idle_stop = power9_idle_stop;
+ } else if (stop_dep.cpuidle_prop & FIRMWARE_STOP_ENABLE) {
+ stop_dep.idle_stop = power9_firmware_idle_stop;
+ } else {
+ stop_dep.idle_stop = NULL;
+ goto out;
+ }
+
rc = pnv_parse_cpuidle_dt();
if (rc)
return rc;
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 1b299e801f74..7430a8edf5c9 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -371,7 +371,8 @@ static int powernv_add_idle_states(void)
*/
static int powernv_idle_probe(void)
{
- if (cpuidle_disable != IDLE_NO_OVERRIDE)
+ if (cpuidle_disable != IDLE_NO_OVERRIDE ||
+ !(stop_dep.cpuidle_prop & STOP_ENABLE))
return -ENODEV;
if (firmware_has_feature(FW_FEATURE_OPAL)) {
--
2.17.1
^ permalink raw reply related
* [PATCH] powerpc/numa: Restrict possible nodes based on platform
From: Srikar Dronamraju @ 2020-07-06 6:40 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, linuxppc-dev, Srikar Dronamraju, Bharata B Rao
As per PAPR, there are 2 device tree property
ibm,max-associativity-domains (which defines the maximum number of
domains that the firmware i.e PowerVM can support) and
ibm,current-associativity-domains (which defines the maximum number of
domains that the platform can support). Value of
ibm,max-associativity-domains property is always greater than or equal
to ibm,current-associativity-domains property.
Powerpc currently uses ibm,max-associativity-domains property while
setting the possible number of nodes. This is currently set at 32.
However the possible number of nodes for a platform may be significantly
less. Hence set the possible number of nodes based on
ibm,current-associativity-domains property.
$ lsprop /proc/device-tree/rtas/ibm,*associ*-domains
/proc/device-tree/rtas/ibm,current-associativity-domains
00000005 00000001 00000002 00000002 00000002 00000010
/proc/device-tree/rtas/ibm,max-associativity-domains
00000005 00000001 00000008 00000020 00000020 00000100
$ cat /sys/devices/system/node/possible ##Before patch
0-31
$ cat /sys/devices/system/node/possible ##After patch
0-1
Note the maximum nodes this platform can support is only 2 but the
possible nodes is set to 32.
This is important because lot of kernel and user space code allocate
structures for all possible nodes leading to a lot of memory that is
allocated but not used.
I ran a simple experiment to create and destroy 100 memory cgroups on
boot on a 8 node machine (Power8 Alpine).
Before patch
free -k at boot
total used free shared buff/cache available
Mem: 523498176 4106816 518820608 22272 570752 516606720
Swap: 4194240 0 4194240
free -k after creating 100 memory cgroups
total used free shared buff/cache available
Mem: 523498176 4628416 518246464 22336 623296 516058688
Swap: 4194240 0 4194240
free -k after destroying 100 memory cgroups
total used free shared buff/cache available
Mem: 523498176 4697408 518173760 22400 627008 515987904
Swap: 4194240 0 4194240
After patch
free -k at boot
total used free shared buff/cache available
Mem: 523498176 3969472 518933888 22272 594816 516731776
Swap: 4194240 0 4194240
free -k after creating 100 memory cgroups
total used free shared buff/cache available
Mem: 523498176 4181888 518676096 22208 640192 516496448
Swap: 4194240 0 4194240
free -k after destroying 100 memory cgroups
total used free shared buff/cache available
Mem: 523498176 4232320 518619904 22272 645952 516443264
Swap: 4194240 0 4194240
Observations:
Fixed kernel takes 137344 kb (4106816-3969472) less to boot.
Fixed kernel takes 309184 kb (4628416-4181888-137344) less to create 100 memcgs.
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Anton Blanchard <anton@ozlabs.org>
Cc: Bharata B Rao <bharata@linux.ibm.com>
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
---
arch/powerpc/mm/numa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 9fcf2d195830..3d55cef1a2dc 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -897,7 +897,7 @@ static void __init find_possible_nodes(void)
return;
if (of_property_read_u32_index(rtas,
- "ibm,max-associativity-domains",
+ "ibm,current-associativity-domains",
min_common_depth, &numnodes))
goto out;
--
2.18.2
^ permalink raw reply related
* Re: [PATCH v5 10/26] powerpc/book3s64/pkeys: Convert pkey_total to max_pkey
From: Michael Ellerman @ 2020-07-06 7:04 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev; +Cc: Aneesh Kumar K.V, linuxram, bauerman
In-Reply-To: <20200619135850.47155-11-aneesh.kumar@linux.ibm.com>
"Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
> max_pkey now represents max key value that userspace can allocate.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> ---
> arch/powerpc/include/asm/pkeys.h | 7 +++++--
> arch/powerpc/mm/book3s64/pkeys.c | 14 +++++++-------
> 2 files changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
> index 75d2a2c19c04..652bad7334f3 100644
> --- a/arch/powerpc/include/asm/pkeys.h
> +++ b/arch/powerpc/include/asm/pkeys.h
> @@ -12,7 +12,7 @@
> #include <asm/firmware.h>
>
> DECLARE_STATIC_KEY_FALSE(pkey_disabled);
> -extern int pkeys_total; /* total pkeys as per device tree */
> +extern int max_pkey;
> extern u32 initial_allocation_mask; /* bits set for the initially allocated keys */
> extern u32 reserved_allocation_mask; /* bits set for reserved keys */
>
> @@ -44,7 +44,10 @@ static inline int vma_pkey(struct vm_area_struct *vma)
> return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT;
> }
>
> -#define arch_max_pkey() pkeys_total
> +static inline int arch_max_pkey(void)
> +{
> + return max_pkey;
> +}
If pkeys_total = 32 then max_pkey = 31.
So we can't just substitute one for the other. ie. arch_max_pkey() must
have been wrong, or it is wrong now.
> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
> index 87d882a9aaf2..a4d7287082a8 100644
> --- a/arch/powerpc/mm/book3s64/pkeys.c
> +++ b/arch/powerpc/mm/book3s64/pkeys.c
> @@ -14,7 +14,7 @@
>
> DEFINE_STATIC_KEY_FALSE(pkey_disabled);
> DEFINE_STATIC_KEY_FALSE(execute_pkey_disabled);
> -int pkeys_total; /* Total pkeys as per device tree */
> +int max_pkey; /* Maximum key value supported */
> u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
> /*
> * Keys marked in the reservation list cannot be allocated by userspace
> @@ -84,7 +84,7 @@ static int scan_pkey_feature(void)
>
> static int pkey_initialize(void)
> {
> - int os_reserved, i;
> + int pkeys_total, i;
>
> /*
> * We define PKEY_DISABLE_EXECUTE in addition to the arch-neutral
> @@ -122,12 +122,12 @@ static int pkey_initialize(void)
> * The OS can manage only 8 pkeys due to its inability to represent them
> * in the Linux 4K PTE. Mark all other keys reserved.
> */
> - os_reserved = pkeys_total - 8;
> + max_pkey = min(8, pkeys_total);
Shouldn't it be 7 ?
> #else
> - os_reserved = 0;
> + max_pkey = pkeys_total;
> #endif
>
> - if (unlikely((pkeys_total - os_reserved) <= execute_only_key)) {
> + if (unlikely(max_pkey <= execute_only_key)) {
Isn't that an off-by-one now?
This is one-off boot time code, there's no need to clutter it with
unlikely.
> /*
> * Insufficient number of keys to support
> * execute only key. Mark it unavailable.
> @@ -174,10 +174,10 @@ static int pkey_initialize(void)
> default_uamor &= ~(0x3ul << pkeyshift(1));
>
> /*
> - * Prevent the usage of OS reserved the keys. Update UAMOR
> + * Prevent the usage of OS reserved keys. Update UAMOR
> * for those keys.
> */
> - for (i = (pkeys_total - os_reserved); i < pkeys_total; i++) {
> + for (i = max_pkey; i < pkeys_total; i++) {
Another off-by-one? Shouldn't we start from max_pkey + 1 ?
> reserved_allocation_mask |= (0x1 << i);
> default_uamor &= ~(0x3ul << pkeyshift(i));
> }
cheers
^ permalink raw reply
* Re: [PATCH v5 11/26] powerpc/book3s64/pkeys: Make initial_allocation_mask static
From: Michael Ellerman @ 2020-07-06 7:04 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev; +Cc: Aneesh Kumar K.V, linuxram, bauerman
In-Reply-To: <20200619135850.47155-12-aneesh.kumar@linux.ibm.com>
"Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
> initial_allocation_mask is not used outside this file.
And never modified after init, so make it __ro_after_init as well?
cheers
> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
> index 652bad7334f3..47c81d41ea9a 100644
> --- a/arch/powerpc/include/asm/pkeys.h
> +++ b/arch/powerpc/include/asm/pkeys.h
> @@ -13,7 +13,6 @@
>
> DECLARE_STATIC_KEY_FALSE(pkey_disabled);
> extern int max_pkey;
> -extern u32 initial_allocation_mask; /* bits set for the initially allocated keys */
> extern u32 reserved_allocation_mask; /* bits set for reserved keys */
>
> #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \
> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
> index a4d7287082a8..73b5ef1490c8 100644
> --- a/arch/powerpc/mm/book3s64/pkeys.c
> +++ b/arch/powerpc/mm/book3s64/pkeys.c
> @@ -15,11 +15,11 @@
> DEFINE_STATIC_KEY_FALSE(pkey_disabled);
> DEFINE_STATIC_KEY_FALSE(execute_pkey_disabled);
> int max_pkey; /* Maximum key value supported */
> -u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
> /*
> * Keys marked in the reservation list cannot be allocated by userspace
> */
> u32 reserved_allocation_mask;
> +static u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
> static u64 default_amr;
> static u64 default_iamr;
> /* Allow all keys to be modified by default */
> --
> 2.26.2
^ permalink raw reply
* Re: [PATCH v5 08/26] powerpc/book3s64/pkeys: Convert execute key support to static key
From: Michael Ellerman @ 2020-07-06 7:19 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev; +Cc: Aneesh Kumar K.V, linuxram, bauerman
In-Reply-To: <20200619135850.47155-9-aneesh.kumar@linux.ibm.com>
"Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
> Convert the bool to a static key like pkey_disabled.
I'm not convinced this is worth the added complexity of a static key.
It's not used in any performance critical paths, except for context
switch, but that's already guarded by:
if (old_thread->iamr != new_thread->iamr)
Which should always be false on machines which don't have the execute
key enabled.
cheers
> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
> index 9e68a08799ee..7d400d5a4076 100644
> --- a/arch/powerpc/mm/book3s64/pkeys.c
> +++ b/arch/powerpc/mm/book3s64/pkeys.c
> @@ -13,13 +13,13 @@
> #include <linux/of_device.h>
>
> DEFINE_STATIC_KEY_TRUE(pkey_disabled);
> +DEFINE_STATIC_KEY_FALSE(execute_pkey_disabled);
> int pkeys_total; /* Total pkeys as per device tree */
> u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
> /*
> * Keys marked in the reservation list cannot be allocated by userspace
> */
> u32 reserved_allocation_mask;
> -static bool pkey_execute_disable_supported;
> static u64 default_amr;
> static u64 default_iamr;
> /* Allow all keys to be modified by default */
> @@ -116,9 +116,7 @@ static int pkey_initialize(void)
> * execute_disable support. Instead we use a PVR check.
> */
> if (pvr_version_is(PVR_POWER7) || pvr_version_is(PVR_POWER7p))
> - pkey_execute_disable_supported = false;
> - else
> - pkey_execute_disable_supported = true;
> + static_branch_enable(&execute_pkey_disabled);
>
> #ifdef CONFIG_PPC_4K_PAGES
> /*
> @@ -214,7 +212,7 @@ static inline void write_amr(u64 value)
>
> static inline u64 read_iamr(void)
> {
> - if (!likely(pkey_execute_disable_supported))
> + if (static_branch_unlikely(&execute_pkey_disabled))
> return 0x0UL;
>
> return mfspr(SPRN_IAMR);
> @@ -222,7 +220,7 @@ static inline u64 read_iamr(void)
>
> static inline void write_iamr(u64 value)
> {
> - if (!likely(pkey_execute_disable_supported))
> + if (static_branch_unlikely(&execute_pkey_disabled))
> return;
>
> mtspr(SPRN_IAMR, value);
> @@ -282,7 +280,7 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
> return -EINVAL;
>
> if (init_val & PKEY_DISABLE_EXECUTE) {
> - if (!pkey_execute_disable_supported)
> + if (static_branch_unlikely(&execute_pkey_disabled))
> return -EINVAL;
> new_iamr_bits |= IAMR_EX_BIT;
> }
> --
> 2.26.2
^ permalink raw reply
* Re: [PATCH v5 15/26] powerpc/book3s64/pkeys: Use execute_pkey_disable static key
From: Michael Ellerman @ 2020-07-06 7:20 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev; +Cc: Aneesh Kumar K.V, linuxram, bauerman
In-Reply-To: <20200619135850.47155-16-aneesh.kumar@linux.ibm.com>
"Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
> Use execute_pkey_disabled static key to check for execute key support instead
> of pkey_disabled.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> ---
> arch/powerpc/include/asm/pkeys.h | 10 +---------
> arch/powerpc/mm/book3s64/pkeys.c | 5 ++++-
> 2 files changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
> index 47c81d41ea9a..09fbaa409ac4 100644
> --- a/arch/powerpc/include/asm/pkeys.h
> +++ b/arch/powerpc/include/asm/pkeys.h
> @@ -126,15 +126,7 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
> * Try to dedicate one of the protection keys to be used as an
> * execute-only protection key.
> */
> -extern int __execute_only_pkey(struct mm_struct *mm);
> -static inline int execute_only_pkey(struct mm_struct *mm)
> -{
> - if (static_branch_likely(&pkey_disabled))
> - return -1;
> -
> - return __execute_only_pkey(mm);
> -}
> -
> +extern int execute_only_pkey(struct mm_struct *mm);
> extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
> int prot, int pkey);
> static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
> index bbba9c601e14..fed4f159011b 100644
> --- a/arch/powerpc/mm/book3s64/pkeys.c
> +++ b/arch/powerpc/mm/book3s64/pkeys.c
> @@ -345,8 +345,11 @@ void thread_pkey_regs_init(struct thread_struct *thread)
> write_uamor(default_uamor);
> }
>
> -int __execute_only_pkey(struct mm_struct *mm)
> +int execute_only_pkey(struct mm_struct *mm)
> {
> + if (static_branch_likely(&execute_pkey_disabled))
> + return -1;
> +
> return mm->context.execute_only_pkey;
> }
That adds the overhead of a function call, but then uses a static_key to
avoid an easy to predict branch, which seems like a bad tradeoff. And
it's not a performance critical path AFAICS.
Anyway this seems unnecessary:
pkey_early_init_devtree()
{
...
if (unlikely(max_pkey <= execute_only_key)) {
/*
* Insufficient number of keys to support
* execute only key. Mark it unavailable.
*/
execute_only_key = -1;
void pkey_mm_init(struct mm_struct *mm)
{
...
mm->context.execute_only_pkey = execute_only_key;
}
ie. Can't it just be:
static inline int execute_only_pkey(struct mm_struct *mm)
{
return mm->context.execute_only_pkey;
}
cheers
^ permalink raw reply
* Re: [PATCH v5 10/26] powerpc/book3s64/pkeys: Convert pkey_total to max_pkey
From: Aneesh Kumar K.V @ 2020-07-06 7:20 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev; +Cc: linuxram, bauerman
In-Reply-To: <87tuyl5dko.fsf@mpe.ellerman.id.au>
On 7/6/20 12:34 PM, Michael Ellerman wrote:
> "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
>> max_pkey now represents max key value that userspace can allocate.
>>
I guess commit message is confusing.
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>> arch/powerpc/include/asm/pkeys.h | 7 +++++--
>> arch/powerpc/mm/book3s64/pkeys.c | 14 +++++++-------
>> 2 files changed, 12 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
>> index 75d2a2c19c04..652bad7334f3 100644
>> --- a/arch/powerpc/include/asm/pkeys.h
>> +++ b/arch/powerpc/include/asm/pkeys.h
>> @@ -12,7 +12,7 @@
>> #include <asm/firmware.h>
>>
>> DECLARE_STATIC_KEY_FALSE(pkey_disabled);
>> -extern int pkeys_total; /* total pkeys as per device tree */
>> +extern int max_pkey;
>> extern u32 initial_allocation_mask; /* bits set for the initially allocated keys */
>> extern u32 reserved_allocation_mask; /* bits set for reserved keys */
>>
>> @@ -44,7 +44,10 @@ static inline int vma_pkey(struct vm_area_struct *vma)
>> return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT;
>> }
>>
>> -#define arch_max_pkey() pkeys_total
>> +static inline int arch_max_pkey(void)
>> +{
>> + return max_pkey;
>> +}
>
> If pkeys_total = 32 then max_pkey = 31.
we have
#ifdef CONFIG_PPC_4K_PAGES
/*
* The OS can manage only 8 pkeys due to its inability to represent them
* in the Linux 4K PTE. Mark all other keys reserved.
*/
max_pkey = min(8, pkeys_total);
#else
max_pkey = pkeys_total;
#endif
so it is 32.
>
> So we can't just substitute one for the other. ie. arch_max_pkey() must
> have been wrong, or it is wrong now.
>
>> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
>> index 87d882a9aaf2..a4d7287082a8 100644
>> --- a/arch/powerpc/mm/book3s64/pkeys.c
>> +++ b/arch/powerpc/mm/book3s64/pkeys.c
>> @@ -14,7 +14,7 @@
>>
>> DEFINE_STATIC_KEY_FALSE(pkey_disabled);
>> DEFINE_STATIC_KEY_FALSE(execute_pkey_disabled);
>> -int pkeys_total; /* Total pkeys as per device tree */
>> +int max_pkey; /* Maximum key value supported */
>> u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
>> /*
>> * Keys marked in the reservation list cannot be allocated by userspace
>> @@ -84,7 +84,7 @@ static int scan_pkey_feature(void)
>>
>> static int pkey_initialize(void)
>> {
>> - int os_reserved, i;
>> + int pkeys_total, i;
>>
>> /*
>> * We define PKEY_DISABLE_EXECUTE in addition to the arch-neutral
>> @@ -122,12 +122,12 @@ static int pkey_initialize(void)
>> * The OS can manage only 8 pkeys due to its inability to represent them
>> * in the Linux 4K PTE. Mark all other keys reserved.
>> */
>> - os_reserved = pkeys_total - 8;
>> + max_pkey = min(8, pkeys_total);
>
> Shouldn't it be 7 ?
>
>> #else
>> - os_reserved = 0;
>> + max_pkey = pkeys_total;
>> #endif
>>
>> - if (unlikely((pkeys_total - os_reserved) <= execute_only_key)) {
>> + if (unlikely(max_pkey <= execute_only_key)) {
>
> Isn't that an off-by-one now?
>
> This is one-off boot time code, there's no need to clutter it with
> unlikely.
>
>> /*
>> * Insufficient number of keys to support
>> * execute only key. Mark it unavailable.
>> @@ -174,10 +174,10 @@ static int pkey_initialize(void)
>> default_uamor &= ~(0x3ul << pkeyshift(1));
>>
>> /*
>> - * Prevent the usage of OS reserved the keys. Update UAMOR
>> + * Prevent the usage of OS reserved keys. Update UAMOR
>> * for those keys.
>> */
>> - for (i = (pkeys_total - os_reserved); i < pkeys_total; i++) {
>> + for (i = max_pkey; i < pkeys_total; i++) {
>
> Another off-by-one? Shouldn't we start from max_pkey + 1 ?
>
>> reserved_allocation_mask |= (0x1 << i);
>> default_uamor &= ~(0x3ul << pkeyshift(i));
>> }
>
It is the commit message. It is max pkey such that userspace can
allocate 0 - maxp_pkey -1.
-aneesh
^ permalink raw reply
* [RFC][PATCH] avoid refcounting the lazy tlb mm struct
From: Nicholas Piggin @ 2020-07-06 7:23 UTC (permalink / raw)
To: linux-mm; +Cc: linux-arch, linuxppc-dev
On big systems, the mm refcount can become highly contented when doing
a lot of context switching with threaded applications (particularly
switching between the idle thread and an application thread).
Not doing lazy tlb at all slows switching down quite a bit, so I wonder
if we can avoid the refcount for the lazy tlb, but have __mmdrop() IPI
all CPUs that might be using this mm lazily.
This patch has only had light testing so far, but seems to work okay.
Thanks,
Nick
--
diff --git a/arch/Kconfig b/arch/Kconfig
index 8cc35dc556c7..69ea7172db3d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -411,6 +411,16 @@ config MMU_GATHER_NO_GATHER
bool
depends on MMU_GATHER_TABLE_FREE
+config MMU_LAZY_TLB_SHOOTDOWN
+ bool
+ help
+ Instead of refcounting the "lazy tlb" mm struct, which can cause
+ contention with multi-threaded apps on large multiprocessor systems,
+ this option causes __mmdrop to IPI all CPUs in the mm_cpumask and
+ switch to init_mm if they were using the to-be-freed mm as the lazy
+ tlb. Architectures which do not track all possible lazy tlb CPUs in
+ mm_cpumask can not use this (without modification).
+
config ARCH_HAVE_NMI_SAFE_CMPXCHG
bool
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 920c4e3ca4ef..24ac85c868db 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -225,6 +225,7 @@ config PPC
select HAVE_PERF_USER_STACK_DUMP
select MMU_GATHER_RCU_TABLE_FREE
select MMU_GATHER_PAGE_SIZE
+ select MMU_LAZY_TLB_SHOOTDOWN
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
select HAVE_SYSCALL_TRACEPOINTS
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index b5cc9b23cf02..52730629b3eb 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -652,10 +652,10 @@ static void do_exit_flush_lazy_tlb(void *arg)
* Must be a kernel thread because sender is single-threaded.
*/
BUG_ON(current->mm);
- mmgrab(&init_mm);
+ mmgrab_lazy_tlb(&init_mm);
switch_mm(mm, &init_mm, current);
current->active_mm = &init_mm;
- mmdrop(mm);
+ mmdrop_lazy_tlb(mm);
}
_tlbiel_pid(pid, RIC_FLUSH_ALL);
}
diff --git a/fs/exec.c b/fs/exec.c
index e6e8a9a70327..6c96c8feba1f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1119,7 +1119,7 @@ static int exec_mmap(struct mm_struct *mm)
mmput(old_mm);
return 0;
}
- mmdrop(active_mm);
+ mmdrop_lazy_tlb(active_mm);
return 0;
}
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index 480a4d1b7dd8..ef28059086a1 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -51,6 +51,25 @@ static inline void mmdrop(struct mm_struct *mm)
void mmdrop(struct mm_struct *mm);
+static inline void mmgrab_lazy_tlb(struct mm_struct *mm)
+{
+ if (!IS_ENABLED(CONFIG_MMU_LAZY_TLB_SHOOTDOWN))
+ mmgrab(mm);
+}
+
+static inline void mmdrop_lazy_tlb(struct mm_struct *mm)
+{
+ if (!IS_ENABLED(CONFIG_MMU_LAZY_TLB_SHOOTDOWN))
+ mmdrop(mm);
+}
+
+static inline void mmdrop_lazy_tlb_smp_mb(struct mm_struct *mm)
+{
+ mmdrop_lazy_tlb(mm);
+ if (IS_ENABLED(CONFIG_MMU_LAZY_TLB_SHOOTDOWN))
+ smp_mb();
+}
+
/*
* This has to be called after a get_task_mm()/mmget_not_zero()
* followed by taking the mmap_lock for writing before modifying the
diff --git a/kernel/fork.c b/kernel/fork.c
index 142b23645d82..e3f1039cee9f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -685,6 +685,34 @@ static void check_mm(struct mm_struct *mm)
#define allocate_mm() (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
#define free_mm(mm) (kmem_cache_free(mm_cachep, (mm)))
+static void do_shoot_lazy_tlb(void *arg)
+{
+ struct mm_struct *mm = arg;
+
+ if (current->active_mm == mm) {
+ BUG_ON(current->mm);
+ switch_mm(mm, &init_mm, current);
+ current->active_mm = &init_mm;
+ }
+}
+
+static void do_check_lazy_tlb(void *arg)
+{
+ struct mm_struct *mm = arg;
+
+ BUG_ON(current->active_mm == mm);
+}
+
+void shoot_lazy_tlbs(struct mm_struct *mm)
+{
+ if (IS_ENABLED(CONFIG_MMU_LAZY_TLB_SHOOTDOWN)) {
+ smp_call_function_many(mm_cpumask(mm), do_shoot_lazy_tlb, (void *)mm, 1);
+ do_shoot_lazy_tlb(mm);
+ }
+ smp_call_function(do_check_lazy_tlb, (void *)mm, 1);
+ do_check_lazy_tlb(mm);
+}
+
/*
* Called when the last reference to the mm
* is dropped: either by a lazy thread or by
@@ -692,6 +720,7 @@ static void check_mm(struct mm_struct *mm)
*/
void __mmdrop(struct mm_struct *mm)
{
+ shoot_lazy_tlbs(mm);
BUG_ON(mm == &init_mm);
WARN_ON_ONCE(mm == current->mm);
WARN_ON_ONCE(mm == current->active_mm);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ca5db40392d4..4d615e0be9e0 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3308,7 +3308,7 @@ static struct rq *finish_task_switch(struct task_struct *prev)
*/
if (mm) {
membarrier_mm_sync_core_before_usermode(mm);
- mmdrop(mm);
+ mmdrop_lazy_tlb_smp_mb(mm);
}
if (unlikely(prev_state == TASK_DEAD)) {
if (prev->sched_class->task_dead)
@@ -3413,9 +3413,9 @@ context_switch(struct rq *rq, struct task_struct *prev,
/*
* kernel -> kernel lazy + transfer active
- * user -> kernel lazy + mmgrab() active
+ * user -> kernel lazy + mmgrab_lazy_tlb() active
*
- * kernel -> user switch + mmdrop() active
+ * kernel -> user switch + mmdrop_lazy_tlb() active
* user -> user switch
*/
if (!next->mm) { // to kernel
@@ -3423,7 +3423,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
next->active_mm = prev->active_mm;
if (prev->mm) // from user
- mmgrab(prev->active_mm);
+ mmgrab_lazy_tlb(prev->active_mm);
else
prev->active_mm = NULL;
} else { // to user
@@ -3439,7 +3439,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
switch_mm_irqs_off(prev->active_mm, next->mm, next);
if (!prev->mm) { // from kernel
- /* will mmdrop() in finish_task_switch(). */
+ /* will mmdrop_lazy_tlb() in finish_task_switch(). */
rq->prev_mm = prev->active_mm;
prev->active_mm = NULL;
}
^ permalink raw reply related
* Re: [PATCH v5 17/26] powerpc/book3s64/keys: Print information during boot.
From: Michael Ellerman @ 2020-07-06 7:52 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev; +Cc: Aneesh Kumar K.V, linuxram, bauerman
In-Reply-To: <20200619135850.47155-18-aneesh.kumar@linux.ibm.com>
"Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> ---
> arch/powerpc/mm/book3s64/pkeys.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
> index 810118123e70..0d72c0246052 100644
> --- a/arch/powerpc/mm/book3s64/pkeys.c
> +++ b/arch/powerpc/mm/book3s64/pkeys.c
> @@ -195,6 +195,7 @@ void __init pkey_early_init_devtree(void)
> */
> initial_allocation_mask |= reserved_allocation_mask;
>
> + pr_info("Enabling Memory keys with max key count %d", max_pkey);
^
missing newline
> return;
> }
The syscall is called pkey_mprotect() and the manpage is "pkeys", so I
think it would make sense to use "pkey" in the message.
cheers
^ permalink raw reply
* Re: [PATCH v8 4/4] powerpc: Book3S 64-bit "heavyweight" KASAN support
From: kernel test robot @ 2020-07-06 8:29 UTC (permalink / raw)
To: Daniel Axtens, linux-kernel, linux-mm, linuxppc-dev, kasan-dev,
christophe.leroy, aneesh.kumar, bsingharora
Cc: kbuild-all, Daniel Axtens
In-Reply-To: <20200702025432.16912-5-dja@axtens.net>
[-- Attachment #1: Type: text/plain, Size: 14987 bytes --]
Hi Daniel,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on powerpc/next]
[also build test WARNING on linux/master linus/master v5.8-rc4 next-20200703]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Daniel-Axtens/KASAN-for-powerpc64-radix/20200702-105552
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc64-randconfig-s031-20200706 (attached as .config)
compiler: powerpc64le-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.2-14-g8fce3d7a-dirty
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=powerpc64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
drivers/char/tpm/tpm_ibmvtpm.c:130:9: sparse: sparse: cast removes address space '__iomem' of expression
>> drivers/char/tpm/tpm_ibmvtpm.c:131:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *s @@ got void [noderef] __iomem *rtce_buf @@
>> drivers/char/tpm/tpm_ibmvtpm.c:131:9: sparse: expected void *s
drivers/char/tpm/tpm_ibmvtpm.c:131:9: sparse: got void [noderef] __iomem *rtce_buf
drivers/char/tpm/tpm_ibmvtpm.c:234:9: sparse: sparse: cast removes address space '__iomem' of expression
drivers/char/tpm/tpm_ibmvtpm.c:369:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const * @@ got void [noderef] __iomem *rtce_buf @@
drivers/char/tpm/tpm_ibmvtpm.c:369:30: sparse: expected void const *
drivers/char/tpm/tpm_ibmvtpm.c:369:30: sparse: got void [noderef] __iomem *rtce_buf
drivers/char/tpm/tpm_ibmvtpm.c:530:43: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected void [noderef] __iomem *rtce_buf @@ got void * @@
drivers/char/tpm/tpm_ibmvtpm.c:530:43: sparse: expected void [noderef] __iomem *rtce_buf
drivers/char/tpm/tpm_ibmvtpm.c:530:43: sparse: got void *
drivers/char/tpm/tpm_ibmvtpm.c:537:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void *ptr @@ got void [noderef] __iomem *rtce_buf @@
drivers/char/tpm/tpm_ibmvtpm.c:537:52: sparse: expected void *ptr
drivers/char/tpm/tpm_ibmvtpm.c:537:52: sparse: got void [noderef] __iomem *rtce_buf
drivers/char/tpm/tpm_ibmvtpm.c:543:46: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const * @@ got void [noderef] __iomem *rtce_buf @@
drivers/char/tpm/tpm_ibmvtpm.c:543:46: sparse: expected void const *
drivers/char/tpm/tpm_ibmvtpm.c:543:46: sparse: got void [noderef] __iomem *rtce_buf
--
drivers/tty/vt/vt.c:233:5: sparse: sparse: symbol 'console_blank_hook' was not declared. Should it be static?
drivers/tty/vt/vt.c:2901:19: sparse: sparse: symbol 'console_driver' was not declared. Should it be static?
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
>> arch/powerpc/include/asm/vga.h:40:21: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected unsigned short [usertype] @@ got restricted __le16 [usertype] @@
>> arch/powerpc/include/asm/vga.h:40:21: sparse: expected unsigned short [usertype]
arch/powerpc/include/asm/vga.h:40:21: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:34:16: sparse: sparse: cast to restricted __le16
arch/powerpc/include/asm/vga.h:29:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short volatile [usertype] @@ got restricted __le16 [usertype] @@
arch/powerpc/include/asm/vga.h:29:15: sparse: expected unsigned short volatile [usertype]
arch/powerpc/include/asm/vga.h:29:15: sparse: got restricted __le16 [usertype]
vim +131 drivers/char/tpm/tpm_ibmvtpm.c
132f7629474424 Ashley Lai 2012-08-22 94
132f7629474424 Ashley Lai 2012-08-22 95 /**
132f7629474424 Ashley Lai 2012-08-22 96 * tpm_ibmvtpm_recv - Receive data after send
93c12f293f8798 Winkler, Tomas 2016-11-23 97 *
132f7629474424 Ashley Lai 2012-08-22 98 * @chip: tpm chip struct
132f7629474424 Ashley Lai 2012-08-22 99 * @buf: buffer to read
93c12f293f8798 Winkler, Tomas 2016-11-23 100 * @count: size of buffer
132f7629474424 Ashley Lai 2012-08-22 101 *
93c12f293f8798 Winkler, Tomas 2016-11-23 102 * Return:
132f7629474424 Ashley Lai 2012-08-22 103 * Number of bytes read
132f7629474424 Ashley Lai 2012-08-22 104 */
132f7629474424 Ashley Lai 2012-08-22 105 static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
132f7629474424 Ashley Lai 2012-08-22 106 {
9e0d39d8a6a0a8 Christophe Ricard 2016-03-31 107 struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
132f7629474424 Ashley Lai 2012-08-22 108 u16 len;
b5666502700855 Ashley Lai 2012-09-12 109 int sig;
132f7629474424 Ashley Lai 2012-08-22 110
132f7629474424 Ashley Lai 2012-08-22 111 if (!ibmvtpm->rtce_buf) {
132f7629474424 Ashley Lai 2012-08-22 112 dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
132f7629474424 Ashley Lai 2012-08-22 113 return 0;
132f7629474424 Ashley Lai 2012-08-22 114 }
132f7629474424 Ashley Lai 2012-08-22 115
6674ff145eef1f Stefan Berger 2015-12-09 116 sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
b5666502700855 Ashley Lai 2012-09-12 117 if (sig)
b5666502700855 Ashley Lai 2012-09-12 118 return -EINTR;
b5666502700855 Ashley Lai 2012-09-12 119
b5666502700855 Ashley Lai 2012-09-12 120 len = ibmvtpm->res_len;
132f7629474424 Ashley Lai 2012-08-22 121
b5666502700855 Ashley Lai 2012-09-12 122 if (count < len) {
132f7629474424 Ashley Lai 2012-08-22 123 dev_err(ibmvtpm->dev,
37ab03414829e5 Jason Gunthorpe 2013-09-14 124 "Invalid size in recv: count=%zd, crq_size=%d\n",
b5666502700855 Ashley Lai 2012-09-12 125 count, len);
132f7629474424 Ashley Lai 2012-08-22 126 return -EIO;
132f7629474424 Ashley Lai 2012-08-22 127 }
132f7629474424 Ashley Lai 2012-08-22 128
132f7629474424 Ashley Lai 2012-08-22 129 spin_lock(&ibmvtpm->rtce_lock);
b5666502700855 Ashley Lai 2012-09-12 130 memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len);
b5666502700855 Ashley Lai 2012-09-12 @131 memset(ibmvtpm->rtce_buf, 0, len);
b5666502700855 Ashley Lai 2012-09-12 132 ibmvtpm->res_len = 0;
132f7629474424 Ashley Lai 2012-08-22 133 spin_unlock(&ibmvtpm->rtce_lock);
132f7629474424 Ashley Lai 2012-08-22 134 return len;
132f7629474424 Ashley Lai 2012-08-22 135 }
132f7629474424 Ashley Lai 2012-08-22 136
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27407 bytes --]
^ permalink raw reply
* Re: [PATCH v5 08/26] powerpc/book3s64/pkeys: Convert execute key support to static key
From: Aneesh Kumar K.V @ 2020-07-06 8:47 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev; +Cc: linuxram, bauerman
In-Reply-To: <87o8ot5cv5.fsf@mpe.ellerman.id.au>
On 7/6/20 12:49 PM, Michael Ellerman wrote:
> "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
>> Convert the bool to a static key like pkey_disabled.
>
> I'm not convinced this is worth the added complexity of a static key.
>
> It's not used in any performance critical paths, except for context
> switch, but that's already guarded by:
>
> if (old_thread->iamr != new_thread->iamr)
>
> Which should always be false on machines which don't have the execute
> key enabled.
>
Ok will drop the patch.
-aneesh
^ permalink raw reply
* Re: [PATCH v5 11/26] powerpc/book3s64/pkeys: Make initial_allocation_mask static
From: Aneesh Kumar K.V @ 2020-07-06 8:48 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev; +Cc: linuxram, bauerman
In-Reply-To: <87sge55dkh.fsf@mpe.ellerman.id.au>
On 7/6/20 12:34 PM, Michael Ellerman wrote:
> "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
>> initial_allocation_mask is not used outside this file.
>
> And never modified after init, so make it __ro_after_init as well?
>
ok, will update reserved_allocation_maask too.
> cheers
>
>> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
>> index 652bad7334f3..47c81d41ea9a 100644
>> --- a/arch/powerpc/include/asm/pkeys.h
>> +++ b/arch/powerpc/include/asm/pkeys.h
>> @@ -13,7 +13,6 @@
>>
>> DECLARE_STATIC_KEY_FALSE(pkey_disabled);
>> extern int max_pkey;
>> -extern u32 initial_allocation_mask; /* bits set for the initially allocated keys */
>> extern u32 reserved_allocation_mask; /* bits set for reserved keys */
>>
>> #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \
>> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
>> index a4d7287082a8..73b5ef1490c8 100644
>> --- a/arch/powerpc/mm/book3s64/pkeys.c
>> +++ b/arch/powerpc/mm/book3s64/pkeys.c
>> @@ -15,11 +15,11 @@
>> DEFINE_STATIC_KEY_FALSE(pkey_disabled);
>> DEFINE_STATIC_KEY_FALSE(execute_pkey_disabled);
>> int max_pkey; /* Maximum key value supported */
>> -u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
>> /*
>> * Keys marked in the reservation list cannot be allocated by userspace
>> */
>> u32 reserved_allocation_mask;
>> +static u32 initial_allocation_mask; /* Bits set for the initially allocated keys */
>> static u64 default_amr;
>> static u64 default_iamr;
>> /* Allow all keys to be modified by default */
>> --
>> 2.26.2
-aneesh
^ permalink raw reply
* Re: [PATCH v5 15/26] powerpc/book3s64/pkeys: Use execute_pkey_disable static key
From: Aneesh Kumar K.V @ 2020-07-06 8:49 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev; +Cc: linuxram, bauerman
In-Reply-To: <87mu4d5cu8.fsf@mpe.ellerman.id.au>
On 7/6/20 12:50 PM, Michael Ellerman wrote:
> "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> writes:
>> Use execute_pkey_disabled static key to check for execute key support instead
>> of pkey_disabled.
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>> arch/powerpc/include/asm/pkeys.h | 10 +---------
>> arch/powerpc/mm/book3s64/pkeys.c | 5 ++++-
>> 2 files changed, 5 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
>> index 47c81d41ea9a..09fbaa409ac4 100644
>> --- a/arch/powerpc/include/asm/pkeys.h
>> +++ b/arch/powerpc/include/asm/pkeys.h
>> @@ -126,15 +126,7 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
>> * Try to dedicate one of the protection keys to be used as an
>> * execute-only protection key.
>> */
>> -extern int __execute_only_pkey(struct mm_struct *mm);
>> -static inline int execute_only_pkey(struct mm_struct *mm)
>> -{
>> - if (static_branch_likely(&pkey_disabled))
>> - return -1;
>> -
>> - return __execute_only_pkey(mm);
>> -}
>> -
>> +extern int execute_only_pkey(struct mm_struct *mm);
>> extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
>> int prot, int pkey);
>> static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
>> diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
>> index bbba9c601e14..fed4f159011b 100644
>> --- a/arch/powerpc/mm/book3s64/pkeys.c
>> +++ b/arch/powerpc/mm/book3s64/pkeys.c
>> @@ -345,8 +345,11 @@ void thread_pkey_regs_init(struct thread_struct *thread)
>> write_uamor(default_uamor);
>> }
>>
>> -int __execute_only_pkey(struct mm_struct *mm)
>> +int execute_only_pkey(struct mm_struct *mm)
>> {
>> + if (static_branch_likely(&execute_pkey_disabled))
>> + return -1;
>> +
>> return mm->context.execute_only_pkey;
>> }
>
> That adds the overhead of a function call, but then uses a static_key to
> avoid an easy to predict branch, which seems like a bad tradeoff. And
> it's not a performance critical path AFAICS.
>
> Anyway this seems unnecessary:
>
> pkey_early_init_devtree()
> {
> ...
> if (unlikely(max_pkey <= execute_only_key)) {
> /*
> * Insufficient number of keys to support
> * execute only key. Mark it unavailable.
> */
> execute_only_key = -1;
>
> void pkey_mm_init(struct mm_struct *mm)
> {
> ...
> mm->context.execute_only_pkey = execute_only_key;
> }
>
>
> ie. Can't it just be:
>
> static inline int execute_only_pkey(struct mm_struct *mm)
> {
> return mm->context.execute_only_pkey;
> }
>
ok updated with
modified arch/powerpc/mm/book3s64/pkeys.c
@@ -151,7 +151,7 @@ void __init pkey_early_init_devtree(void)
max_pkey = pkeys_total;
#endif
- if (unlikely(max_pkey <= execute_only_key)) {
+ if (unlikely(max_pkey <= execute_only_key) ||
!pkey_execute_disable_supported) {
/*
* Insufficient number of keys to support
* execute only key. Mark it unavailable.
@@ -368,9 +368,6 @@ int __arch_set_user_pkey_access(struct task_struct
*tsk, int pkey,
int execute_only_pkey(struct mm_struct *mm)
{
- if (static_branch_likely(&execute_pkey_disabled))
- return -1;
-
return mm->context.execute_only_pkey;
}
-aneesh
^ permalink raw reply
* Re: [PATCH v2 01/12] kexec_file: allow archs to handle special regions while locating memory hole
From: Dave Young @ 2020-07-06 9:07 UTC (permalink / raw)
To: Hari Bathini
Cc: Thiago Jung Bauermann, kernel test robot, Pingfan Liu, Kexec-ml,
Mahesh J Salgaonkar, Petr Tesarik, lkml, linuxppc-dev, Mimi Zohar,
Sourabh Jain, Andrew Morton, Vivek Goyal, Eric Biederman
In-Reply-To: <159371964681.21555.573193508667543223.stgit@hbathini.in.ibm.com>
On 07/03/20 at 01:24am, Hari Bathini wrote:
> Some architectures may have special memory regions, within the given
> memory range, which can't be used for the buffer in a kexec segment.
> Implement weak arch_kexec_locate_mem_hole() definition which arch code
> may override, to take care of special regions, while trying to locate
> a memory hole.
>
> Also, add the missing declarations for arch overridable functions and
> and drop the __weak descriptors in the declarations to avoid non-weak
> definitions from becoming weak.
>
> Reported-by: kernel test robot <lkp@intel.com>
> [lkp: In v1, arch_kimage_file_post_load_cleanup() declaration was missing]
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
>
> Changes in v2:
> * Introduced arch_kexec_locate_mem_hole() for override and dropped
> weak arch_kexec_add_buffer().
> * Dropped __weak identifier for arch overridable functions.
> * Fixed the missing declaration for arch_kimage_file_post_load_cleanup()
> reported by lkp. lkp report for reference:
> - https://lore.kernel.org/patchwork/patch/1264418/
>
>
> include/linux/kexec.h | 29 ++++++++++++++++++-----------
> kernel/kexec_file.c | 16 ++++++++++++++--
> 2 files changed, 32 insertions(+), 13 deletions(-)
>
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index ea67910..9e93bef 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -183,17 +183,24 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
> bool get_value);
> void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
>
> -int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> - unsigned long buf_len);
> -void * __weak arch_kexec_kernel_image_load(struct kimage *image);
> -int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
> - Elf_Shdr *section,
> - const Elf_Shdr *relsec,
> - const Elf_Shdr *symtab);
> -int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
> - Elf_Shdr *section,
> - const Elf_Shdr *relsec,
> - const Elf_Shdr *symtab);
> +/* Architectures may override the below functions */
> +int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> + unsigned long buf_len);
> +void *arch_kexec_kernel_image_load(struct kimage *image);
> +int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
> + Elf_Shdr *section,
> + const Elf_Shdr *relsec,
> + const Elf_Shdr *symtab);
> +int arch_kexec_apply_relocations(struct purgatory_info *pi,
> + Elf_Shdr *section,
> + const Elf_Shdr *relsec,
> + const Elf_Shdr *symtab);
> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
> +#ifdef CONFIG_KEXEC_SIG
> +int arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
> + unsigned long buf_len);
> +#endif
> +int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf);
>
> extern int kexec_add_buffer(struct kexec_buf *kbuf);
> int kexec_locate_mem_hole(struct kexec_buf *kbuf);
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 09cc78d..e89912d 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -636,6 +636,19 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
> }
>
> /**
> + * arch_kexec_locate_mem_hole - Find free memory to place the segments.
> + * @kbuf: Parameters for the memory search.
> + *
> + * On success, kbuf->mem will have the start address of the memory region found.
> + *
> + * Return: 0 on success, negative errno on error.
> + */
> +int __weak arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
> +{
> + return kexec_locate_mem_hole(kbuf);
> +}
> +
> +/**
> * kexec_add_buffer - place a buffer in a kexec segment
> * @kbuf: Buffer contents and memory parameters.
> *
> @@ -647,7 +660,6 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
> */
> int kexec_add_buffer(struct kexec_buf *kbuf)
> {
> -
> struct kexec_segment *ksegment;
> int ret;
>
> @@ -675,7 +687,7 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
> kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
>
> /* Walk the RAM ranges and allocate a suitable range for the buffer */
> - ret = kexec_locate_mem_hole(kbuf);
> + ret = arch_kexec_locate_mem_hole(kbuf);
> if (ret)
> return ret;
>
>
Acked-by: Dave Young <dyoung@redhat.com>
Thanks
Dave
^ permalink raw reply
* Re: [PATCH 01/14] powerpc/eeh: Remove eeh_dev_phb_init_dynamic()
From: kernel test robot @ 2020-07-06 9:12 UTC (permalink / raw)
To: Oliver O'Halloran, linuxppc-dev
Cc: Oliver O'Halloran, kbuild-all, mahesh
In-Reply-To: <20200706013619.459420-2-oohall@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3420 bytes --]
Hi Oliver,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on v5.8-rc4 next-20200706]
[cannot apply to scottwood/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Oliver-O-Halloran/powerpc-eeh-Remove-eeh_dev_phb_init_dynamic/20200706-103630
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc64-randconfig-r006-20200706 (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=powerpc64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/kernel/of_platform.c: In function 'of_pci_phb_probe':
>> arch/powerpc/kernel/of_platform.c:66:2: error: implicit declaration of function 'eeh_phb_pe_create' [-Werror=implicit-function-declaration]
66 | eeh_phb_pe_create(phb);
| ^~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
vim +/eeh_phb_pe_create +66 arch/powerpc/kernel/of_platform.c
28
29 /* The probing of PCI controllers from of_platform is currently
30 * 64 bits only, mostly due to gratuitous differences between
31 * the 32 and 64 bits PCI code on PowerPC and the 32 bits one
32 * lacking some bits needed here.
33 */
34
35 static int of_pci_phb_probe(struct platform_device *dev)
36 {
37 struct pci_controller *phb;
38
39 /* Check if we can do that ... */
40 if (ppc_md.pci_setup_phb == NULL)
41 return -ENODEV;
42
43 pr_info("Setting up PCI bus %pOF\n", dev->dev.of_node);
44
45 /* Alloc and setup PHB data structure */
46 phb = pcibios_alloc_controller(dev->dev.of_node);
47 if (!phb)
48 return -ENODEV;
49
50 /* Setup parent in sysfs */
51 phb->parent = &dev->dev;
52
53 /* Setup the PHB using arch provided callback */
54 if (ppc_md.pci_setup_phb(phb)) {
55 pcibios_free_controller(phb);
56 return -ENODEV;
57 }
58
59 /* Process "ranges" property */
60 pci_process_bridge_OF_ranges(phb, dev->dev.of_node, 0);
61
62 /* Init pci_dn data structures */
63 pci_devs_phb_init_dynamic(phb);
64
65 /* Create EEH PE for the PHB */
> 66 eeh_phb_pe_create(phb);
67
68 /* Scan the bus */
69 pcibios_scan_phb(phb);
70 if (phb->bus == NULL)
71 return -ENXIO;
72
73 /* Claim resources. This might need some rework as well depending
74 * whether we are doing probe-only or not, like assigning unassigned
75 * resources etc...
76 */
77 pcibios_claim_one_bus(phb->bus);
78
79 /* Add probed PCI devices to the device model */
80 pci_bus_add_devices(phb->bus);
81
82 return 0;
83 }
84
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36529 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: select ARCH_HAS_MEMBARRIER_SYNC_CORE
From: Christophe Leroy @ 2020-07-06 9:53 UTC (permalink / raw)
To: Nicholas Piggin, linuxppc-dev; +Cc: linux-arch, Mathieu Desnoyers
In-Reply-To: <20200706021822.1515189-1-npiggin@gmail.com>
Le 06/07/2020 à 04:18, Nicholas Piggin a écrit :
> powerpc return from interrupt and return from system call sequences are
> context synchronising.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> .../features/sched/membarrier-sync-core/arch-support.txt | 4 ++--
> arch/powerpc/Kconfig | 1 +
> arch/powerpc/include/asm/exception-64s.h | 4 ++++
> 3 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/features/sched/membarrier-sync-core/arch-support.txt b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
> index 8a521a622966..52ad74a25f54 100644
> --- a/Documentation/features/sched/membarrier-sync-core/arch-support.txt
> +++ b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
> @@ -5,7 +5,7 @@
> #
> # Architecture requirements
> #
> -# * arm/arm64
> +# * arm/arm64/powerpc
> #
> # Rely on implicit context synchronization as a result of exception return
> # when returning from IPI handler, and when returning to user-space.
> @@ -45,7 +45,7 @@
> | nios2: | TODO |
> | openrisc: | TODO |
> | parisc: | TODO |
> - | powerpc: | TODO |
> + | powerpc: | ok |
> | riscv: | TODO |
> | s390: | TODO |
> | sh: | TODO |
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 9fa23eb320ff..920c4e3ca4ef 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -131,6 +131,7 @@ config PPC
> select ARCH_HAS_PTE_DEVMAP if PPC_BOOK3S_64
> select ARCH_HAS_PTE_SPECIAL
> select ARCH_HAS_MEMBARRIER_CALLBACKS
> + select ARCH_HAS_MEMBARRIER_SYNC_CORE
> select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
> select ARCH_HAS_STRICT_KERNEL_RWX if (PPC32 && !HIBERNATION)
> select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
> diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
> index 47bd4ea0837d..b88cb3a989b6 100644
> --- a/arch/powerpc/include/asm/exception-64s.h
> +++ b/arch/powerpc/include/asm/exception-64s.h
> @@ -68,6 +68,10 @@
> *
> * The nop instructions allow us to insert one or more instructions to flush the
> * L1-D cache when returning to userspace or a guest.
> + *
> + * powerpc relies on return from interrupt/syscall being context synchronising
> + * (which hrfid, rfid, and rfscv are) to support ARCH_HAS_MEMBARRIER_SYNC_CORE
> + * without additional additional synchronisation instructions.
This file is dedicated to BOOK3S/64. What about other ones ?
On 32 bits, this is also valid as 'rfi' is also context synchronising,
but then why just add some comment in exception-64s.h and only there ?
> */
> #define RFI_FLUSH_SLOT \
> RFI_FLUSH_FIXUP_SECTION; \
>
Christophe
^ permalink raw reply
* Re: [PATCH v12 00/31] Speculative page faults
From: Chinwen Chang @ 2020-07-06 9:25 UTC (permalink / raw)
To: Haiyan Song
Cc: jack, sergey.senozhatsky.work, peterz, Will Deacon, mhocko,
linux-mm, paulus, Punit Agrawal, hpa, Michel Lespinasse,
Alexei Starovoitov, Andrea Arcangeli, ak, Minchan Kim,
aneesh.kumar, x86, Matthew Wilcox, Daniel Jordan, Ingo Molnar,
David Rientjes, paulmck, npiggin, sj38.park, Jerome Glisse, dave,
kemi.wang, kirill, Thomas Gleixner, Laurent Dufour, zhong jiang,
Ganesh Mahendran, Yang Shi, Mike Rapoport, linuxppc-dev,
linux-kernel, Sergey Senozhatsky, miles.chen, vinayak menon, akpm,
Tim Chen, haren
In-Reply-To: <20190620081945.hwj6ruqddefnxg6z@haiyan.sh.intel.com>
On Thu, 2019-06-20 at 16:19 +0800, Haiyan Song wrote:
> Hi Laurent,
>
> I downloaded your script and run it on Intel 2s skylake platform with spf-v12 patch
> serials.
>
> Here attached the output results of this script.
>
> The following comparison result is statistics from the script outputs.
>
> a). Enable THP
> SPF_0 change SPF_1
> will-it-scale.page_fault2.per_thread_ops 2664190.8 -11.7% 2353637.6
> will-it-scale.page_fault3.per_thread_ops 4480027.2 -14.7% 3819331.9
>
>
> b). Disable THP
> SPF_0 change SPF_1
> will-it-scale.page_fault2.per_thread_ops 2653260.7 -10% 2385165.8
> will-it-scale.page_fault3.per_thread_ops 4436330.1 -12.4% 3886734.2
>
>
> Thanks,
> Haiyan Song
>
>
> On Fri, Jun 14, 2019 at 10:44:47AM +0200, Laurent Dufour wrote:
> > Le 14/06/2019 à 10:37, Laurent Dufour a écrit :
> > > Please find attached the script I run to get these numbers.
> > > This would be nice if you could give it a try on your victim node and share the result.
> >
> > Sounds that the Intel mail fitering system doesn't like the attached shell script.
> > Please find it there: https://gist.github.com/ldu4/a5cc1a93f293108ea387d43d5d5e7f44
> >
> > Thanks,
> > Laurent.
> >
Hi Laurent,
We merged SPF v11 and some patches from v12 into our platforms. After
several experiments, we observed SPF has obvious improvements on the
launch time of applications, especially for those high-TLP ones,
# launch time of applications(s):
package version w/ SPF w/o SPF improve(%)
------------------------------------------------------------------
Baidu maps 10.13.3 0.887 0.98 9.49
Taobao 8.4.0.35 1.227 1.293 5.10
Meituan 9.12.401 1.107 1.543 28.26
WeChat 7.0.3 2.353 2.68 12.20
Honor of Kings 1.43.1.6 6.63 6.713 1.24
By the way, we have verified our platforms with those patches and
achieved the goal of mass production.
Thanks.
Chinwen Chang
^ permalink raw reply
* [PATCH 0/11 RFC] PCI: Remove "*val = 0" from pcie_capability_read_*()
From: Saheed Olayemi Bolarinwa @ 2020-07-06 9:31 UTC (permalink / raw)
To: helgaas
Cc: Mike Marciniszyn, linuxppc-dev,
Greg Kroah-Hartman linux-rdma @ vger . kernel . org,
Arnd Bergmann, Jason Gunthorpe, Sam Bobroff,
Bolarinwa Olayemi Saheed, Dennis Dalessandro, skhan,
Rafael J. Wysocki, linux-kernel, wunner.de, linux-acpi,
Doug Ledford, linux-pci, bjorn, Oliver O'Halloran,
linux-kernel-mentees, linux-rdma
From: Bolarinwa Olayemi Saheed <refactormyself@gmail.com>
*** BLURB HERE ***
Bolarinwa Olayemi Saheed (9):
IB/hfi1: Confirm that pcie_capability_read_dword() is successful
misc: rtsx: Confirm that pcie_capability_read_word() is successful
PCI/AER: Use error return value from pcie_capability_read_*()
PCI/ASPM: Use error return value from pcie_capability_read_*()
PCI: pciehp: Fix wrong failure check on pcie_capability_read_*()
PCI: pciehp: Prevent wrong failure check on pcie_capability_read_*()
PCI: pciehp: Make "Power On" the default in pciehp_get_power_status()
PCI/ACPI: Prevent wrong failure check on pcie_capability_read_*()
PCI: Prevent wrong failure check on pcie_capability_read_*()
PCI: Remove "*val = 0" fom pcie_capability_read_*()
drivers/infiniband/hw/hfi1/aspm.c | 7 ++++---
drivers/misc/cardreader/rts5227.c | 5 +++--
drivers/misc/cardreader/rts5249.c | 5 +++--
drivers/misc/cardreader/rts5260.c | 5 +++--
drivers/misc/cardreader/rts5261.c | 5 +++--
drivers/pci/pcie/aer.c | 5 +++--
drivers/pci/pcie/aspm.c | 33 +++++++++++++++++----------------
drivers/pci/hotplug/pciehp_hpc.c | 47 ++++++++++++++++----------------
drivers/pci/pci-acpi.c | 10 ++++---
drivers/pci/probe.c | 29 ++++++++++++--------
drivers/pci/access.c | 14 --------------
11 files changed, 82 insertions(+), 83 deletions(-)
--
2.18.2
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox