[azure][PATCH v2 2/3] Revert "UBUNTU: SAUCE: x86/hyper-v: support extended CPU ranges for TLB flush hypercalls"

Marcelo Henrique Cerri marcelo.cerri at canonical.com
Mon Oct 2 14:45:41 UTC 2017


BugLink: http://bugs.launchpad.net/bugs/1719045

This reverts commit 0aa1395238f701fdf2c2e12e49de04b0f2d3a064.

Some golang applications are getting random failures with the linux-azure
kernel. The failures range from some unexpected SIGBUS or SIGSEGV errors to
internal memory allocation failures in the golang runtime.

Bisecting linux-azure shows the problem is caused by the changes that added
support for remote TLB flush via Hyper-V hypercalls. And removing this feature
causes the problem to not happen anymore.

Revert those changes until a proper fix is available.

Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri at canonical.com>
---
 arch/x86/hyperv/mmu.c              | 149 +------------------------------------
 arch/x86/include/uapi/asm/hyperv.h |  10 ---
 2 files changed, 2 insertions(+), 157 deletions(-)

diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
index c9cecb3502e9..e3ab9b984b52 100644
--- a/arch/x86/hyperv/mmu.c
+++ b/arch/x86/hyperv/mmu.c
@@ -15,57 +15,8 @@ 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[];
-};
-
 static struct hv_flush_pcpu __percpu *pcpu_flush;
 
-static struct hv_flush_pcpu_ex __percpu *pcpu_flush_ex;
-
-static inline int cpumask_to_vp_set(struct hv_flush_pcpu_ex *flush,
-				    const struct cpumask *cpus)
-{
-	int cur_bank, cpu, vcpu, nr_bank = 0;
-	bool has_cpus;
-
-	/*
-	 * We can't be sure that translated vcpu numbers will always be
-	 * in ascending order, so iterate over all possible banks and
-	 * check all vcpus in it instead.
-	 */
-	for (cur_bank = 0; cur_bank < ms_hyperv.max_vp_index/64; cur_bank++) {
-		has_cpus = false;
-		for_each_cpu(cpu, cpus) {
-			vcpu = hv_cpu_number_to_vp_number(cpu);
-			if (vcpu/64 != cur_bank)
-				continue;
-			if (!has_cpus) {
-				flush->hv_vp_set.valid_bank_mask |=
-					1 << vcpu / 64;
-				flush->hv_vp_set.bank_contents[nr_bank] =
-					1 << vcpu % 64;
-				has_cpus = true;
-			} else {
-				flush->hv_vp_set.bank_contents[nr_bank] |=
-					1 << vcpu % 64;
-			}
-		}
-		if (has_cpus)
-			nr_bank++;
-	}
-
-	return nr_bank;
-}
-
 static void hyperv_flush_tlb_others(const struct cpumask *cpus,
 				    struct mm_struct *mm, unsigned long start,
 				    unsigned long end)
@@ -151,112 +102,16 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
 	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)
-{
-	struct hv_flush_pcpu_ex *flush;
-	unsigned long cur, flags;
-	u64 status = -1ULL;
-	int nr_bank = 0, max_gvas, gva_n;
-
-	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_ALL;
-		flush->flags |= HV_FLUSH_ALL_PROCESSORS;
-	} else {
-		flush->hv_vp_set.format = HV_GENERIC_SET_SPARCE_4K;
-		nr_bank = cpumask_to_vp_set(flush, cpus);
-	}
-
-	/*
-	 * 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*8) / 8;
-
-	if (end == TLB_FLUSH_ALL ||
-	    (end && ((end - start)/(PAGE_SIZE*PAGE_SIZE)) > max_gvas)) {
-		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 {
-		cur = start;
-		gva_n = nr_bank;
-		do {
-			flush->gva_list[gva_n] = cur & PAGE_MASK;
-			/*
-			 * Lower 12 bits encode the number of additional
-			 * pages to flush (in addition to the 'cur' page).
-			 */
-			if (end >= cur + PAGE_SIZE * PAGE_SIZE)
-				flush->gva_list[gva_n] |= ~PAGE_MASK;
-			else if (end > cur)
-				flush->gva_list[gva_n] |=
-					(end - cur - 1) >> PAGE_SHIFT;
-
-			cur += PAGE_SIZE * PAGE_SIZE;
-			++gva_n;
-
-		} while (cur < 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 & 0xffff))
-		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))
-		return;
-
-	if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) {
+	if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) {
 		pr_info("Hyper-V: Using hypercall for remote TLB flush\n");
 		pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
-	} else {
-		pr_info("Hyper-V: 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))
-		return;
-
-	if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
+	if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_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
index a6b543cc14b6..ecb0470e520b 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -149,9 +149,6 @@
  */
 #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
  */
@@ -248,8 +245,6 @@
 #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
 
@@ -271,11 +266,6 @@
 #define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY	0x00000004
 #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT	0x00000008
 
-enum HV_GENERIC_SET_FORMAT {
-	HV_GENERIC_SET_SPARCE_4K,
-	HV_GENERIC_SET_ALL,
-};
-
 /* Hypercall interface */
 union hv_hypercall_input {
 	u64 as_uint64;
-- 
2.7.4





More information about the kernel-team mailing list