Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Hering <ohering@suse.de>2017-10-20 12:20:33 +0200
committerOlaf Hering <ohering@suse.de>2017-10-20 12:23:28 +0200
commit1203ead36cf26d779a21933b4b86135a59558f57 (patch)
tree2b09ec0059d95251c5df83de17cc148164015414
parent7bb20ab011d67336b1aed95f75eba828bc0b0716 (diff)
x86/hyper-v: Support extended CPU ranges for TLB flush
hypercalls (fate#323887).
-rw-r--r--patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch236
-rw-r--r--series.conf1
2 files changed, 237 insertions, 0 deletions
diff --git a/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch b/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch
new file mode 100644
index 0000000000..566f0b11b7
--- /dev/null
+++ b/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch
@@ -0,0 +1,236 @@
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 2 Aug 2017 18:09:20 +0200
+Patch-mainline: v4.14-rc1
+Subject: x86/hyper-v: Support extended CPU ranges for TLB flush hypercalls
+Git-commit: 628f54cc6451d2706ba8a56763dbf93be02aaa80
+References: fate#323887
+
+Hyper-V hosts may support more than 64 vCPUs, we need to use
+HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX/LIST_EX hypercalls in this
+case.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Stephen Hemminger <sthemmin@microsoft.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Haiyang Zhang <haiyangz@microsoft.com>
+Cc: Jork Loeser <Jork.Loeser@microsoft.com>
+Cc: K. Y. Srinivasan <kys@microsoft.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Simon Xiao <sixiao@microsoft.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: devel@linuxdriverproject.org
+Link: http://lkml.kernel.org/r/20170802160921.21791-9-vkuznets@redhat.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Olaf Hering <ohering@suse.de>
+---
+ arch/x86/hyperv/mmu.c | 133 ++++++++++++++++++++++++++++++++++++-
+ arch/x86/include/uapi/asm/hyperv.h | 10 +++
+ 2 files changed, 140 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
+--- a/arch/x86/hyperv/mmu.c
++++ b/arch/x86/hyperv/mmu.c
+@@ -18,11 +18,25 @@ struct hv_flush_pcpu {
+ u64 gva_list[];
+ };
+
++/* HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressListEx hypercalls */
++struct hv_flush_pcpu_ex {
++ u64 address_space;
++ u64 flags;
++ struct {
++ u64 format;
++ u64 valid_bank_mask;
++ u64 bank_contents[];
++ } hv_vp_set;
++ u64 gva_list[];
++};
++
+ /* Each gva in gva_list encodes up to 4096 pages to flush */
+ #define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE)
+
+ static struct hv_flush_pcpu __percpu *pcpu_flush;
+
++static struct hv_flush_pcpu_ex __percpu *pcpu_flush_ex;
++
+ /*
+ * Fills in gva_list starting from offset. Returns the number of items added.
+ */
+@@ -53,6 +67,34 @@ static inline int fill_gva_list(u64 gva_list[], int offset,
+ return gva_n - offset;
+ }
+
++/* Return the number of banks in the resulting vp_set */
++static inline int cpumask_to_vp_set(struct hv_flush_pcpu_ex *flush,
++ const struct cpumask *cpus)
++{
++ int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1;
++
++ /*
++ * Some banks may end up being empty but this is acceptable.
++ */
++ for_each_cpu(cpu, cpus) {
++ vcpu = hv_cpu_number_to_vp_number(cpu);
++ vcpu_bank = vcpu / 64;
++ vcpu_offset = vcpu % 64;
++
++ /* valid_bank_mask can represent up to 64 banks */
++ if (vcpu_bank >= 64)
++ return 0;
++
++ __set_bit(vcpu_offset, (unsigned long *)
++ &flush->hv_vp_set.bank_contents[vcpu_bank]);
++ if (vcpu_bank >= nr_bank)
++ nr_bank = vcpu_bank + 1;
++ }
++ flush->hv_vp_set.valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0);
++
++ return nr_bank;
++}
++
+ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
+ struct mm_struct *mm, unsigned long start, unsigned long end)
+ {
+@@ -122,17 +164,102 @@ do_native:
+ native_flush_tlb_others(cpus, mm, start, end);
+ }
+
++static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
++struct mm_struct *mm, unsigned long start, unsigned long end)
++{
++ int nr_bank = 0, max_gvas, gva_n;
++ struct hv_flush_pcpu_ex *flush;
++ u64 status = U64_MAX;
++ unsigned long flags;
++
++ if (!pcpu_flush_ex || !hv_hypercall_pg)
++ goto do_native;
++
++ if (cpumask_empty(cpus))
++ return;
++
++ local_irq_save(flags);
++
++ flush = this_cpu_ptr(pcpu_flush_ex);
++
++ if (mm) {
++ flush->address_space = virt_to_phys(mm->pgd);
++ flush->flags = 0;
++ } else {
++ flush->address_space = 0;
++ flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES;
++ }
++
++ flush->hv_vp_set.valid_bank_mask = 0;
++
++ if (!cpumask_equal(cpus, cpu_present_mask)) {
++ flush->hv_vp_set.format = HV_GENERIC_SET_SPARCE_4K;
++ nr_bank = cpumask_to_vp_set(flush, cpus);
++ }
++
++ if (!nr_bank) {
++ flush->hv_vp_set.format = HV_GENERIC_SET_ALL;
++ flush->flags |= HV_FLUSH_ALL_PROCESSORS;
++ }
++
++ /*
++ * We can flush not more than max_gvas with one hypercall. Flush the
++ * whole address space if we were asked to do more.
++ */
++ max_gvas =
++ (PAGE_SIZE - sizeof(*flush) - nr_bank *
++ sizeof(flush->hv_vp_set.bank_contents[0])) /
++ sizeof(flush->gva_list[0]);
++
++ if (end == TLB_FLUSH_ALL) {
++ flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY;
++ status = hv_do_rep_hypercall(
++ HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX,
++ 0, nr_bank + 2, flush, NULL);
++ } else if (end &&
++ ((end - start)/HV_TLB_FLUSH_UNIT) > max_gvas) {
++ status = hv_do_rep_hypercall(
++ HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX,
++ 0, nr_bank + 2, flush, NULL);
++ } else {
++ gva_n = fill_gva_list(flush->gva_list, nr_bank,
++ start, end);
++ status = hv_do_rep_hypercall(
++ HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX,
++ gva_n, nr_bank + 2, flush, NULL);
++ }
++
++ local_irq_restore(flags);
++
++ if (!(status & HV_HYPERCALL_RESULT_MASK))
++ return;
++do_native:
++ native_flush_tlb_others(cpus, mm, start, end);
++}
++
+ void hyperv_setup_mmu_ops(void)
+ {
+- if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) {
++ if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))
++ return;
++
++ setup_clear_cpu_cap(X86_FEATURE_PCID);
++
++ if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) {
+ pr_info("Using hypercall for remote TLB flush\n");
+ pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
+- setup_clear_cpu_cap(X86_FEATURE_PCID);
++ } else {
++ pr_info("Using ext hypercall for remote TLB flush\n");
++ pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others_ex;
+ }
+ }
+
+ void hyper_alloc_mmu(void)
+ {
+- if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED)
++ if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))
++ return;
++
++ if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
+ pcpu_flush = __alloc_percpu(PAGE_SIZE, PAGE_SIZE);
++ else
++ pcpu_flush_ex = __alloc_percpu(PAGE_SIZE, PAGE_SIZE);
+ }
+diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
+--- a/arch/x86/include/uapi/asm/hyperv.h
++++ b/arch/x86/include/uapi/asm/hyperv.h
+@@ -149,6 +149,9 @@
+ */
+ #define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
+
++/* Recommend using the newer ExProcessorMasks interface */
++#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11)
++
+ /*
+ * HV_VP_SET available
+ */
+@@ -245,6 +248,8 @@
+ #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002
+ #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003
+ #define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008
++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
+ #define HVCALL_POST_MESSAGE 0x005c
+ #define HVCALL_SIGNAL_EVENT 0x005d
+
+@@ -266,6 +271,11 @@
+ #define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
+ #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
+
++enum HV_GENERIC_SET_FORMAT {
++ HV_GENERIC_SET_SPARCE_4K,
++ HV_GENERIC_SET_ALL,
++};
++
+ /* hypercall status code */
+ #define HV_STATUS_SUCCESS 0
+ #define HV_STATUS_INVALID_HYPERCALL_CODE 2
diff --git a/series.conf b/series.conf
index 2fe1b612ca..ec64bcad91 100644
--- a/series.conf
+++ b/series.conf
@@ -1701,6 +1701,7 @@
patches.suse/msft-hv-1448-hv_netvsc-Add-ethtool-handler-to-set-and-get-UDP-has.patch
patches.suse/msft-hv-1449-hv_netvsc-Fix-rndis_filter_close-error-during-netvsc.patch
patches.suse/msft-hv-1452-scsi-storvsc-fix-memory-leak-on-ring-buffer-busy.patch
+ patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch
patches.suse/suse-hv-guest-os-id.patch
patches.suse/suse-hv-kvp_on_msg.dbg.patch