All of lore.kernel.org
 help / color / mirror / Atom feed
From: lantianyu1986@gmail.com
To: unlisted-recipients:; (no To-header on input)
Cc: Lan Tianyu <Tianyu.Lan@microsoft.com>,
	kys@microsoft.com, haiyangz@microsoft.com,
	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,
	michael.h.kelley@microsoft.com, vkuznets@redhat.com
Subject: [PATCH V4 12/15] x86/hyper-v: Add HvFlushGuestAddressList hypercall support
Date: Sat, 13 Oct 2018 22:54:03 +0800	[thread overview]
Message-ID: <20181013145406.4911-13-Tianyu.Lan@microsoft.com> (raw)
In-Reply-To: <20181013145406.4911-1-Tianyu.Lan@microsoft.com>

From: Lan Tianyu <Tianyu.Lan@microsoft.com>

Hyper-V provides HvFlushGuestAddressList() hypercall to flush EPT tlb
with specified ranges. This patch is to add the hypercall support.

Reviewed-by:  Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Lan Tianyu <Tianyu.Lan@microsoft.com>
---
Change since v2:
      Fix some coding style issues
        - Move HV_MAX_FLUSH_PAGES and HV_MAX_FLUSH_REP_COUNT to
	hyperv-tlfs.h.
	- Calculate HV_MAX_FLUSH_REP_COUNT in the macro definition
	- Use HV_MAX_FLUSH_REP_COUNT to define length of gpa_list in
	struct hv_guest_mapping_flush_list.

Change since v1:
       Add hyperv tlb flush struct to avoid use kvm tlb flush struct
in the hyperv file.
---
 arch/x86/hyperv/nested.c           | 84 ++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/hyperv-tlfs.h | 32 +++++++++++++++
 arch/x86/include/asm/mshyperv.h    | 16 ++++++++
 3 files changed, 132 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index b8e60cc50461..a6fdfec63c7d 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -7,6 +7,7 @@
  *
  * Author : Lan Tianyu <Tianyu.Lan@microsoft.com>
  */
+#define pr_fmt(fmt)  "Hyper-V: " fmt
 
 
 #include <linux/types.h>
@@ -54,3 +55,86 @@ int hyperv_flush_guest_mapping(u64 as)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
+
+static int fill_flush_list(union hv_gpa_page_range gpa_list[],
+		int offset, u64 start_gfn, u64 pages)
+{
+	int gpa_n = offset;
+	u64 cur = start_gfn;
+	u64 additional_pages;
+
+	do {
+		/*
+		 * If flush requests exceed max flush count, go back to
+		 * flush tlbs without range.
+		 */
+		if (gpa_n >= HV_MAX_FLUSH_REP_COUNT)
+			return -ENOSPC;
+
+		additional_pages = min_t(u64, pages, HV_MAX_FLUSH_PAGES) - 1;
+
+		gpa_list[gpa_n].page.additional_pages = additional_pages;
+		gpa_list[gpa_n].page.largepage = false;
+		gpa_list[gpa_n].page.basepfn = cur;
+
+		pages -= additional_pages + 1;
+		cur += additional_pages + 1;
+		gpa_n++;
+	} while (pages > 0);
+
+	return gpa_n;
+}
+
+int hyperv_flush_guest_mapping_range(u64 as, struct hyperv_tlb_range *range)
+{
+	struct hv_guest_mapping_flush_list **flush_pcpu;
+	struct hv_guest_mapping_flush_list *flush;
+	u64 status = 0;
+	unsigned long flags;
+	int ret = -ENOTSUPP;
+	int gpa_n = 0;
+
+	if (!hv_hypercall_pg)
+		goto fault;
+
+	local_irq_save(flags);
+
+	flush_pcpu = (struct hv_guest_mapping_flush_list **)
+		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;
+
+	if (!range->flush_list)
+		gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
+				range->start_gfn, range->pages);
+	else if (range->parse_flush_list_func)
+		gpa_n = range->parse_flush_list_func(flush->gpa_list, gpa_n,
+				range->flush_list, fill_flush_list);
+	else
+		gpa_n = -1;
+
+	if (gpa_n < 0) {
+		local_irq_restore(flags);
+		goto fault;
+	}
+
+	status = hv_do_rep_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST,
+				     gpa_n, 0, flush, NULL);
+
+	local_irq_restore(flags);
+
+	if (!(status & HV_HYPERCALL_RESULT_MASK))
+		ret = 0;
+	else
+		ret = status;
+fault:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index 00e01d215f74..cf59250c284a 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -10,6 +10,7 @@
 #define _ASM_X86_HYPERV_TLFS_H
 
 #include <linux/types.h>
