On 19/10/2018 15:13, Yi Sun wrote: > The HvNotifyLongSpinWait hypercall (HVCALL_NOTIFY_LONG_SPIN_WAIT) > is used by a guest OS to notify the hypervisor that the calling > virtual processor is attempting to acquire a resource that is > potentially held by another virtual processor within the same > Virtual Machine. This scheduling hint improves the scalability of > VMs with more than one virtual processor on Hyper-V. > > Per MSFT TLFS, the retry number (SpinWaitInfo) is sent to hypervisor > only when the retry number exceeds the recommended number. If > recommended number is 0xFFFFFFFF, never retry. > > Signed-off-by: Yi Sun <yi.y....@linux.intel.com> > Cc: "K. Y. Srinivasan" <k...@microsoft.com> > Cc: Haiyang Zhang <haiya...@microsoft.com> > Cc: Stephen Hemminger <sthem...@microsoft.com> > Cc: Thomas Gleixner <t...@linutronix.de> > Cc: Michael Kelley (EOSG) <michael.h.kel...@microsoft.com> > Cc: Juergen Gross <jgr...@suse.com> > --- > arch/x86/hyperv/hv_spinlock.c | 18 ++++++++++++++++++ > arch/x86/include/asm/mshyperv.h | 1 + > kernel/locking/qspinlock_paravirt.h | 10 ++++++++++ > 3 files changed, 29 insertions(+) > > diff --git a/arch/x86/hyperv/hv_spinlock.c b/arch/x86/hyperv/hv_spinlock.c > index a861b04..723dccb 100644 > --- a/arch/x86/hyperv/hv_spinlock.c > +++ b/arch/x86/hyperv/hv_spinlock.c > @@ -18,6 +18,24 @@ > > static bool __initdata hv_pvspin = true; > > +bool hv_notify_long_spin_wait(int retry_num) > +{ > + /* > + * Per MSFT TLFS, the SpinWaitInfo is sent to hypervisor only when > + * the retry number exceeds the recommended number. > + * > + * If recommended number is 0xFFFFFFFF, never retry. > + */ > + if (ms_hyperv.num_spin_retry == HYPERV_SPINLOCK_RETRY_NEVER) > + return false; > + > + if ((0 == retry_num % ms_hyperv.num_spin_retry) && retry_num) > + hv_do_fast_hypercall8(HVCALL_NOTIFY_LONG_SPIN_WAIT, > + retry_num); > + > + return true; > +} > + > static void hv_qlock_kick(int cpu) > { > apic->send_IPI(cpu, X86_PLATFORM_IPI_VECTOR); > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index f909365..bd87868 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -356,6 +356,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, > void hv_apic_init(void); > void __init hv_init_spinlocks(void); > bool hv_vcpu_is_preempted(int vcpu); > +bool hv_notify_long_spin_wait(int retry_num); > #else > static inline void hv_apic_init(void) {} > #endif > diff --git a/kernel/locking/qspinlock_paravirt.h > b/kernel/locking/qspinlock_paravirt.h > index 0130e48..9e88c7e 100644 > --- a/kernel/locking/qspinlock_paravirt.h > +++ b/kernel/locking/qspinlock_paravirt.h > @@ -7,6 +7,8 @@ > #include <linux/bootmem.h> > #include <linux/debug_locks.h> > > +#include <asm/mshyperv.h> > + > /* > * Implement paravirt qspinlocks; the general idea is to halt the vcpus > instead > * of spinning them. > @@ -305,6 +307,10 @@ static void pv_wait_node(struct mcs_spinlock *node, > struct mcs_spinlock *prev) > wait_early = true; > break; > } > +#if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_SPINLOCKS) && > IS_ENABLED(CONFIG_HYPERV) > + if (!hv_notify_long_spin_wait(SPIN_THRESHOLD - loop)) > + break; > +#endif
I don't like that. Why should a KVM or Xen guest call into a hyperv specific function? Can't you move this to existing hyperv specific paravirt hooks? Juergen