LoongArch: Revert qspinlock to test-and-set simple lock on VM
commit e5ba90abb2eb ("LoongArch: Revert qspinlock to test-and-set simple lock on VM") Conflict: none Backport-reason: Synchronize upstream linux loongarch kvm patch to support loongarch virtualization. Checkpatch: no, to be consistent with upstream commit. Similar with x86, when VM is detected, revert to a simple test-and-set lock to avoid the horrors of queue preemption. Tested on 3C5000 Dual-way machine with 32 cores and 2 numa nodes, test case is kcbench on kernel mainline 6.10, the detailed command is "kcbench --src /root/src/linux" Performance on host machine kernel compile time performance impact Original 150.29 seconds With patch 150.19 seconds almost no impact Performance on virtual machine: 1. 1 VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 170.87 seconds With patch 171.73 seconds almost no impact 2. 2 VMs, each VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 2362.04 seconds With patch 354.73 seconds +565% Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
This commit is contained in:
parent
2205e133b6
commit
b62160a3c5
|
@ -4,7 +4,6 @@ generic-y += mcs_spinlock.h
|
|||
generic-y += parport.h
|
||||
generic-y += early_ioremap.h
|
||||
generic-y += qrwlock.h
|
||||
generic-y += qspinlock.h
|
||||
generic-y += rwsem.h
|
||||
generic-y += segment.h
|
||||
generic-y += user.h
|
||||
|
|
|
@ -18,6 +18,7 @@ static inline u64 paravirt_steal_clock(int cpu)
|
|||
|
||||
int pv_ipi_init(void);
|
||||
int __init pv_time_init(void);
|
||||
int __init pv_spinlock_init(void);
|
||||
#else
|
||||
static inline int pv_ipi_init(void)
|
||||
{
|
||||
|
@ -28,5 +29,11 @@ static inline int pv_time_init(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pv_spinlock_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // CONFIG_PARAVIRT
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_LOONGARCH_QSPINLOCK_H
|
||||
#define _ASM_LOONGARCH_QSPINLOCK_H
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
|
||||
|
||||
#define virt_spin_lock virt_spin_lock
|
||||
|
||||
static inline bool virt_spin_lock(struct qspinlock *lock)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!static_branch_unlikely(&virt_spin_lock_key))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* On hypervisors without PARAVIRT_SPINLOCKS support we fall
|
||||
* back to a Test-and-Set spinlock, because fair locks have
|
||||
* horrible lock 'holder' preemption issues.
|
||||
*/
|
||||
|
||||
__retry:
|
||||
val = atomic_read(&lock->val);
|
||||
|
||||
if (val || !atomic_try_cmpxchg(&lock->val, &val, _Q_LOCKED_VAL)) {
|
||||
cpu_relax();
|
||||
goto __retry;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PARAVIRT */
|
||||
|
||||
#include <asm-generic/qspinlock.h>
|
||||
|
||||
#endif // _ASM_LOONGARCH_QSPINLOCK_H
|
|
@ -12,6 +12,7 @@ static int has_steal_clock;
|
|||
struct static_key paravirt_steal_enabled;
|
||||
struct static_key paravirt_steal_rq_enabled;
|
||||
static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
|
||||
DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key);
|
||||
|
||||
static u64 native_steal_clock(int cpu)
|
||||
{
|
||||
|
@ -563,3 +564,13 @@ int __init pv_time_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init pv_spinlock_init(void)
|
||||
{
|
||||
if (!cpu_has_hypervisor)
|
||||
return 0;
|
||||
|
||||
static_branch_enable(&virt_spin_lock_key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -665,6 +665,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
arch_mem_init(cmdline_p);
|
||||
|
||||
resource_init();
|
||||
jump_label_init(); /* Initialise the static keys for paravirtualization */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
plat_smp_setup();
|
||||
prefill_possible_map();
|
||||
|
|
|
@ -477,7 +477,7 @@ core_initcall(ipi_pm_init);
|
|||
#endif
|
||||
|
||||
/* Preload SMP state for boot cpu */
|
||||
void smp_prepare_boot_cpu(void)
|
||||
void __init smp_prepare_boot_cpu(void)
|
||||
{
|
||||
unsigned int cpu, node, rr_node;
|
||||
|
||||
|
@ -510,6 +510,8 @@ void smp_prepare_boot_cpu(void)
|
|||
rr_node = next_node_in(rr_node, node_online_map);
|
||||
}
|
||||
}
|
||||
|
||||
pv_spinlock_init();
|
||||
}
|
||||
|
||||
/* called from main before smp_init() */
|
||||
|
|
Loading…
Reference in New Issue