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:27 +0200
commit4230a65da056c84c9fd77ff597bede650b606ea1 (patch)
treeb5b9edcd79ce622497ec6c2b742bb1daf4c29161
parente7782862358fdcee521667e16e805f264606d702 (diff)
hyper-v: Globalize vp_index (fate#323887).
-rw-r--r--patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch366
-rw-r--r--series.conf1
2 files changed, 367 insertions, 0 deletions
diff --git a/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch b/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch
new file mode 100644
index 0000000000..f9e902cdce
--- /dev/null
+++ b/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch
@@ -0,0 +1,366 @@
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 2 Aug 2017 18:09:18 +0200
+Patch-mainline: v4.14-rc1
+Subject: hyper-v: Globalize vp_index
+Git-commit: 7415aea6072bab15969b6c3c5b2a193d88095326
+References: fate#323887
+
+To support implementing remote TLB flushing on Hyper-V with a hypercall
+we need to make vp_index available outside of vmbus module. Rename and
+globalize.
+
+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-7-vkuznets@redhat.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Olaf Hering <ohering@suse.de>
+---
+ arch/x86/hyperv/hv_init.c | 34 +++++++++++++++++++++++++-
+ arch/x86/include/asm/mshyperv.h | 24 ++++++++++++++++++
+ drivers/hv/channel_mgmt.c | 7 +++---
+ drivers/hv/connection.c | 3 ++-
+ drivers/hv/hv.c | 9 -------
+ drivers/hv/hyperv_vmbus.h | 11 ---------
+ drivers/hv/vmbus_drv.c | 17 -------------
+ drivers/pci/host/pci-hyperv.c | 54 +++--------------------------------------
+ include/linux/hyperv.h | 1 -
+ 9 files changed, 65 insertions(+), 95 deletions(-)
+
+diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
+--- a/arch/x86/hyperv/hv_init.c
++++ b/arch/x86/hyperv/hv_init.c
+@@ -26,6 +26,8 @@
+ #include <linux/mm.h>
+ #include <linux/clockchips.h>
+ #include <linux/hyperv.h>
++#include <linux/slab.h>
++#include <linux/cpuhotplug.h>
+
+ #ifdef CONFIG_HYPERV_TSCPAGE
+
+@@ -80,6 +82,20 @@ EXPORT_SYMBOL_GPL(hv_hypercall_pg);
+ struct clocksource *hyperv_cs;
+ EXPORT_SYMBOL_GPL(hyperv_cs);
+
++u32 *hv_vp_index;
++EXPORT_SYMBOL_GPL(hv_vp_index);
++
++static int hv_cpu_init(unsigned int cpu)
++{
++ u64 msr_vp_index;
++
++ hv_get_vp_index(msr_vp_index);
++
++ hv_vp_index[smp_processor_id()] = msr_vp_index;
++
++ return 0;
++}
++
+ /*
+ * This function is to be invoked early in the boot sequence after the
+ * hypervisor has been detected.
+@@ -95,6 +111,16 @@ void hyperv_init(void)
+ if (x86_hyper != &x86_hyper_ms_hyperv)
+ return;
+
++ /* Allocate percpu VP index */
++ hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
++ GFP_KERNEL);
++ if (!hv_vp_index)
++ return;
++
++ if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
++ hv_cpu_init, NULL) < 0)
++ goto free_vp_index;
++
+ /*
+ * Setup the hypercall page and enable hypercalls.
+ * 1. Register the guest ID
+@@ -106,7 +132,7 @@ void hyperv_init(void)
+ hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
+ if (hv_hypercall_pg == NULL) {
+ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
+- return;
++ goto free_vp_index;
+ }
+
+ rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+@@ -149,6 +175,12 @@ register_msr_cs:
+ hyperv_cs = &hyperv_cs_msr;
+ if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
+ clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
++
++ return;
++
++free_vp_index:
++ kfree(hv_vp_index);
++ hv_vp_index = NULL;
+ }
+
+ /*
+diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
+--- a/arch/x86/include/asm/mshyperv.h
++++ b/arch/x86/include/asm/mshyperv.h
+@@ -282,6 +282,30 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size,
+ return status;
+ }
+
++/*
++ * Hypervisor's notion of virtual processor ID is different from
++ * Linux' notion of CPU ID. This information can only be retrieved
++ * in the context of the calling CPU. Setup a map for easy access
++ * to this information.
++ */
++extern u32 *hv_vp_index;
++
++/**
++ * hv_cpu_number_to_vp_number() - Map CPU to VP.
++ * @cpu_number: CPU number in Linux terms
++ *
++ * This function returns the mapping between the Linux processor
++ * number and the hypervisor's virtual processor number, useful
++ * in making hypercalls and such that talk about specific
++ * processors.
++ *
++ * Return: Virtual processor number in Hyper-V terms
++ */
++static inline int hv_cpu_number_to_vp_number(int cpu_number)
++{
++ return hv_vp_index[cpu_number];
++}
++
+ void hyperv_init(void);
+ void hyperv_report_panic(struct pt_regs *regs);
+ bool hv_is_hypercall_page_setup(void);
+diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -599,7 +599,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
+ */
+ channel->numa_node = 0;
+ channel->target_cpu = 0;
+- channel->target_vp = hv_context.vp_index[0];
++ channel->target_vp = hv_cpu_number_to_vp_number(0);
+ return;
+ }
+
+@@ -683,7 +683,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
+ }
+
+ channel->target_cpu = cur_cpu;
+- channel->target_vp = hv_context.vp_index[cur_cpu];
++ channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu);
+ }
+
+ static void vmbus_wait_for_unload(void)
+@@ -1219,8 +1219,7 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
+ return outgoing_channel;
+ }
+
+- cur_cpu = hv_context.vp_index[get_cpu()];
+- put_cpu();
++ cur_cpu = hv_cpu_number_to_vp_number(smp_processor_id());
+ list_for_each_safe(cur, tmp, &primary->sc_list) {
+ cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
+ if (cur_channel->state != CHANNEL_OPENED_STATE)
+diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
+--- a/drivers/hv/connection.c
++++ b/drivers/hv/connection.c
+@@ -96,7 +96,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
+ * the CPU attempting to connect may not be CPU 0.
+ */
+ if (version >= VERSION_WIN8_1) {
+- msg->target_vcpu = hv_context.vp_index[smp_processor_id()];
++ msg->target_vcpu =
++ hv_cpu_number_to_vp_number(smp_processor_id());
+ vmbus_connection.connect_cpu = smp_processor_id();
+ } else {
+ msg->target_vcpu = 0;
+diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
+--- a/drivers/hv/hv.c
++++ b/drivers/hv/hv.c
+@@ -234,7 +234,6 @@ int hv_synic_init(unsigned int cpu)
+ union hv_synic_siefp siefp;
+ union hv_synic_sint shared_sint;
+ union hv_synic_scontrol sctrl;
+- u64 vp_index;
+
+ /* Setup the Synic's message page */
+ hv_get_simp(simp.as_uint64);
+@@ -275,14 +274,6 @@ int hv_synic_init(unsigned int cpu)
+
+ hv_context.synic_initialized = true;
+
+- /*
+- * Setup the mapping between Hyper-V's notion
+- * of cpuid and Linux' notion of cpuid.
+- * This array will be indexed using Linux cpuid.
+- */
+- hv_get_vp_index(vp_index);
+- hv_context.vp_index[cpu] = (u32)vp_index;
+-
+ /*
+ * Register the per-cpu clockevent source.
+ */
+diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
+--- a/drivers/hv/hyperv_vmbus.h
++++ b/drivers/hv/hyperv_vmbus.h
+@@ -228,17 +228,6 @@ struct hv_context {
+
+ struct hv_per_cpu_context __percpu *cpu_context;
+
+- /*
+- * Hypervisor's notion of virtual processor ID is different from
+- * Linux' notion of CPU ID. This information can only be retrieved
+- * in the context of the calling CPU. Setup a map for easy access
+- * to this information:
+- *
+- * vp_index[a] is the Hyper-V's processor ID corresponding to
+- * Linux cpuid 'a'.
+- */
+- u32 vp_index[NR_CPUS];
+-
+ /*
+ * To manage allocations in a NUMA node.
+ * Array indexed by numa node ID.
+diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -1451,23 +1451,6 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size)
+ }
+ EXPORT_SYMBOL_GPL(vmbus_free_mmio);
+
+-/**
+- * vmbus_cpu_number_to_vp_number() - Map CPU to VP.
+- * @cpu_number: CPU number in Linux terms
+- *
+- * This function returns the mapping between the Linux processor
+- * number and the hypervisor's virtual processor number, useful
+- * in making hypercalls and such that talk about specific
+- * processors.
+- *
+- * Return: Virtual processor number in Hyper-V terms
+- */
+-int vmbus_cpu_number_to_vp_number(int cpu_number)
+-{
+- return hv_context.vp_index[cpu_number];
+-}
+-EXPORT_SYMBOL_GPL(vmbus_cpu_number_to_vp_number);
+-
+ static int vmbus_acpi_add(struct acpi_device *device)
+ {
+ acpi_status result;
+diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
+--- a/drivers/pci/host/pci-hyperv.c
++++ b/drivers/pci/host/pci-hyperv.c
+@@ -562,52 +562,6 @@ static void put_pcichild(struct hv_pci_dev *hv_pcidev,
+ static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus);
+ static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus);
+
+-
+-/*
+- * Temporary CPU to vCPU mapping to address transitioning
+- * vmbus_cpu_number_to_vp_number() being migrated to
+- * hv_cpu_number_to_vp_number() in a separate patch. Once that patch
+- * has been picked up in the main line, remove this code here and use
+- * the official code.
+- */
+-static struct hv_tmpcpumap
+-{
+- bool initialized;
+- u32 vp_index[NR_CPUS];
+-} hv_tmpcpumap;
+-
+-static void hv_tmpcpumap_init_cpu(void *_unused)
+-{
+- int cpu = smp_processor_id();
+- u64 vp_index;
+-
+- hv_get_vp_index(vp_index);
+-
+- hv_tmpcpumap.vp_index[cpu] = vp_index;
+-}
+-
+-static void hv_tmpcpumap_init(void)
+-{
+- if (hv_tmpcpumap.initialized)
+- return;
+-
+- memset(hv_tmpcpumap.vp_index, -1, sizeof(hv_tmpcpumap.vp_index));
+- on_each_cpu(hv_tmpcpumap_init_cpu, NULL, true);
+- hv_tmpcpumap.initialized = true;
+-}
+-
+-/**
+- * hv_tmp_cpu_nr_to_vp_nr() - Convert Linux CPU nr to Hyper-V vCPU nr
+- *
+- * Remove once vmbus_cpu_number_to_vp_number() has been converted to
+- * hv_cpu_number_to_vp_number() and replace callers appropriately.
+- */
+-static u32 hv_tmp_cpu_nr_to_vp_nr(int cpu)
+-{
+- return hv_tmpcpumap.vp_index[cpu];
+-}
+-
+-
+ /**
+ * devfn_to_wslot() - Convert from Linux PCI slot to Windows
+ * @devfn: The Linux representation of PCI slot
+@@ -971,7 +925,7 @@ static void hv_irq_unmask(struct irq_data *data)
+ var_size = 1 + HV_VP_SET_BANK_COUNT_MAX;
+
+ for_each_cpu_and(cpu, dest, cpu_online_mask) {
+- cpu_vmbus = hv_tmp_cpu_nr_to_vp_nr(cpu);
++ cpu_vmbus = hv_cpu_number_to_vp_number(cpu);
+
+ if (cpu_vmbus >= HV_VP_SET_BANK_COUNT_MAX * 64) {
+ dev_err(&hbus->hdev->device,
+@@ -986,7 +940,7 @@ static void hv_irq_unmask(struct irq_data *data)
+ } else {
+ for_each_cpu_and(cpu, dest, cpu_online_mask) {
+ params->int_target.vp_mask |=
+- (1ULL << hv_tmp_cpu_nr_to_vp_nr(cpu));
++ (1ULL << hv_cpu_number_to_vp_number(cpu));
+ }
+ }
+
+@@ -1063,7 +1017,7 @@ static u32 hv_compose_msi_req_v2(
+ */
+ cpu = cpumask_first_and(affinity, cpu_online_mask);
+ int_pkt->int_desc.processor_array[0] =
+- hv_tmp_cpu_nr_to_vp_nr(cpu);
++ hv_cpu_number_to_vp_number(cpu);
+ int_pkt->int_desc.processor_count = 1;
+
+ return sizeof(*int_pkt);
+@@ -2490,8 +2444,6 @@ static int hv_pci_probe(struct hv_device *hdev,
+ return -ENOMEM;
+ hbus->state = hv_pcibus_init;
+
+- hv_tmpcpumap_init();
+-
+ /*
+ * The PCI bus "domain" is what is called "segment" in ACPI and
+ * other specs. Pull it from the instance ID, to get something
+diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -1173,7 +1173,6 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
+ resource_size_t size, resource_size_t align,
+ bool fb_overlap_ok);
+ void vmbus_free_mmio(resource_size_t start, resource_size_t size);
+-int vmbus_cpu_number_to_vp_number(int cpu_number);
+
+ /*
+ * GUID definitions of various offer types - services offered to the guest.
diff --git a/series.conf b/series.conf
index ca448e5ef0..5ef011fbf2 100644
--- a/series.conf
+++ b/series.conf
@@ -1673,6 +1673,7 @@
patches.suse/msft-hv-1420-x86-hyper-v-Introduce-fast-hypercall-implementation.patch
patches.suse/msft-hv-1421-hyper-v-Use-fast-hypercall-for-HVCALL_SIGNAL_EVENT.patch
patches.suse/msft-hv-1422-x86-hyper-v-Implement-rep-hypercalls.patch
+ patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch
patches.suse/suse-hv-guest-os-id.patch
patches.suse/suse-hv-kvp_on_msg.dbg.patch