Skip to content

Commit 05eee61

Browse files
Zhenzhong Duanbonzini
authored andcommitted
x86/kvm: Add "nopvspin" parameter to disable PV spinlocks
There are cases where a guest tries to switch spinlocks to bare metal behavior (e.g. by setting "xen_nopvspin" on XEN platform and "hv_nopvspin" on HYPER_V). That feature is missed on KVM, add a new parameter "nopvspin" to disable PV spinlocks for KVM guest. The new 'nopvspin' parameter will also replace Xen and Hyper-V specific parameters in future patches. Define variable nopvsin as global because it will be used in future patches as above. Signed-off-by: Zhenzhong Duan <[email protected]> Reviewed-by: Vitaly Kuznetsov <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Radim Krcmar <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: Vitaly Kuznetsov <[email protected]> Cc: Wanpeng Li <[email protected]> Cc: Jim Mattson <[email protected]> Cc: Joerg Roedel <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 5aefd78 commit 05eee61

File tree

4 files changed

+45
-7
lines changed

4 files changed

+45
-7
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5739,6 +5739,11 @@
57395739
as generic guest with no PV drivers. Currently support
57405740
XEN HVM, KVM, HYPER_V and VMWARE guest.
57415741

5742+
nopvspin [X86,KVM]
5743+
Disables the qspinlock slow path using PV optimizations
5744+
which allow the hypervisor to 'idle' the guest on lock
5745+
contention.
5746+
57425747
xirc2ps_cs= [NET,PCMCIA]
57435748
Format:
57445749
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]

arch/x86/include/asm/qspinlock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extern void native_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
3232
extern void __pv_init_lock_hash(void);
3333
extern void __pv_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
3434
extern void __raw_callee_save___pv_queued_spin_unlock(struct qspinlock *lock);
35+
extern bool nopvspin;
3536

3637
#define queued_spin_unlock queued_spin_unlock
3738
/**

arch/x86/kernel/kvm.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -871,18 +871,36 @@ asm(
871871
*/
872872
void __init kvm_spinlock_init(void)
873873
{
874-
/* Does host kernel support KVM_FEATURE_PV_UNHALT? */
875-
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
874+
/*
875+
* In case host doesn't support KVM_FEATURE_PV_UNHALT there is still an
876+
* advantage of keeping virt_spin_lock_key enabled: virt_spin_lock() is
877+
* preferred over native qspinlock when vCPU is preempted.
878+
*/
879+
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) {
880+
pr_info("PV spinlocks disabled, no host support\n");
876881
return;
882+
}
877883

884+
/*
885+
* Disable PV spinlocks and use native qspinlock when dedicated pCPUs
886+
* are available.
887+
*/
878888
if (kvm_para_has_hint(KVM_HINTS_REALTIME)) {
879-
static_branch_disable(&virt_spin_lock_key);
880-
return;
889+
pr_info("PV spinlocks disabled with KVM_HINTS_REALTIME hints\n");
890+
goto out;
881891
}
882892

883-
/* Don't use the pvqspinlock code if there is only 1 vCPU. */
884-
if (num_possible_cpus() == 1)
885-
return;
893+
if (num_possible_cpus() == 1) {
894+
pr_info("PV spinlocks disabled, single CPU\n");
895+
goto out;
896+
}
897+
898+
if (nopvspin) {
899+
pr_info("PV spinlocks disabled, forced by \"nopvspin\" parameter\n");
900+
goto out;
901+
}
902+
903+
pr_info("PV spinlocks enabled\n");
886904

887905
__pv_init_lock_hash();
888906
pv_ops.lock.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath;
@@ -895,6 +913,13 @@ void __init kvm_spinlock_init(void)
895913
pv_ops.lock.vcpu_is_preempted =
896914
PV_CALLEE_SAVE(__kvm_vcpu_is_preempted);
897915
}
916+
/*
917+
* When PV spinlock is enabled which is preferred over
918+
* virt_spin_lock(), virt_spin_lock_key's value is meaningless.
919+
* Just disable it anyway.
920+
*/
921+
out:
922+
static_branch_disable(&virt_spin_lock_key);
898923
}
899924

900925
#endif /* CONFIG_PARAVIRT_SPINLOCKS */

kernel/locking/qspinlock.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,4 +581,11 @@ EXPORT_SYMBOL(queued_spin_lock_slowpath);
581581
#include "qspinlock_paravirt.h"
582582
#include "qspinlock.c"
583583

584+
bool nopvspin __initdata;
585+
static __init int parse_nopvspin(char *arg)
586+
{
587+
nopvspin = true;
588+
return 0;
589+
}
590+
early_param("nopvspin", parse_nopvspin);
584591
#endif

0 commit comments

Comments
 (0)