diff mbox

[RFC,1/3] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

Message ID 20180604090749.489-2-Tianyu.Lan@microsoft.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tianyu Lan June 4, 2018, 9:08 a.m. UTC
Hyper-V provides a pv hypercall HvFlushGuestPhysicalAddressSpace to flush
nested VM address space mapping in l1 hypervisor and it's to reduce overhead
of flushing ept tlb among vcpus. This patch is to implement it.

Signed-off-by: Lan Tianyu <Tianyu.Lan@microsoft.com>
---
 arch/x86/hyperv/Makefile           |  2 +-
 arch/x86/hyperv/nested.c           | 64 ++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +++++
 arch/x86/include/asm/mshyperv.h    |  2 ++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

Comments

Michael Kelley (EOSG) June 5, 2018, 4:59 p.m. UTC | #1
> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org <linux-kernel-owner@vger.kernel.org> On Behalf
> Of Tianyu Lan
> Sent: Monday, June 4, 2018 2:08 AM
> Cc: Tianyu Lan <Tianyu.Lan@microsoft.com>; KY Srinivasan <kys@microsoft.com>; Haiyang
> Zhang <haiyangz@microsoft.com>; Stephen Hemminger <sthemmin@microsoft.com>;
> tglx@linutronix.de; mingo@redhat.com; hpa@zytor.com; x86@kernel.org;
> pbonzini@redhat.com; rkrcmar@redhat.com; devel@linuxdriverproject.org; linux-
> kernel@vger.kernel.org; kvm@vger.kernel.org; vkuznets@redhat.com
> Subject: [RFC Patch 1/3] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
> support
> 
> Hyper-V provides a pv hypercall HvFlushGuestPhysicalAddressSpace to flush
> nested VM address space mapping in l1 hypervisor and it's to reduce overhead
> of flushing ept tlb among vcpus. This patch is to implement it.
> 
> Signed-off-by: Lan Tianyu <Tianyu.Lan@microsoft.com>
> ---
> diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
> new file mode 100644
> index 000000000000..17f7c288eccc
> --- /dev/null
> +++ b/arch/x86/hyperv/nested.c
> +#include <linux/types.h>
> +#include <asm/hyperv-tlfs.h>
> +#include <asm/mshyperv.h>
> +#include <asm/tlbflush.h>
> +
> +int hyperv_flush_guest_mapping(u64 as)
> +{
> +	struct hv_guest_mapping_flush **flush_pcpu;
> +	struct hv_guest_mapping_flush *flush;
> +	u64 status = U64_MAX;

Initializing status to U64_MAX doesn't seem necessary.

> +	unsigned long flags;
> +	int ret = -EFAULT;
> +
> +	if (!hv_hypercall_pg)
> +		goto fault;
> +
> +	local_irq_save(flags);
> +
> +	flush_pcpu = (struct hv_guest_mapping_flush **)
> +		this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> +	flush = *flush_pcpu;
> +
> +	if (unlikely(!flush)) {
> +		local_irq_restore(flags);
> +		goto fault;
> +	}
> +
> +	flush->address_space = as;
> +	flush->flags = 0;
> +
> +	status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
> +				 flush, NULL);
> +	local_irq_restore(flags);
> +
> +	if (!(status & HV_HYPERCALL_RESULT_MASK))
> +		ret = 0;
> +
> +fault:
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
> diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
> index b8c89265baf0..53bbeb08faea 100644
> --- a/arch/x86/include/asm/hyperv-tlfs.h
> +++ b/arch/x86/include/asm/hyperv-tlfs.h
> @@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
>  #define HV_X64_MSR_REENLIGHTENMENT_CONTROL	0x40000106
> 
>  /* Nested features (CPUID 0x4000000A) EAX */
> +#define HV_X64_NESTED_GUSET_MAPPING_FLUSH	BIT(18)

The #define name is misspelled.  "_GUSET_" should be "_GUEST_".
And the matching usage in patch 3/3 will need to be updated as well.

Michael
Tianyu Lan June 6, 2018, 5:36 a.m. UTC | #2
Hi Michael:
	Thanks for your review.

On 6/6/2018 12:59 AM, Michael Kelley (EOSG) wrote:
>> -----Original Message-----

>> From: linux-kernel-owner@vger.kernel.org <linux-kernel-owner@vger.kernel.org> On Behalf

>> Of Tianyu Lan

>> Sent: Monday, June 4, 2018 2:08 AM

>> Cc: Tianyu Lan <Tianyu.Lan@microsoft.com>; KY Srinivasan <kys@microsoft.com>; Haiyang

>> Zhang <haiyangz@microsoft.com>; Stephen Hemminger <sthemmin@microsoft.com>;

>> tglx@linutronix.de; mingo@redhat.com; hpa@zytor.com; x86@kernel.org;