+#include <asm/page.h>
 
 /*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@@ -353,6 +354,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_POST_MESSAGE			0x005c
 #define HVCALL_SIGNAL_EVENT			0x005d
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE	0x00000001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT	12
@@ -752,6 +754,36 @@ struct hv_guest_mapping_flush {
 	u64 flags;
 };
 
+/*
+ *  HV_MAX_FLUSH_PAGES = "additional_pages" + 1. It's limited
+ *  by the bitwidth of "additional_pages" in union hv_gpa_page_range.
+ */
+#define HV_MAX_FLUSH_PAGES (2048)
+
+/* HvFlushGuestPhysicalAddressList hypercall */
+union hv_gpa_page_range {
+	u64 address_space;
+	struct {
+		u64 additional_pages:11;
+		u64 largepage:1;
+		u64 basepfn:52;
+	} page;
+};
+
+/*
+ * All input flush parameters should be in single page. The max flush
+ * count is equal with how many entries of union hv_gpa_page_range can
+ * be populated into the input parameter page.
+ */
+#define HV_MAX_FLUSH_REP_COUNT (PAGE_SIZE - 2 * sizeof(u64) /	\
+				sizeof(union hv_gpa_page_range))
+
+struct hv_guest_mapping_flush_list {
+	u64 address_space;
+	u64 flags;
+	union hv_gpa_page_range gpa_list[HV_MAX_FLUSH_REP_COUNT];
+};
+
 /* 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 f37704497d8f..19f49fbcf94d 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -22,6 +22,16 @@ struct ms_hyperv_info {
 
 extern struct ms_hyperv_info ms_hyperv;
 
+struct hyperv_tlb_range {
+	u64 start_gfn;
+	u64 pages;
+	struct list_head *flush_list;
+	int (*parse_flush_list_func)(union hv_gpa_page_range gpa_list[],
+		int offset, struct list_head *flush_list,
+		int (*fill_flush_list)(union hv_gpa_page_range gpa_list[],
+		int offset, u64 start_gfn, u64 end_gfn));
+};
+
 /*
  * Generate the guest ID.
  */
