From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:48:56
This series adds an option to use queued spinlocks for powerpc, and
makes it the default for the Book3S-64 subarch.
This effort starts with the generic code so it's very simple but
still very performant. There are optimisations that can be made to
slowpaths, but I think it's better to attack those incrementally
if/when we find things, and try to add the improvements to generic
code as much as possible.
Still in the process of getting numbers and testing, but the
implementation turned out to be surprisingly simple and we have a
config option, so I think we could merge it fairly soon.
Thanks,
Nick
Nicholas Piggin (8):
powerpc/powernv: must include hvcall.h to get PAPR defines
powerpc/pseries: use smp_rmb() in H_CONFER spin yield
powerpc/pseries: move some PAPR paravirt functions to their own file
powerpc: move spinlock implementation to simple_spinlock
powerpc/64s: implement queued spinlocks and rwlocks
powerpc/pseries: implement paravirt qspinlocks for SPLPAR
powerpc/qspinlock: optimised atomic_try_cmpxchg_lock that adds the
lock hint
powerpc/64s: remove paravirt from simple spinlocks (RFC only)
arch/powerpc/Kconfig | 13 +
arch/powerpc/include/asm/Kbuild | 2 +
arch/powerpc/include/asm/atomic.h | 28 ++
arch/powerpc/include/asm/paravirt.h | 84 +++++
arch/powerpc/include/asm/qspinlock.h | 75 +++++
arch/powerpc/include/asm/qspinlock_paravirt.h | 5 +
arch/powerpc/include/asm/simple_spinlock.h | 235 +++++++++++++
.../include/asm/simple_spinlock_types.h | 21 ++
arch/powerpc/include/asm/spinlock.h | 308 +-----------------
arch/powerpc/include/asm/spinlock_types.h | 17 +-
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 6 -
arch/powerpc/lib/Makefile | 1 -
arch/powerpc/lib/locks.c | 65 ----
arch/powerpc/platforms/powernv/pci-ioda-tce.c | 1 +
arch/powerpc/platforms/pseries/Kconfig | 5 +
arch/powerpc/platforms/pseries/setup.c | 6 +-
include/asm-generic/qspinlock.h | 4 +
17 files changed, 488 insertions(+), 388 deletions(-)
create mode 100644 arch/powerpc/include/asm/paravirt.h
create mode 100644 arch/powerpc/include/asm/qspinlock.h
create mode 100644 arch/powerpc/include/asm/qspinlock_paravirt.h
create mode 100644 arch/powerpc/include/asm/simple_spinlock.h
create mode 100644 arch/powerpc/include/asm/simple_spinlock_types.h
delete mode 100644 arch/powerpc/lib/locks.c
--
2.23.0
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:49:03
An include goes away in future patches which breaks compilation
without this.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/powernv/pci-ioda-tce.c | 1 +
1 file changed, 1 insertion(+)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:49:08
There is no need for rmb(), this allows faster lwsync here.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/lib/locks.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -30,7 +30,7 @@ void splpar_spin_yield(arch_spinlock_t *lock)yield_count=be32_to_cpu(lppaca_of(holder_cpu).yield_count);if((yield_count&1)==0)return;/* virtual cpu is currently running */-rmb();+smp_rmb();if(lock->slock!=lock_value)return;/* something has changed */plpar_hcall_norets(H_CONFER,
@@ -56,7 +56,7 @@ void splpar_rw_yield(arch_rwlock_t *rw)yield_count=be32_to_cpu(lppaca_of(holder_cpu).yield_count);if((yield_count&1)==0)return;/* virtual cpu is currently running */-rmb();+smp_rmb();if(rw->lock!=lock_value)return;/* something has changed */plpar_hcall_norets(H_CONFER,
From: Peter Zijlstra <peterz@infradead.org> Date: 2020-07-02 08:28:55
On Thu, Jul 02, 2020 at 05:48:33PM +1000, Nicholas Piggin wrote:
There is no need for rmb(), this allows faster lwsync here.
Since you determined this; I'm thinking you actually understand the
ordering here. How about recording this understanding in a comment?
Also, should the lock->slock load not use READ_ONCE() ?
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 10:36:37
Excerpts from Peter Zijlstra's message of July 2, 2020 6:28 pm:
On Thu, Jul 02, 2020 at 05:48:33PM +1000, Nicholas Piggin wrote:
quoted
There is no need for rmb(), this allows faster lwsync here.
Since you determined this; I'm thinking you actually understand the
ordering here. How about recording this understanding in a comment?
Also, should the lock->slock load not use READ_ONCE() ?
Yeah, good point. Maybe I'll drop it from this series, doesn't really
belong I just saw the cleanup and didn't want to forget it.
We we just ordering the two loads in this function, and !SMP isn't a
concern (i.e., no issues of !SMP guest on SMP HV), but yeah fixing
the lack of comment is warranted, thanks.
Thanks,
Nick
@@ -0,0 +1,61 @@+/* SPDX-License-Identifier: GPL-2.0-or-later */+#ifndef __ASM_PARAVIRT_H+#define __ASM_PARAVIRT_H+#ifdef __KERNEL__++#include<linux/jump_label.h>+#include<asm/smp.h>+#ifdef CONFIG_PPC64+#include<asm/paca.h>+#include<asm/hvcall.h>+#endif++#ifdef CONFIG_PPC_SPLPAR+DECLARE_STATIC_KEY_FALSE(shared_processor);++staticinlineboolis_shared_processor(void)+{+returnstatic_branch_unlikely(&shared_processor);+}++/* If bit 0 is set, the cpu has been preempted */+staticinlineu32yield_count_of(intcpu)+{+__be32yield_count=READ_ONCE(lppaca_of(cpu).yield_count);+returnbe32_to_cpu(yield_count);+}++staticinlinevoidyield_to_preempted(intcpu,u32yield_count)+{+plpar_hcall_norets(H_CONFER,get_hard_smp_processor_id(cpu),yield_count);+}+#else+staticinlineboolis_shared_processor(void)+{+returnfalse;+}++staticinlineu32yield_count_of(intcpu)+{+return0;+}++externvoid___bad_yield_to_preempted(void);+staticinlinevoidyield_to_preempted(intcpu,u32yield_count)+{+___bad_yield_to_preempted();/* This would be a bug */+}+#endif++#define vcpu_is_preempted vcpu_is_preempted+staticinlineboolvcpu_is_preempted(intcpu)+{+if(!is_shared_processor())+returnfalse;+if(yield_count_of(cpu)&1)+returntrue;+returnfalse;+}++#endif /* __KERNEL__ */+#endif /* __ASM_PARAVIRT_H */
@@ -27,14 +27,14 @@ void splpar_spin_yield(arch_spinlock_t *lock)return;holder_cpu=lock_value&0xffff;BUG_ON(holder_cpu>=NR_CPUS);-yield_count=be32_to_cpu(lppaca_of(holder_cpu).yield_count);++yield_count=yield_count_of(holder_cpu);if((yield_count&1)==0)return;/* virtual cpu is currently running */smp_rmb();if(lock->slock!=lock_value)return;/* something has changed */-plpar_hcall_norets(H_CONFER,-get_hard_smp_processor_id(holder_cpu),yield_count);+yield_to_preempted(holder_cpu,yield_count);}EXPORT_SYMBOL_GPL(splpar_spin_yield);
@@ -53,13 +53,13 @@ void splpar_rw_yield(arch_rwlock_t *rw)return;/* no write lock at present */holder_cpu=lock_value&0xffff;BUG_ON(holder_cpu>=NR_CPUS);-yield_count=be32_to_cpu(lppaca_of(holder_cpu).yield_count);++yield_count=yield_count_of(holder_cpu);if((yield_count&1)==0)return;/* virtual cpu is currently running */smp_rmb();if(rw->lock!=lock_value)return;/* something has changed */-plpar_hcall_norets(H_CONFER,-get_hard_smp_processor_id(holder_cpu),yield_count);+yield_to_preempted(holder_cpu,yield_count);}#endif
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:49:23
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 | 20 ++++++++++++++++++++
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, 50 insertions(+)
create mode 100644 arch/powerpc/include/asm/qspinlock.h
A long and sad tale that ends here 51d7d5205d338
Should probably at least refer to that commit from here, since this one
is not going to git blame back there. I'll add something.
Thanks,
Nick
A long and sad tale that ends here 51d7d5205d338
Should probably at least refer to that commit from here, since this one
is not going to git blame back there. I'll add something.
Is this still an issue, though?
See 38b850a73034 (where we added a similar barrier on arm64) and then
c6f5d02b6a0f (where we removed it).
Will
A long and sad tale that ends here 51d7d5205d338
Should probably at least refer to that commit from here, since this one
is not going to git blame back there. I'll add something.
Is this still an issue, though?
See 38b850a73034 (where we added a similar barrier on arm64) and then
c6f5d02b6a0f (where we removed it).
Oh nice, I didn't know that went away. Thanks for the heads up.
I'm going to say I'm too scared to remove it while changing the
spinlock algorithm, but I'll open an issue and we should look at
removing it.
Thanks,
Nick
A long and sad tale that ends here 51d7d5205d338
Should probably at least refer to that commit from here, since this one
is not going to git blame back there. I'll add something.
Is this still an issue, though?
See 38b850a73034 (where we added a similar barrier on arm64) and then
c6f5d02b6a0f (where we removed it).
Oh nice, I didn't know that went away. Thanks for the heads up.
I'm going to say I'm too scared to remove it while changing the
spinlock algorithm, but I'll open an issue and we should look at
removing it.
Makes sense to me -- it certainly needs a deeper look! In the meantime,
please put some of this in a comment next to the barrier.
Cheers,
Will
A long and sad tale that ends here 51d7d5205d338
Should probably at least refer to that commit from here, since this one
is not going to git blame back there. I'll add something.
Is this still an issue, though?
See 38b850a73034 (where we added a similar barrier on arm64) and then
c6f5d02b6a0f (where we removed it).
Oh nice, I didn't know that went away. Thanks for the heads up.
Argh! I spent so much time chasing that damn bug in the ipc code.
I'm going to say I'm too scared to remove it while changing the
spinlock algorithm, but I'll open an issue and we should look at
removing it.
@@ -45,6 +55,19 @@ static inline void yield_to_preempted(int cpu, u32 yield_count){___bad_yield_to_preempted();/* This would be a bug */}++externvoid___bad_yield_to_any(void);+staticinlinevoidyield_to_any(void)+{+___bad_yield_to_any();/* This would be a bug */+}++externvoid___bad_prod_cpu(void);+staticinlinevoidprod_cpu(intcpu)+{+___bad_prod_cpu();/* This would be a bug */+}+#endif#define vcpu_is_preempted vcpu_is_preempted
From: kernel test robot <hidden> Date: 2020-07-02 16:18:17
Hi Nicholas,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on tip/locking/core v5.8-rc3 next-20200702]
[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/Nicholas-Piggin/powerpc-queued-spinlocks-and-rwlocks/20200702-155158
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (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=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>
All errors (new ones prefixed by >>):
kernel/locking/lock_events.c:61:16: warning: no previous prototype for 'lockevent_read' [-Wmissing-prototypes]
61 | ssize_t __weak lockevent_read(struct file *file, char __user *user_buf,
| ^~~~~~~~~~~~~~
kernel/locking/lock_events.c: In function 'skip_lockevent':
quoted
kernel/locking/lock_events.c:126:12: error: implicit declaration of function 'pv_is_native_spin_unlock' [-Werror=implicit-function-declaration]
126 | pv_on = !pv_is_native_spin_unlock();
| ^~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/pv_is_native_spin_unlock +126 kernel/locking/lock_events.c
fb346fd9fc081c Waiman Long 2019-04-04 57
fb346fd9fc081c Waiman Long 2019-04-04 58 /*
fb346fd9fc081c Waiman Long 2019-04-04 59 * The lockevent_read() function can be overridden.
fb346fd9fc081c Waiman Long 2019-04-04 60 */
fb346fd9fc081c Waiman Long 2019-04-04 @61 ssize_t __weak lockevent_read(struct file *file, char __user *user_buf,
fb346fd9fc081c Waiman Long 2019-04-04 62 size_t count, loff_t *ppos)
fb346fd9fc081c Waiman Long 2019-04-04 63 {
fb346fd9fc081c Waiman Long 2019-04-04 64 char buf[64];
fb346fd9fc081c Waiman Long 2019-04-04 65 int cpu, id, len;
fb346fd9fc081c Waiman Long 2019-04-04 66 u64 sum = 0;
fb346fd9fc081c Waiman Long 2019-04-04 67
fb346fd9fc081c Waiman Long 2019-04-04 68 /*
fb346fd9fc081c Waiman Long 2019-04-04 69 * Get the counter ID stored in file->f_inode->i_private
fb346fd9fc081c Waiman Long 2019-04-04 70 */
fb346fd9fc081c Waiman Long 2019-04-04 71 id = (long)file_inode(file)->i_private;
fb346fd9fc081c Waiman Long 2019-04-04 72
fb346fd9fc081c Waiman Long 2019-04-04 73 if (id >= lockevent_num)
fb346fd9fc081c Waiman Long 2019-04-04 74 return -EBADF;
fb346fd9fc081c Waiman Long 2019-04-04 75
fb346fd9fc081c Waiman Long 2019-04-04 76 for_each_possible_cpu(cpu)
fb346fd9fc081c Waiman Long 2019-04-04 77 sum += per_cpu(lockevents[id], cpu);
fb346fd9fc081c Waiman Long 2019-04-04 78 len = snprintf(buf, sizeof(buf) - 1, "%llu\n", sum);
fb346fd9fc081c Waiman Long 2019-04-04 79
fb346fd9fc081c Waiman Long 2019-04-04 80 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
fb346fd9fc081c Waiman Long 2019-04-04 81 }
fb346fd9fc081c Waiman Long 2019-04-04 82
fb346fd9fc081c Waiman Long 2019-04-04 83 /*
fb346fd9fc081c Waiman Long 2019-04-04 84 * Function to handle write request
fb346fd9fc081c Waiman Long 2019-04-04 85 *
fb346fd9fc081c Waiman Long 2019-04-04 86 * When idx = reset_cnts, reset all the counts.
fb346fd9fc081c Waiman Long 2019-04-04 87 */
fb346fd9fc081c Waiman Long 2019-04-04 88 static ssize_t lockevent_write(struct file *file, const char __user *user_buf,
fb346fd9fc081c Waiman Long 2019-04-04 89 size_t count, loff_t *ppos)
fb346fd9fc081c Waiman Long 2019-04-04 90 {
fb346fd9fc081c Waiman Long 2019-04-04 91 int cpu;
fb346fd9fc081c Waiman Long 2019-04-04 92
fb346fd9fc081c Waiman Long 2019-04-04 93 /*
fb346fd9fc081c Waiman Long 2019-04-04 94 * Get the counter ID stored in file->f_inode->i_private
fb346fd9fc081c Waiman Long 2019-04-04 95 */
fb346fd9fc081c Waiman Long 2019-04-04 96 if ((long)file_inode(file)->i_private != LOCKEVENT_reset_cnts)
fb346fd9fc081c Waiman Long 2019-04-04 97 return count;
fb346fd9fc081c Waiman Long 2019-04-04 98
fb346fd9fc081c Waiman Long 2019-04-04 99 for_each_possible_cpu(cpu) {
fb346fd9fc081c Waiman Long 2019-04-04 100 int i;
fb346fd9fc081c Waiman Long 2019-04-04 101 unsigned long *ptr = per_cpu_ptr(lockevents, cpu);
fb346fd9fc081c Waiman Long 2019-04-04 102
fb346fd9fc081c Waiman Long 2019-04-04 103 for (i = 0 ; i < lockevent_num; i++)
fb346fd9fc081c Waiman Long 2019-04-04 104 WRITE_ONCE(ptr[i], 0);
fb346fd9fc081c Waiman Long 2019-04-04 105 }
fb346fd9fc081c Waiman Long 2019-04-04 106 return count;
fb346fd9fc081c Waiman Long 2019-04-04 107 }
fb346fd9fc081c Waiman Long 2019-04-04 108
fb346fd9fc081c Waiman Long 2019-04-04 109 /*
fb346fd9fc081c Waiman Long 2019-04-04 110 * Debugfs data structures
fb346fd9fc081c Waiman Long 2019-04-04 111 */
fb346fd9fc081c Waiman Long 2019-04-04 112 static const struct file_operations fops_lockevent = {
fb346fd9fc081c Waiman Long 2019-04-04 113 .read = lockevent_read,
fb346fd9fc081c Waiman Long 2019-04-04 114 .write = lockevent_write,
fb346fd9fc081c Waiman Long 2019-04-04 115 .llseek = default_llseek,
fb346fd9fc081c Waiman Long 2019-04-04 116 };
fb346fd9fc081c Waiman Long 2019-04-04 117
bf20616f46e536 Waiman Long 2019-04-04 118 #ifdef CONFIG_PARAVIRT_SPINLOCKS
bf20616f46e536 Waiman Long 2019-04-04 119 #include <asm/paravirt.h>
bf20616f46e536 Waiman Long 2019-04-04 120
bf20616f46e536 Waiman Long 2019-04-04 121 static bool __init skip_lockevent(const char *name)
bf20616f46e536 Waiman Long 2019-04-04 122 {
bf20616f46e536 Waiman Long 2019-04-04 123 static int pv_on __initdata = -1;
bf20616f46e536 Waiman Long 2019-04-04 124
bf20616f46e536 Waiman Long 2019-04-04 125 if (pv_on < 0)
bf20616f46e536 Waiman Long 2019-04-04 @126 pv_on = !pv_is_native_spin_unlock();
bf20616f46e536 Waiman Long 2019-04-04 127 /*
bf20616f46e536 Waiman Long 2019-04-04 128 * Skip PV qspinlock events on bare metal.
bf20616f46e536 Waiman Long 2019-04-04 129 */
bf20616f46e536 Waiman Long 2019-04-04 130 if (!pv_on && !memcmp(name, "pv_", 3))
bf20616f46e536 Waiman Long 2019-04-04 131 return true;
bf20616f46e536 Waiman Long 2019-04-04 132 return false;
bf20616f46e536 Waiman Long 2019-04-04 133 }
bf20616f46e536 Waiman Long 2019-04-04 134 #else
bf20616f46e536 Waiman Long 2019-04-04 135 static inline bool skip_lockevent(const char *name)
bf20616f46e536 Waiman Long 2019-04-04 136 {
bf20616f46e536 Waiman Long 2019-04-04 137 return false;
bf20616f46e536 Waiman Long 2019-04-04 138 }
bf20616f46e536 Waiman Long 2019-04-04 139 #endif
bf20616f46e536 Waiman Long 2019-04-04 140
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
From: Waiman Long <longman@redhat.com> Date: 2020-07-03 00:36:18
On 7/2/20 12:15 PM, kernel test robot wrote:
Hi Nicholas,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on tip/locking/core v5.8-rc3 next-20200702]
[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/Nicholas-Piggin/powerpc-queued-spinlocks-and-rwlocks/20200702-155158
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (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=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>
All errors (new ones prefixed by >>):
kernel/locking/lock_events.c:61:16: warning: no previous prototype for 'lockevent_read' [-Wmissing-prototypes]
61 | ssize_t __weak lockevent_read(struct file *file, char __user *user_buf,
| ^~~~~~~~~~~~~~
kernel/locking/lock_events.c: In function 'skip_lockevent':
quoted
quoted
kernel/locking/lock_events.c:126:12: error: implicit declaration of function 'pv_is_native_spin_unlock' [-Werror=implicit-function-declaration]
126 | pv_on = !pv_is_native_spin_unlock();
| ^~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/pv_is_native_spin_unlock +126 kernel/locking/lock_events.c
I think you will need to add the following into
arch/powerpc/include/asm/qspinlock_paravirt.h:
static inline pv_is_native_spin_unlock(void)
{
return !is_shared_processor();
}
Cheers,
Longman
@@ -45,6 +55,19 @@ static inline void yield_to_preempted(int cpu, u32 yield_count){___bad_yield_to_preempted();/* This would be a bug */}++externvoid___bad_yield_to_any(void);+staticinlinevoidyield_to_any(void)+{+___bad_yield_to_any();/* This would be a bug */+}++externvoid___bad_prod_cpu(void);+staticinlinevoidprod_cpu(intcpu)+{+___bad_prod_cpu();/* This would be a bug */+}+#endif#define vcpu_is_preempted vcpu_is_preempted
You may need to match the use of __pv_queued_spin_lock_slowpath() with
the corresponding __pv_queued_spin_unlock(), e.g.
#define queued_spin_unlock queued_spin_unlock
static inline queued_spin_unlock(struct qspinlock *lock)
{
if (!is_shared_processor())
smp_store_release(&lock->locked, 0);
else
__pv_queued_spin_unlock(lock);
}
Otherwise, pv_kick() will never be called.
Cheers,
Longman
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:49:34
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(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-07-02 07:49:40
RFC until we settle on queued spinlocks for 64s and remove the
option to go back to simple locks. If other sub-archs want to keep
simple spinlocks, the code can be nicely simplified.
---
arch/powerpc/include/asm/simple_spinlock.h | 61 +-------------------
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 6 --
arch/powerpc/lib/Makefile | 4 --
arch/powerpc/lib/locks.c | 65 ----------------------
4 files changed, 2 insertions(+), 134 deletions(-)
delete mode 100644 arch/powerpc/lib/locks.c
@@ -16,23 +16,10 @@*(thetypedefinitionsareinasm/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-#endifstatic__always_inlineintarch_spin_value_unlocked(arch_spinlock_tlock){
@@ -74,43 +61,14 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)return__arch_spin_trylock(lock)==0;}-/*-*Onasystemwithsharedprocessors(thatis,whereaphysical-*processorismultiplexedbetweenseveralvirtualprocessors),-*thereisnopointspinningonalockiftheholderofthelock-*isn'tcurrentlyscheduledonaphysicalprocessor.Instead-*wedetectthissituationandaskthehypervisortogivethe-*restofourtimeslicetothelockholder.-*-*Sothatwecantellwhichvirtualprocessorisholdingalock,-*weput0x80000000|smp_processor_id()inthelockwhenitis-*held.Conveniently,wehaveawordinthepacathatholdsthis-*value.-*/--#if defined(CONFIG_PPC_SPLPAR)-/* We only yield to the hypervisor if we are in shared processor mode */-voidsplpar_spin_yield(arch_spinlock_t*lock);-voidsplpar_rw_yield(arch_rwlock_t*lock);-#else /* SPLPAR */-staticinlinevoidsplpar_spin_yield(arch_spinlock_t*lock){};-staticinlinevoidsplpar_rw_yield(arch_rwlock_t*lock){};-#endif-staticinlinevoidspin_yield(arch_spinlock_t*lock){-if(is_shared_processor())-splpar_spin_yield(lock);-else-barrier();+barrier();}staticinlinevoidrw_yield(arch_rwlock_t*lock){-if(is_shared_processor())-splpar_rw_yield(lock);-else-barrier();+barrier();}staticinlinevoidarch_spin_lock(arch_spinlock_t*lock)
@@ -1,65 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- * Spin and read/write 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- */--#include <linux/kernel.h>-#include <linux/spinlock.h>-#include <linux/export.h>-#include <linux/smp.h>--/* waiting for a spinlock... */-#if defined(CONFIG_PPC_SPLPAR)-#include <asm/hvcall.h>-#include <asm/smp.h>--void splpar_spin_yield(arch_spinlock_t *lock)-{- unsigned int lock_value, holder_cpu, yield_count;-- lock_value = lock->slock;- if (lock_value == 0)- return;- holder_cpu = lock_value & 0xffff;- BUG_ON(holder_cpu >= NR_CPUS);-- yield_count = yield_count_of(holder_cpu);- if ((yield_count & 1) == 0)- return; /* virtual cpu is currently running */- smp_rmb();- if (lock->slock != lock_value)- return; /* something has changed */- yield_to_preempted(holder_cpu, yield_count);-}-EXPORT_SYMBOL_GPL(splpar_spin_yield);--/*- * Waiting for a read lock or a write lock on a rwlock...- * This turns out to be the same for read and write locks, since- * we only know the holder if it is write-locked.- */-void splpar_rw_yield(arch_rwlock_t *rw)-{- int lock_value;- unsigned int holder_cpu, yield_count;-- lock_value = rw->lock;- if (lock_value >= 0)- return; /* no write lock at present */- holder_cpu = lock_value & 0xffff;- BUG_ON(holder_cpu >= NR_CPUS);-- yield_count = yield_count_of(holder_cpu);- if ((yield_count & 1) == 0)- return; /* virtual cpu is currently running */- smp_rmb();- if (rw->lock != lock_value)- return; /* something has changed */- yield_to_preempted(holder_cpu, yield_count);-}-#endif