>> pbonzini@redhat.com; rkrcmar@redhat.com; devel@linuxdriverproject.org; linux-

>> kernel@vger.kernel.org; kvm@vger.kernel.org; vkuznets@redhat.com

>> Subject: [RFC Patch 1/3] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall

>> support

>>

>> Hyper-V provides a pv hypercall HvFlushGuestPhysicalAddressSpace to flush

>> nested VM address space mapping in l1 hypervisor and it's to reduce overhead

>> of flushing ept tlb among vcpus. This patch is to implement it.

>>

>> Signed-off-by: Lan Tianyu <Tianyu.Lan@microsoft.com>

>> ---

>> diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c

>> new file mode 100644

>> index 000000000000..17f7c288eccc

>> --- /dev/null

>> +++ b/arch/x86/hyperv/nested.c

>> +#include <linux/types.h>

>> +#include <asm/hyperv-tlfs.h>

>> +#include <asm/mshyperv.h>

>> +#include <asm/tlbflush.h>

>> +

>> +int hyperv_flush_guest_mapping(u64 as)

>> +{

>> +	struct hv_guest_mapping_flush **flush_pcpu;

>> +	struct hv_guest_mapping_flush *flush;

>> +	u64 status = U64_MAX;

> 

> Initializing status to U64_MAX doesn't seem necessary.

> 

>> +	unsigned long flags;

>> +	int ret = -EFAULT;

>> +

>> +	if (!hv_hypercall_pg)

>> +		goto fault;

>> +

>> +	local_irq_save(flags);

>> +

>> +	flush_pcpu = (struct hv_guest_mapping_flush **)

>> +		this_cpu_ptr(hyperv_pcpu_input_arg);

>> +

>> +	flush = *flush_pcpu;

>> +

>> +	if (unlikely(!flush)) {

>> +		local_irq_restore(flags);

>> +		goto fault;

>> +	}

>> +

>> +	flush->address_space = as;

>> +	flush->flags = 0;

>> +

>> +	status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,

>> +				 flush, NULL);

>> +	local_irq_restore(flags);

>> +

>> +	if (!(status & HV_HYPERCALL_RESULT_MASK))

>> +		ret = 0;

>> +

>> +fault:

>> +	return ret;

>> +}

>> +EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);

>> diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h

>> index b8c89265baf0..53bbeb08faea 100644

>> --- a/arch/x86/include/asm/hyperv-tlfs.h

>> +++ b/arch/x86/include/asm/hyperv-tlfs.h

>> @@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {

>>   #define HV_X64_MSR_REENLIGHTENMENT_CONTROL	0x40000106

>>

>>   /* Nested features (CPUID 0x4000000A) EAX */

>> +#define HV_X64_NESTED_GUSET_MAPPING_FLUSH	BIT(18)

> 

> The #define name is misspelled.  "_GUSET_" should be "_GUEST_".

> And the matching usage in patch 3/3 will need to be updated as well.

> 

> Michael

> 


Nice catch! Will update.
diff mbox

Patch

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@ 
-obj-y			:= hv_init.o mmu.o
+obj-y			:= hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)	+= hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index 000000000000..17f7c288eccc
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,64 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu <Tianyu.Lan@microsoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include <linux/types.h>
+#include <asm/hyperv-tlfs.h>
+#include <asm/mshyperv.h>
+#include <asm/tlbflush.h>
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+	struct hv_guest_mapping_flush **flush_pcpu;
+	struct hv_guest_mapping_flush *flush;
+	u64 status = U64_MAX;
+	unsigned long flags;
+	int ret = -EFAULT;
+
+	if (!hv_hypercall_pg)
+		goto fault;
+
+	local_irq_save(flags);
+
+	flush_pcpu = (struct hv_guest_mapping_flush **)
+		this_cpu_ptr(hyperv_pcpu_input_arg);
+
+	flush = *flush_pcpu;
+
+	if (unlikely(!flush)) {
+		local_irq_restore(flags);
+		goto fault;
+	}
+
+	flush->address_space = as;
+	flush->flags = 0;
+
+	status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+				 flush, NULL);
+	local_irq_restore(flags);
+
+	if (!(status & HV_HYPERCALL_RESULT_MASK))
+		ret = 0;
+
+fault:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..53bbeb08faea 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@  struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL	0x40000106
 
 /* Nested features (CPUID 0x4000000A) EAX */
+#define HV_X64_NESTED_GUSET_MAPPING_FLUSH	BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP		BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@  struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX			0x0015
 #define HVCALL_POST_MESSAGE			0x005c
 #define HVCALL_SIGNAL_EVENT			0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE	0x00000001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT	12
@@ -741,6 +743,12 @@  struct ipi_arg_ex {
 	struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+	u64 address_space;
+	u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
 	u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@  void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@  static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
 {
 	return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE