* Re: [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V
2018-10-08 8:29 ` [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V Yi Sun
@ 2018-10-08 9:15 ` Juergen Gross
2018-10-09 9:30 ` [tip:x86/hyperv] x86/hyperv: " tip-bot for Yi Sun
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Juergen Gross @ 2018-10-08 9:15 UTC (permalink / raw)
To: Yi Sun, linux-kernel
Cc: x86, tglx, chao.p.peng, chao.gao, isaku.yamahata,
michael.h.kelley, tianyu.lan, K. Y. Srinivasan, Haiyang Zhang,
Stephen Hemminger
On 08/10/2018 10:29, Yi Sun wrote:
> Follow PV spinlock mechanism to implement the callback functions
> to allow the CPU idling and kicking operations on Hyper-V.
>
> Cc: "K. Y. Srinivasan" <kys@microsoft.com>
> Cc: Haiyang Zhang <haiyangz@microsoft.com>
> Cc: Stephen Hemminger <sthemmin@microsoft.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Michael Kelley (EOSG) <Michael.H.Kelley@microsoft.com>
> Cc: Juergen Gross <jgross@suse.com>
> Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Juergen
^ permalink raw reply [flat|nested] 10+ messages in thread
* [tip:x86/hyperv] x86/hyperv: Enable PV qspinlock for Hyper-V
2018-10-08 8:29 ` [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V Yi Sun
2018-10-08 9:15 ` Juergen Gross
@ 2018-10-09 9:30 ` tip-bot for Yi Sun
2018-10-09 10:54 ` [PATCH v4 2/2] locking/pvqspinlock, hv: " Ingo Molnar
2018-10-09 12:28 ` [tip:x86/paravirt] x86/hyperv: " tip-bot for Yi Sun
3 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Yi Sun @ 2018-10-09 9:30 UTC (permalink / raw)
To: linux-tip-commits
Cc: sthemmin, tglx, yi.y.sun, kys, jgross, mingo, haiyangz,
Michael.H.Kelley, hpa, linux-kernel
Commit-ID: b36bcb7ce0b353bd4889e06b61e036744b02ca51
Gitweb: https://git.kernel.org/tip/b36bcb7ce0b353bd4889e06b61e036744b02ca51
Author: Yi Sun <yi.y.sun@linux.intel.com>
AuthorDate: Mon, 8 Oct 2018 16:29:34 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 9 Oct 2018 11:26:31 +0200
x86/hyperv: Enable PV qspinlock for Hyper-V
Implement the required wait and kick callbacks to support PV spinlocks in
Hyper-V guests.
[ tglx: Document the requirement for disabling interrupts in the wait()
callback. Remove goto and unnecessary includes. Add prototype
for hv_vcpu_is_preempted(). ]
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Juergen Gross <jgross@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Michael Kelley (EOSG) <Michael.H.Kelley@microsoft.com>
Cc: chao.p.peng@intel.com
Cc: chao.gao@intel.com
Cc: isaku.yamahata@intel.com
Cc: tianyu.lan@microsoft.com
Link: https://lkml.kernel.org/r/1538987374-51217-3-git-send-email-yi.y.sun@linux.intel.com
---
Documentation/admin-guide/kernel-parameters.txt | 5 ++
arch/x86/hyperv/Makefile | 4 ++
arch/x86/hyperv/hv_spinlock.c | 88 +++++++++++++++++++++++++
arch/x86/include/asm/mshyperv.h | 2 +
arch/x86/kernel/cpu/mshyperv.c | 14 ++++
5 files changed, 113 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 92eb1f42240d..ca6ca93e8281 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1385,6 +1385,11 @@
hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs.
If specified, z/VM IUCV HVC accepts connections
from listed z/VM user IDs only.
+
+ hv_nopvspin [X86,HYPER_V] Disables the paravirt spinlock optimizations
+ which allow the hypervisor to 'idle' the
+ guest on lock contention.
+
keep_bootcon [KNL]
Do not unregister boot console at start. This is only
useful for debugging when something happens in the window
diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b21ee65c4101..1c11f9420a82 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,6 @@
obj-y := hv_init.o mmu.o nested.o
obj-$(CONFIG_X86_64) += hv_apic.o
+
+ifdef CONFIG_X86_64
+obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o
+endif
diff --git a/arch/x86/hyperv/hv_spinlock.c b/arch/x86/hyperv/hv_spinlock.c
new file mode 100644
index 000000000000..2b6382cbb769
--- /dev/null
+++ b/arch/x86/hyperv/hv_spinlock.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V specific spinlock code.
+ *
+ * Copyright (C) 2018, Intel, Inc.
+ *
+ * Author : Yi Sun <yi.y.sun@intel.com>
+ */
+
+#define pr_fmt(fmt) "Hyper-V: " fmt
+
+#include <linux/spinlock.h>
+
+#include <asm/mshyperv.h>
+#include <asm/paravirt.h>
+#include <asm/apic.h>
+
+static bool __initdata hv_pvspin = true;
+
+static void hv_qlock_kick(int cpu)
+{
+ apic->send_IPI(cpu, X86_PLATFORM_IPI_VECTOR);
+}
+
+static void hv_qlock_wait(u8 *byte, u8 val)
+{
+ unsigned long msr_val;
+ unsigned long flags;
+
+ if (in_nmi())
+ return;
+
+ /*
+ * Reading HV_X64_MSR_GUEST_IDLE MSR tells the hypervisor that the
+ * vCPU can be put into 'idle' state. This 'idle' state is
+ * terminated by an IPI, usually from hv_qlock_kick(), even if
+ * interrupts are disabled on the vCPU.
+ *
+ * To prevent a race against the unlock path it is required to
+ * disable interrupts before accessing the HV_X64_MSR_GUEST_IDLE
+ * MSR. Otherwise, if the IPI from hv_qlock_kick() arrives between
+ * the lock value check and the rdmsrl() then the vCPU might be put
+ * into 'idle' state by the hypervisor and kept in that state for
+ * an unspecified amount of time.
+ */
+ local_irq_save(flags);
+ /*
+ * Only issue the rdmsrl() when the lock state has not changed.
+ */
+ if (READ_ONCE(*byte) == val)
+ rdmsrl(HV_X64_MSR_GUEST_IDLE, msr_val);
+ local_irq_restore(flags);
+}
+
+/*
+ * Hyper-V does not support this so far.
+ */
+bool hv_vcpu_is_preempted(int vcpu)
+{
+ return false;
+}
+PV_CALLEE_SAVE_REGS_THUNK(hv_vcpu_is_preempted);
+
+void __init hv_init_spinlocks(void)
+{
+ if (!hv_pvspin || !apic ||
+ !(ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) ||
+ !(ms_hyperv.features & HV_X64_MSR_GUEST_IDLE_AVAILABLE)) {
+ pr_info("PV spinlocks disabled\n");
+ return;
+ }
+ pr_info("PV spinlocks enabled\n");
+
+ __pv_init_lock_hash();
+ pv_lock_ops.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath;
+ pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
+ pv_lock_ops.wait = hv_qlock_wait;
+ pv_lock_ops.kick = hv_qlock_kick;
+ pv_lock_ops.vcpu_is_preempted = PV_CALLEE_SAVE(hv_vcpu_is_preempted);
+}
+
+static __init int hv_parse_nopvspin(char *arg)
+{
+ hv_pvspin = false;
+ return 0;
+}
+early_param("hv_nopvspin", hv_parse_nopvspin);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index f37704497d8f..0d6271cce198 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -351,6 +351,8 @@ int hyperv_flush_guest_mapping(u64 as);
#ifdef CONFIG_X86_64
void hv_apic_init(void);
+void __init hv_init_spinlocks(void);
+bool hv_vcpu_is_preempted(int vcpu);
#else
static inline void hv_apic_init(void) {}
#endif
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index ad12733f6058..2179c7efc1f4 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -199,6 +199,16 @@ static unsigned long hv_get_tsc_khz(void)
return freq / 1000;
}
+#if defined(CONFIG_SMP) && IS_ENABLED(CONFIG_HYPERV)
+static void __init hv_smp_prepare_boot_cpu(void)
+{
+ native_smp_prepare_boot_cpu();
+#if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_SPINLOCKS)
+ hv_init_spinlocks();
+#endif
+}
+#endif
+
static void __init ms_hyperv_init_platform(void)
{
int hv_host_info_eax;
@@ -303,6 +313,10 @@ static void __init ms_hyperv_init_platform(void)
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
alloc_intr_gate(HYPERV_STIMER0_VECTOR,
hv_stimer0_callback_vector);
+
+# if defined(CONFIG_SMP)
+ smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
+# endif
#endif
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V
2018-10-08 8:29 ` [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V Yi Sun
2018-10-08 9:15 ` Juergen Gross
2018-10-09 9:30 ` [tip:x86/hyperv] x86/hyperv: " tip-bot for Yi Sun
@ 2018-10-09 10:54 ` Ingo Molnar
2018-10-10 2:25 ` Yi Sun
2018-10-09 12:28 ` [tip:x86/paravirt] x86/hyperv: " tip-bot for Yi Sun
3 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2018-10-09 10:54 UTC (permalink / raw)
To: Yi Sun
Cc: linux-kernel, x86, tglx, jgross, chao.p.peng, chao.gao,
isaku.yamahata, michael.h.kelley, tianyu.lan, K. Y. Srinivasan,
Haiyang Zhang, Stephen Hemminger
* Yi Sun <yi.y.sun@linux.intel.com> wrote:
> Follow PV spinlock mechanism to implement the callback functions
> to allow the CPU idling and kicking operations on Hyper-V.
> +#if defined(CONFIG_SMP)
> + smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
> +#endif
What's wrong with using the common pattern of:
#ifdef CONFIG_SMP
?
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V
2018-10-09 10:54 ` [PATCH v4 2/2] locking/pvqspinlock, hv: " Ingo Molnar
@ 2018-10-10 2:25 ` Yi Sun
2018-10-10 5:50 ` Ingo Molnar
0 siblings, 1 reply; 10+ messages in thread
From: Yi Sun @ 2018-10-10 2:25 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, x86, tglx, jgross, chao.p.peng, chao.gao,
isaku.yamahata, michael.h.kelley, tianyu.lan, K. Y. Srinivasan,
Haiyang Zhang, Stephen Hemminger
On 18-10-09 12:54:27, Ingo Molnar wrote:
>
> * Yi Sun <yi.y.sun@linux.intel.com> wrote:
>
> > Follow PV spinlock mechanism to implement the callback functions
> > to allow the CPU idling and kicking operations on Hyper-V.
>
> > +#if defined(CONFIG_SMP)
> > + smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
> > +#endif
>
> What's wrong with using the common pattern of:
>
> #ifdef CONFIG_SMP
>
> ?
There is no difference between "#ifdef" and "#if defined". I just copied
it from "hv_smp_prepare_boot_cpu()". Do you need me submit a fix patch
after this set is merged?
>
> Thanks,
>
> Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V
2018-10-10 2:25 ` Yi Sun
@ 2018-10-10 5:50 ` Ingo Molnar
2018-10-10 8:02 ` Yi Sun
0 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2018-10-10 5:50 UTC (permalink / raw)
To: Yi Sun
Cc: linux-kernel, x86, tglx, jgross, chao.p.peng, chao.gao,
isaku.yamahata, michael.h.kelley, tianyu.lan, K. Y. Srinivasan,
Haiyang Zhang, Stephen Hemminger
* Yi Sun <yi.y.sun@linux.intel.com> wrote:
> On 18-10-09 12:54:27, Ingo Molnar wrote:
> >
> > * Yi Sun <yi.y.sun@linux.intel.com> wrote:
> >
> > > Follow PV spinlock mechanism to implement the callback functions
> > > to allow the CPU idling and kicking operations on Hyper-V.
> >
> > > +#if defined(CONFIG_SMP)
> > > + smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
> > > +#endif
> >
> > What's wrong with using the common pattern of:
> >
> > #ifdef CONFIG_SMP
> >
> > ?
>
> There is no difference between "#ifdef" and "#if defined". I just copied
> it from "hv_smp_prepare_boot_cpu()". Do you need me submit a fix patch
> after this set is merged?
It's equivalent code, my point was that '#ifdef CONFIG_XYZ' is the shorter, more canonical
pattern we use in the kernel most of the time, it's shorter, easier to read. We only use
defined() for longer preprocessor directive conditions, and it's a pattern for "there's
something more complex here than a simple CONFIG_XYZ dependency".
Anyway, Thomas fixed it up in the latest iteration.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V
2018-10-10 5:50 ` Ingo Molnar
@ 2018-10-10 8:02 ` Yi Sun
0 siblings, 0 replies; 10+ messages in thread
From: Yi Sun @ 2018-10-10 8:02 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, x86, tglx, jgross, chao.p.peng, chao.gao,
isaku.yamahata, michael.h.kelley, tianyu.lan, K. Y. Srinivasan,
Haiyang Zhang, Stephen Hemminger
On 18-10-10 07:50:26, Ingo Molnar wrote:
>
> * Yi Sun <yi.y.sun@linux.intel.com> wrote:
>
> > On 18-10-09 12:54:27, Ingo Molnar wrote:
> > >
> > > * Yi Sun <yi.y.sun@linux.intel.com> wrote:
> > >
> > > > Follow PV spinlock mechanism to implement the callback functions
> > > > to allow the CPU idling and kicking operations on Hyper-V.
> > >
> > > > +#if defined(CONFIG_SMP)
> > > > + smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
> > > > +#endif
> > >
> > > What's wrong with using the common pattern of:
> > >
> > > #ifdef CONFIG_SMP
> > >
> > > ?
> >
> > There is no difference between "#ifdef" and "#if defined". I just copied
> > it from "hv_smp_prepare_boot_cpu()". Do you need me submit a fix patch
> > after this set is merged?
>
> It's equivalent code, my point was that '#ifdef CONFIG_XYZ' is the shorter, more canonical
> pattern we use in the kernel most of the time, it's shorter, easier to read. We only use
> defined() for longer preprocessor directive conditions, and it's a pattern for "there's
> something more complex here than a simple CONFIG_XYZ dependency".
>
> Anyway, Thomas fixed it up in the latest iteration.
>
> Thanks,
>
> Ingo
Thank you! I will notice it in the future.
BRs,
Yi Sun
^ permalink raw reply [flat|nested] 10+ messages in thread
* [tip:x86/paravirt] x86/hyperv: Enable PV qspinlock for Hyper-V
2018-10-08 8:29 ` [PATCH v4 2/2] locking/pvqspinlock, hv: Enable PV qspinlock for Hyper-V Yi Sun
` (2 preceding siblings ...)
2018-10-09 10:54 ` [PATCH v4 2/2] locking/pvqspinlock, hv: " Ingo Molnar
@ 2018-10-09 12:28 ` tip-bot for Yi Sun
3 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Yi Sun @ 2018-10-09 12:28 UTC (permalink / raw)
To: linux-tip-commits
Cc: kys, yi.y.sun, sthemmin, linux-kernel, haiyangz,
Michael.H.Kelley, mingo, jgross, hpa, tglx
Commit-ID: 3a025de64bf89c84a79909069e3c24ad9e710d27
Gitweb: https://git.kernel.org/tip/3a025de64bf89c84a79909069e3c24ad9e710d27
Author: Yi Sun <yi.y.sun@linux.intel.com>
AuthorDate: Mon, 8 Oct 2018 16:29:34 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 9 Oct 2018 14:21:39 +0200
x86/hyperv: Enable PV qspinlock for Hyper-V
Implement the required wait and kick callbacks to support PV spinlocks in
Hyper-V guests.
[ tglx: Document the requirement for disabling interrupts in the wait()
callback. Remove goto and unnecessary includes. Add prototype
for hv_vcpu_is_preempted(). Adapted to pending paravirt changes. ]
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Juergen Gross <jgross@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Michael Kelley (EOSG) <Michael.H.Kelley@microsoft.com>
Cc: chao.p.peng@intel.com
Cc: chao.gao@intel.com
Cc: isaku.yamahata@intel.com
Cc: tianyu.lan@microsoft.com
Link: https://lkml.kernel.org/r/1538987374-51217-3-git-send-email-yi.y.sun@linux.intel.com
---
Documentation/admin-guide/kernel-parameters.txt | 5 ++
arch/x86/hyperv/Makefile | 4 ++
arch/x86/hyperv/hv_spinlock.c | 88 +++++++++++++++++++++++++
arch/x86/include/asm/mshyperv.h | 2 +
arch/x86/kernel/cpu/mshyperv.c | 14 ++++
5 files changed, 113 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 9871e649ffef..4cdf6a673592 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1385,6 +1385,11 @@
hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs.
If specified, z/VM IUCV HVC accepts connections
from listed z/VM user IDs only.
+
+ hv_nopvspin [X86,HYPER_V] Disables the paravirt spinlock optimizations
+ which allow the hypervisor to 'idle' the
+ guest on lock contention.
+
keep_bootcon [KNL]
Do not unregister boot console at start. This is only
useful for debugging when something happens in the window
diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b21ee65c4101..1c11f9420a82 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,6 @@
obj-y := hv_init.o mmu.o nested.o
obj-$(CONFIG_X86_64) += hv_apic.o
+
+ifdef CONFIG_X86_64
+obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o
+endif
diff --git a/arch/x86/hyperv/hv_spinlock.c b/arch/x86/hyperv/hv_spinlock.c
new file mode 100644
index 000000000000..a861b0456b1a
--- /dev/null
+++ b/arch/x86/hyperv/hv_spinlock.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V specific spinlock code.
+ *
+ * Copyright (C) 2018, Intel, Inc.
+ *
+ * Author : Yi Sun <yi.y.sun@intel.com>
+ */
+
+#define pr_fmt(fmt) "Hyper-V: " fmt
+
+#include <linux/spinlock.h>
+
+#include <asm/mshyperv.h>
+#include <asm/paravirt.h>
+#include <asm/apic.h>
+
+static bool __initdata hv_pvspin = true;
+
+static void hv_qlock_kick(int cpu)
+{
+ apic->send_IPI(cpu, X86_PLATFORM_IPI_VECTOR);
+}
+
+static void hv_qlock_wait(u8 *byte, u8 val)
+{
+ unsigned long msr_val;
+ unsigned long flags;
+
+ if (in_nmi())
+ return;
+
+ /*
+ * Reading HV_X64_MSR_GUEST_IDLE MSR tells the hypervisor that the
+ * vCPU can be put into 'idle' state. This 'idle' state is
+ * terminated by an IPI, usually from hv_qlock_kick(), even if
+ * interrupts are disabled on the vCPU.
+ *
+ * To prevent a race against the unlock path it is required to
+ * disable interrupts before accessing the HV_X64_MSR_GUEST_IDLE
+ * MSR. Otherwise, if the IPI from hv_qlock_kick() arrives between
+ * the lock value check and the rdmsrl() then the vCPU might be put
+ * into 'idle' state by the hypervisor and kept in that state for
+ * an unspecified amount of time.
+ */
+ local_irq_save(flags);
+ /*
+ * Only issue the rdmsrl() when the lock state has not changed.
+ */
+ if (READ_ONCE(*byte) == val)
+ rdmsrl(HV_X64_MSR_GUEST_IDLE, msr_val);
+ local_irq_restore(flags);
+}
+
+/*
+ * Hyper-V does not support this so far.
+ */
+bool hv_vcpu_is_preempted(int vcpu)
+{
+ return false;
+}
+PV_CALLEE_SAVE_REGS_THUNK(hv_vcpu_is_preempted);
+
+void __init hv_init_spinlocks(void)
+{
+ if (!hv_pvspin || !apic ||
+ !(ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) ||
+ !(ms_hyperv.features & HV_X64_MSR_GUEST_IDLE_AVAILABLE)) {
+ pr_info("PV spinlocks disabled\n");
+ return;
+ }
+ pr_info("PV spinlocks enabled\n");
+
+ __pv_init_lock_hash();
+ pv_ops.lock.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath;
+ pv_ops.lock.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
+ pv_ops.lock.wait = hv_qlock_wait;
+ pv_ops.lock.kick = hv_qlock_kick;
+ pv_ops.lock.vcpu_is_preempted = PV_CALLEE_SAVE(hv_vcpu_is_preempted);
+}
+
+static __init int hv_parse_nopvspin(char *arg)
+{
+ hv_pvspin = false;
+ return 0;
+}
+early_param("hv_nopvspin", hv_parse_nopvspin);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index f37704497d8f..0d6271cce198 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -351,6 +351,8 @@ int hyperv_flush_guest_mapping(u64 as);
#ifdef CONFIG_X86_64
void hv_apic_init(void);
+void __init hv_init_spinlocks(void);
+bool hv_vcpu_is_preempted(int vcpu);
#else
static inline void hv_apic_init(void) {}
#endif
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index ad12733f6058..1c72f3819eb1 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -199,6 +199,16 @@ static unsigned long hv_get_tsc_khz(void)
return freq / 1000;
}
+#if defined(CONFIG_SMP) && IS_ENABLED(CONFIG_HYPERV)
+static void __init hv_smp_prepare_boot_cpu(void)
+{
+ native_smp_prepare_boot_cpu();
+#if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_SPINLOCKS)
+ hv_init_spinlocks();
+#endif
+}
+#endif
+
static void __init ms_hyperv_init_platform(void)
{
int hv_host_info_eax;
@@ -303,6 +313,10 @@ static void __init ms_hyperv_init_platform(void)
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
alloc_intr_gate(HYPERV_STIMER0_VECTOR,
hv_stimer0_callback_vector);
+
+# ifdef CONFIG_SMP
+ smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
+# endif
#endif
}
^ permalink raw reply related [flat|nested] 10+ messages in thread