Commit a237ea36 authored by Bibo Mao's avatar Bibo Mao Committed by Xianglai Li
Browse files

LoongArch: Revert qspinlock to test-and-set simple lock on VM

mainline inclusion
from mainline-v6.12-rc1
commit e5ba90abb2ebdfd3c19481319b349d4885312bef
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAZJDO


CVE: NA

--------------------------------

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: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
Signed-off-by: default avatarXianglai Li <lixianglai@loongson.cn>
parent 67aa62f6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -6,7 +6,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
+7 −0
Original line number Diff line number Diff line
@@ -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
+41 −0
Original line number Diff line number Diff line
/* 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
+11 −0
Original line number Diff line number Diff line
@@ -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;
}
+2 −0
Original line number Diff line number Diff line
@@ -641,6 +641,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();
Loading