@@ -348,6 +358,7 @@ 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);
+int hyperv_flush_guest_mapping_range(u64 as, struct hyperv_tlb_range *range);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -368,6 +379,11 @@ 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; }
+static inline int hyperv_flush_guest_mapping_range(u64 as,
+		struct hyperv_tlb_range *range)
+{
+	return -1;
+}
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.4


  parent reply	other threads:[~2018-10-13 14:55 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-13 14:53 [PATCH V4 00/15] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM lantianyu1986
2018-10-13 14:53 ` lantianyu1986
2018-10-13 14:53 ` lantianyu1986 at gmail.com
2018-10-13 14:53 ` lantianyu1986
2018-10-13 14:53 ` lantianyu1986
2018-10-13 14:53 ` lantianyu1986
2018-10-13 14:53 ` [PATCH V4 1/15] KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986 at gmail.com
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53 ` [PATCH V4 2/15] KVM/MMU: Add tlb flush with range helper function lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986 at gmail.com
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-14  7:26   ` Liran Alon
2018-10-14  7:26     ` Liran Alon
2018-10-14  7:26     ` Liran Alon
2018-10-14  7:26     ` Liran Alon
2018-10-14  7:26     ` Liran Alon
2018-10-14  8:16     ` Thomas Gleixner
2018-10-14  8:16       ` Thomas Gleixner
2018-10-14  8:16       ` Thomas Gleixner
2018-10-14  8:16       ` Thomas Gleixner
2018-10-14  8:16       ` Thomas Gleixner
2018-10-14  9:20       ` Liran Alon
2018-10-14  9:20         ` Liran Alon
2018-10-14  9:20         ` Liran Alon
2018-10-14  9:20         ` Liran Alon
2018-10-14  9:20         ` Liran Alon
2018-10-14 12:57         ` Tianyu Lan
2018-10-14 12:57           ` Tianyu Lan
2018-10-14 12:57           ` Tianyu Lan
2018-10-14 12:57           ` Tianyu Lan
2018-10-14 12:57           ` Tianyu Lan
2018-10-14  9:27       ` Russell King - ARM Linux
2018-10-14  9:27         ` Russell King - ARM Linux
2018-10-14  9:27         ` Russell King - ARM Linux
2018-10-14  9:27         ` Russell King - ARM Linux
2018-10-14  9:27         ` Russell King - ARM Linux
2018-10-14  9:27         ` Russell King - ARM Linux
2018-10-14  9:35         ` Russell King - ARM Linux
2018-10-14  9:35           ` Russell King - ARM Linux
2018-10-14  9:35           ` Russell King - ARM Linux
2018-10-14  9:35           ` Russell King - ARM Linux
2018-10-14 13:21           ` Tianyu Lan
2018-10-14 13:21             ` Tianyu Lan
2018-10-14 13:21             ` Tianyu Lan
2018-10-14 13:21             ` Tianyu Lan
2018-10-14 13:21             ` Tianyu Lan
2018-10-14 13:21             ` Tianyu Lan
2018-10-14 13:33             ` Russell King - ARM Linux
2018-10-14 13:33               ` Russell King - ARM Linux
2018-10-14 13:33               ` Russell King - ARM Linux
2018-10-14 13:33               ` Russell King - ARM Linux
2018-10-14 13:33               ` Russell King - ARM Linux
2018-10-15 12:02       ` Paolo Bonzini
2018-10-15 12:02         ` Paolo Bonzini
2018-10-15 12:02         ` Paolo Bonzini
2018-10-15 12:02         ` Paolo Bonzini
2018-10-13 14:53 ` [PATCH V4 3/15] KVM: Replace old tlb flush function with new one to flush a specified range lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986 at gmail.com
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53 ` [PATCH V4 4/15] KVM: Make kvm_set_spte_hva() return int lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986 at gmail.com
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:53 ` [PATCH V4 5/15] KVM/MMU: Move tlb flush in kvm_set_pte_rmapp() to kvm_mmu_notifier_change_pte() lantianyu1986
2018-10-13 14:53 ` [PATCH V4 6/15] KVM/MMU: Flush tlb directly in the kvm_set_pte_rmapp() lantianyu1986
2018-10-15 11:52   ` Paolo Bonzini
2018-10-13 14:53 ` [PATCH V4 7/15] KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range() lantianyu1986
2018-10-15 10:04   ` Paolo Bonzini
2018-10-15 13:08     ` Tianyu Lan
2018-10-13 14:53 ` [PATCH V4 8/15] KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte() lantianyu1986
2018-10-13 14:53   ` lantianyu1986
2018-10-13 14:54 ` [PATCH V4 9/15] KVM: Add flush_link and parent_pte in the struct kvm_mmu_page lantianyu1986
2018-10-15 10:12   ` Paolo Bonzini
2018-10-15 10:12     ` Paolo Bonzini
2018-10-13 14:54 ` [PATCH V4 10/15] KVM: Add spte's point " lantianyu1986
2018-10-13 14:54 ` [PATCH V4 11/15] KVM/MMU: Replace tlb flush function with range list flush function lantianyu1986
2018-10-15 11:51   ` Paolo Bonzini
2018-10-13 14:54 ` lantianyu1986 [this message]
2018-10-15 10:30   ` [PATCH V4 12/15] x86/hyper-v: Add HvFlushGuestAddressList hypercall support Paolo Bonzini
2018-10-15 10:30     ` Paolo Bonzini
2018-10-13 14:54 ` [PATCH V4 13/15] x86/Hyper-v: Add trace in the hyperv_nested_flush_guest_mapping_range() lantianyu1986
2018-10-13 14:54 ` [PATCH V4 14/15] KVM/VMX: Change hv flush logic when ept tables are mismatched lantianyu1986
2018-10-15 11:15   ` Paolo Bonzini
2018-10-13 14:54 ` [PATCH V4 15/15] KVM/VMX: Add hv tlb range flush support lantianyu1986
2018-10-15 12:04 ` [PATCH V4 00/15] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM Paolo Bonzini
2018-10-15 12:04   ` Paolo Bonzini
2018-10-15 12:04   ` Paolo Bonzini
2018-10-15 12:04   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181013145406.4911-13-Tianyu.Lan@microsoft.com \
    --to=lantianyu1986@gmail.com \
    --cc=Tianyu.Lan@microsoft.com \
    --cc=devel@linuxdriverproject.org \
    --cc=haiyangz@microsoft.com \
    --cc=hpa@zytor.com \
    --cc=kvm@vger.kernel.org \
    --cc=kys@microsoft.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.h.kelley@microsoft.com \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=sthemmin@microsoft.com \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.