[PATCH 1/2] Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl()
From: Dexuan Cui This is a longstanding issue: if the vmbus upper-layer drivers try to consume too many GPADLs, the host may return with an error 0xC044 (STATUS_QUOTA_EXCEEDED), but currently we forget to check the creation_status, and hence we can pass an invalid GPADL handle into the OPEN_CHANNEL message, and get an error code 0xc225 in open_info->response.open_result.status, and finally we hang in vmbus_open() -> "goto error_free_info" -> vmbus_teardown_gpadl(). With this patch, we can exit gracefully on STATUS_QUOTA_EXCEEDED. Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: sta...@vger.kernel.org Signed-off-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index f96a77b18bb9..ce0ba2062723 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, } wait_for_completion(&msginfo->waitevent); + if (msginfo->response.gpadl_created.creation_status != 0) { + pr_err("Failed to establish GPADL: err = 0x%x\n", + msginfo->response.gpadl_created.creation_status); + + ret = -EDQUOT; + goto cleanup; + } + if (channel->rescind) { ret = -ENODEV; goto cleanup; -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues
From: Dexuan Cui vmbus_process_offer() mustn't call channel->sc_creation_callback() directly for sub-channels, because sc_creation_callback() -> vmbus_open() may never get the host's response to the OPEN_CHANNEL message (the host may rescind a channel at any time, e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind() may not wake up the vmbus_open() as it's blocked due to a non-zero vmbus_connection.offer_in_progress, and finally we have a deadlock. The above is also true for primary channels, if the related device drivers use sync probing mode by default. And, usually the handling of primary channels and sub-channels can depend on each other, so we should offload them to different workqueues to avoid possible deadlock, e.g. in sync-probing mode, NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() -> rtnl_lock(), and causes deadlock: the former gets the rtnl_lock and waits for all the sub-channels to appear, but the latter can't get the rtnl_lock and this blocks the handling of sub-channels. The patch can fix the multiple-NIC deadlock described above for v3.x kernels (e.g. RHEL 7.x) which don't support async-probing of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing but don't enable async-probing for Hyper-V drivers (yet). The patch can also fix the hang issue in sub-channel's handling described above for all versions of kernels, including v4.19 and v4.20-rc3. So the patch should be applied to all the existing kernels. Fixes: 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug") Cc: sta...@vger.kernel.org Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 188 +- drivers/hv/connection.c | 24 - drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h| 7 ++ 4 files changed, 161 insertions(+), 65 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 82e673671087..d01689079e9b 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -434,60 +434,16 @@ void vmbus_free_channels(void) } } -/* - * vmbus_process_offer - Process the offer by creating a channel/device - * associated with this offer - */ -static void vmbus_process_offer(struct vmbus_channel *newchannel) +/* Note: the function can run concurrently for primary/sub channels. */ +static void vmbus_add_channel_work(struct work_struct *work) { - struct vmbus_channel *channel; - bool fnew = true; + struct vmbus_channel *newchannel = + container_of(work, struct vmbus_channel, add_channel_work); + struct vmbus_channel *primary_channel = newchannel->primary_channel; unsigned long flags; u16 dev_type; int ret; - /* Make sure this is a new offer */ - mutex_lock(&vmbus_connection.channel_mutex); - - /* -* Now that we have acquired the channel_mutex, -* we can release the potentially racing rescind thread. -*/ - atomic_dec(&vmbus_connection.offer_in_progress); - - list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { - if (!uuid_le_cmp(channel->offermsg.offer.if_type, - newchannel->offermsg.offer.if_type) && - !uuid_le_cmp(channel->offermsg.offer.if_instance, - newchannel->offermsg.offer.if_instance)) { - fnew = false; - break; - } - } - - if (fnew) - list_add_tail(&newchannel->listentry, - &vmbus_connection.chn_list); - - mutex_unlock(&vmbus_connection.channel_mutex); - - if (!fnew) { - /* -* Check to see if this is a sub-channel. -*/ - if (newchannel->offermsg.offer.sub_channel_index != 0) { - /* -* Process the sub-channel. -*/ - newchannel->primary_channel = channel; - spin_lock_irqsave(&channel->lock, flags); - list_add_tail(&newchannel->sc_list, &channel->sc_list); - spin_unlock_irqrestore(&channel->lock, flags); - } else { - goto err_free_chan; - } - } - dev_type = hv_get_dev_type(newchannel); init_vp_index(newchannel, dev_type); @@ -505,27 +461,26 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) /* * This state is used to indicate a successful open * so that when we do close the channel normally, we -* can cleanup properly +* can cleanup properly. */ newchannel->state = CHANNEL_OPEN_STATE; - if (!fnew) { - struct hv_device *dev - = newchann
[PATCH 0/2] Drivers: hv: vmbus: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. Dexuan Cui (2): Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl() Drivers: hv: vmbus: offload the handling of channels to two workqueues drivers/hv/channel.c | 8 ++ drivers/hv/channel_mgmt.c | 188 +- drivers/hv/connection.c | 24 - drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h| 7 ++ 5 files changed, 169 insertions(+), 65 deletions(-) -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] Drivers: hv: vmbus: Remove the useless API vmbus_get_outgoing_channel()
From: Dexuan Cui Commit d86adf482b84 ("scsi: storvsc: Enable multi-queue support") removed the usage of the API in Jan 2017, and the API is not used since then. netvsc and storvsc have their own algorithms to determine the outgoing channel, so this API is useless. And the API is potentially unsafe, because it reads primary->num_sc without any lock held. This can be risky considering the RESCIND-OFFER message. Let's remove the API. Cc: Long Li Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel.c | 1 - drivers/hv/channel_mgmt.c | 45 --- include/linux/hyperv.h| 17 --- 3 files changed, 63 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index de8193f3b838..f96a77b18bb9 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -703,7 +703,6 @@ int vmbus_disconnect_ring(struct vmbus_channel *channel) /* Snapshot the list of subchannels */ spin_lock_irqsave(&channel->lock, flags); list_splice_init(&channel->sc_list, &list); - channel->num_sc = 0; spin_unlock_irqrestore(&channel->lock, flags); list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) { diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 6277597d3d58..82e673671087 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -405,7 +405,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel) primary_channel = channel->primary_channel; spin_lock_irqsave(&primary_channel->lock, flags); list_del(&channel->sc_list); - primary_channel->num_sc--; spin_unlock_irqrestore(&primary_channel->lock, flags); } @@ -483,7 +482,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) newchannel->primary_channel = channel; spin_lock_irqsave(&channel->lock, flags); list_add_tail(&newchannel->sc_list, &channel->sc_list); - channel->num_sc++; spin_unlock_irqrestore(&channel->lock, flags); } else { goto err_free_chan; @@ -1239,49 +1237,6 @@ int vmbus_request_offers(void) return ret; } -/* - * Retrieve the (sub) channel on which to send an outgoing request. - * When a primary channel has multiple sub-channels, we try to - * distribute the load equally amongst all available channels. - */ -struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) -{ - struct list_head *cur, *tmp; - int cur_cpu; - struct vmbus_channel *cur_channel; - struct vmbus_channel *outgoing_channel = primary; - int next_channel; - int i = 1; - - if (list_empty(&primary->sc_list)) - return outgoing_channel; - - next_channel = primary->next_oc++; - - if (next_channel > (primary->num_sc)) { - primary->next_oc = 0; - return outgoing_channel; - } - - 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) - continue; - - if (cur_channel->target_vp == cur_cpu) - return cur_channel; - - if (i == next_channel) - return cur_channel; - - i++; - } - - return outgoing_channel; -} -EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel); - static void invoke_sc_cb(struct vmbus_channel *primary_channel) { struct list_head *cur, *tmp; diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index b3e24368930a..07a367f5e22f 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -830,15 +830,6 @@ struct vmbus_channel { * All Sub-channels of a primary channel are linked here. */ struct list_head sc_list; - /* -* Current number of sub-channels. -*/ - int num_sc; - /* -* Number of a sub-channel (position within sc_list) which is supposed -* to be used as the next outgoing channel. -*/ - int next_oc; /* * The primary channel this sub-channel belongs to. * This will be NULL for the primary channel. @@ -965,14 +956,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel, void (*chn_rescind_cb)(struct vmbus_channel *)); -/* - * Retrieve the (sub) channel on which to send an outgoing request. - * When a primary channel has multiple sub-channels, we choose a - * channel whose VCPU binding is clos
[PATCH] scsi: storvsc: Fix a race in sub-channel creation that can cause panic
From: Dexuan Cui We can concurrently try to open the same sub-channel from 2 paths: path #1: vmbus_onoffer() -> vmbus_process_offer() -> handle_sc_creation(). path #2: storvsc_probe() -> storvsc_connect_to_vsp() -> -> storvsc_channel_init() -> handle_multichannel_storage() -> -> vmbus_are_subchannels_present() -> handle_sc_creation(). They conflict with each other, but it was not an issue before the recent commit ae6935ed7d42 ("vmbus: split ring buffer allocation from open"), because at the beginning of vmbus_open() we checked newchannel->state so only one path could succeed, and the other would return with -EINVAL. After ae6935ed7d42, the failing path frees the channel's ringbuffer by vmbus_free_ring(), and this causes a panic later. Commit ae6935ed7d42 itself is good, and it just reveals the longstanding race. We can resolve the issue by removing path #2, i.e. removing the second vmbus_are_subchannels_present() in handle_multichannel_storage(). BTW, the comment "Check to see if sub-channels have already been created" in handle_multichannel_storage() is incorrect: when we unload the driver, we first close the sub-channel(s) and then close the primary channel, next the host sends rescind-offer message(s) so primary->sc_list will become empty. This means the first vmbus_are_subchannels_present() in handle_multichannel_storage() is never useful. Fixes: ae6935ed7d42 ("vmbus: split ring buffer allocation from open") Cc: sta...@vger.kernel.org Cc: Long Li Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- drivers/scsi/storvsc_drv.c | 61 +++--- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f03dc03a42c3..8f88348ebe42 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -446,7 +446,6 @@ struct storvsc_device { bool destroy; bool drain_notify; - bool open_sub_channel; atomic_t num_outstanding_req; struct Scsi_Host *host; @@ -636,33 +635,38 @@ static inline struct storvsc_device *get_in_stor_device( static void handle_sc_creation(struct vmbus_channel *new_sc) { struct hv_device *device = new_sc->primary_channel->device_obj; + struct device *dev = &device->device; struct storvsc_device *stor_device; struct vmstorage_channel_properties props; + int ret; stor_device = get_out_stor_device(device); if (!stor_device) return; - if (stor_device->open_sub_channel == false) - return; - memset(&props, 0, sizeof(struct vmstorage_channel_properties)); - vmbus_open(new_sc, - storvsc_ringbuffer_size, - storvsc_ringbuffer_size, - (void *)&props, - sizeof(struct vmstorage_channel_properties), - storvsc_on_channel_callback, new_sc); + ret = vmbus_open(new_sc, +storvsc_ringbuffer_size, +storvsc_ringbuffer_size, +(void *)&props, +sizeof(struct vmstorage_channel_properties), +storvsc_on_channel_callback, new_sc); - if (new_sc->state == CHANNEL_OPENED_STATE) { - stor_device->stor_chns[new_sc->target_cpu] = new_sc; - cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); + /* In case vmbus_open() fails, we don't use the sub-channel. */ + if (ret != 0) { + dev_err(dev, "Failed to open sub-channel: err=%d\n", ret); + return; } + + /* Add the sub-channel to the array of available channels. */ + stor_device->stor_chns[new_sc->target_cpu] = new_sc; + cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); } static void handle_multichannel_storage(struct hv_device *device, int max_chns) { + struct device *dev = &device->device; struct storvsc_device *stor_device; int num_cpus = num_online_cpus(); int num_sc; @@ -679,21 +683,11 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) request = &stor_device->init_request; vstor_packet = &request->vstor_packet; - stor_device->open_sub_channel = true; /* * Establish a handler for dealing with subchannels. */ vmbus_set_sc_create_callback(device->channel, handle_sc_creation); - /* -* Check to see if sub-channels have already been created. This -* can happen when this driver is re-loaded after unloading. -*/ - - if (vmbus_are_subchannels_present(device->channel)) - return; - - stor_device->open_sub_channel = false; /* * Request the host to create sub-channels. */ @@ -710,23 +
[PATCH 4/4] Drivers: hv: Enable CONFIG_HYPERV on ARM64
From: Michael Kelley Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on ARM64, causing the Hyper-V specific code to be built. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 97954f575c3f..c3e11a2f9c70 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support" config HYPERV tristate "Microsoft Hyper-V client drivers" - depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST + depends on ACPI && PCI && \ + ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64) select PARAVIRT help Select this option to run Linux as a Hyper-V client operating -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/4] arm64: hyperv: Add support for Hyper-V as a hypervisor
From: Michael Kelley Add ARM64-specific code to enable Hyper-V. This code includes: * Detecting Hyper-V and initializing the guest/Hyper-V interface * Setting up Hyper-V's synthetic clocks * Making hypercalls using the HVC instruction * Setting up VMbus and stimer0 interrupts * Setting up kexec and crash handlers This code is architecture dependent code and is mostly driven by architecture independent code in the VMbus driver in drivers/hv/hv.c and drivers/hv/vmbus_drv.c. This code is built only when CONFIG_HYPERV is enabled. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- MAINTAINERS | 1 + arch/arm64/Makefile | 1 + arch/arm64/hyperv/Makefile | 2 + arch/arm64/hyperv/hv_hvc.S | 54 + arch/arm64/hyperv/hv_init.c | 441 +++ arch/arm64/hyperv/mshyperv.c | 178 ++ 6 files changed, 677 insertions(+) create mode 100644 arch/arm64/hyperv/Makefile create mode 100644 arch/arm64/hyperv/hv_hvc.S create mode 100644 arch/arm64/hyperv/hv_init.c create mode 100644 arch/arm64/hyperv/mshyperv.c diff --git a/MAINTAINERS b/MAINTAINERS index 72f19cef4c48..326eeb32a0cd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6837,6 +6837,7 @@ F:arch/x86/kernel/cpu/mshyperv.c F: arch/x86/hyperv F: arch/arm64/include/asm/hyperv-tlfs.h F: arch/arm64/include/asm/mshyperv.h +F: arch/arm64/hyperv F: drivers/hid/hid-hyperv.c F: drivers/hv/ F: drivers/input/serio/hyperv-keyboard.c diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 6cb9fc7e9382..ad9ec0579553 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -106,6 +106,7 @@ core-y += arch/arm64/kernel/ arch/arm64/mm/ core-$(CONFIG_NET) += arch/arm64/net/ core-$(CONFIG_KVM) += arch/arm64/kvm/ core-$(CONFIG_XEN) += arch/arm64/xen/ +core-$(CONFIG_HYPERV) += arch/arm64/hyperv/ core-$(CONFIG_CRYPTO) += arch/arm64/crypto/ libs-y := arch/arm64/lib/ $(libs-y) core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile new file mode 100644 index ..988eda55330c --- /dev/null +++ b/arch/arm64/hyperv/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-y := hv_init.o hv_hvc.o mshyperv.o diff --git a/arch/arm64/hyperv/hv_hvc.S b/arch/arm64/hyperv/hv_hvc.S new file mode 100644 index ..82636969b4f2 --- /dev/null +++ b/arch/arm64/hyperv/hv_hvc.S @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Microsoft Hyper-V hypervisor invocation routines + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : Michael Kelley + * + * 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 + + .text +/* + * Do the HVC instruction. For Hyper-V the argument is always 1. + * x0 contains the hypercall control value, while additional registers + * vary depending on the hypercall, and whether the hypercall arguments + * are in memory or in registers (a "fast" hypercall per the Hyper-V + * TLFS). When the arguments are in memory x1 is the guest physical + * address of the input arguments, and x2 is the guest physical + * address of the output arguments. When the arguments are in + * registers, the register values depends on the hypercall. Note + * that this version cannot return any values in registers. + */ +ENTRY(hv_do_hvc) + hvc #1 + ret +ENDPROC(hv_do_hvc) + +/* + * This variant of HVC invocation is for hv_get_vpreg and + * hv_get_vpreg_128. The input parameters are passed in registers + * along with a pointer in x4 to where the output result should + * be stored. The output is returned in x15 and x16. x18 is used as + * scratch space to avoid buildng a stack frame, as Hyper-V does + * not preserve registers x0-x17. + */ +ENTRY(hv_do_hvc_fast_get) + mov x18, x4 + hvc #1 + str x15,[x18] + str x16,[x18,#8] + ret +ENDPROC(hv_do_hvc_fast_get) diff --git a/arch/arm64/hyperv/hv_init.c b/arch/arm64/hyperv/hv_init.c new file mode 100644 index ..aa1a8c09d989 --- /dev/null +++ b/arch/arm64/hyperv/hv_init.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Initialization of the interface with Microsoft's Hyper-V hypervisor, + * and various low level utility routines for interacting with Hyper-V. + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : Michael Kelley + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GN
[PATCH 3/4] Drivers: hv: vmbus: Add hooks for per-CPU IRQ
From: Michael Kelley Add hooks to enable/disable a per-CPU IRQ for VMbus. These hooks are in the architecture independent setup and shutdown paths for Hyper-V, and are needed by Linux guests on Hyper-V on ARM64. The x86/x64 implementation is null because VMbus interrupts on x86/x64 don't use an IRQ. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/include/asm/mshyperv.h | 4 drivers/hv/hv.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 0d6271cce198..8d97bd3a13a6 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -109,6 +109,10 @@ void hyperv_vector_handler(struct pt_regs *regs); void hv_setup_vmbus_irq(void (*handler)(void)); void hv_remove_vmbus_irq(void); +/* On x86/x64, there isn't a real IRQ to be enabled/disable */ +static inline void hv_enable_vmbus_irq(void) {} +static inline void hv_disable_vmbus_irq(void) {} + void hv_setup_kexec_handler(void (*handler)(void)); void hv_remove_kexec_handler(void); void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 166c2501de17..d0bb09a4bd73 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -307,6 +307,7 @@ int hv_synic_init(unsigned int cpu) hv_set_siefp(siefp.as_uint64); /* Setup the shared SINT. */ + hv_enable_vmbus_irq(); hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; @@ -434,6 +435,7 @@ int hv_synic_cleanup(unsigned int cpu) /* Disable the global synic bit */ sctrl.enable = 0; hv_set_synic_state(sctrl.as_uint64); + hv_disable_vmbus_irq(); return 0; } -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/4] arm64: hyperv: Add core Hyper-V include files
From: Michael Kelley hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level Functional Spec (TLFS). The TLFS is distinctly oriented to x86/x64, and Hyper-V has not separated out the architecture-dependent parts into x86/x64 vs. ARM64. So hyperv-tlfs.h includes information for ARM64 that is not yet formally published. The TLFS is available here: docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs mshyperv.h defines Linux-specific structures and routines for interacting with Hyper-V. It is split into an ARM64 specific file and an architecture independent file in include/asm-generic. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- MAINTAINERS | 3 + arch/arm64/include/asm/hyperv-tlfs.h | 338 +++ arch/arm64/include/asm/mshyperv.h| 116 + include/asm-generic/mshyperv.h | 240 +++ 4 files changed, 697 insertions(+) create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h create mode 100644 arch/arm64/include/asm/mshyperv.h create mode 100644 include/asm-generic/mshyperv.h diff --git a/MAINTAINERS b/MAINTAINERS index f4855974f325..72f19cef4c48 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6835,6 +6835,8 @@ F:arch/x86/include/asm/trace/hyperv.h F: arch/x86/include/asm/hyperv-tlfs.h F: arch/x86/kernel/cpu/mshyperv.c F: arch/x86/hyperv +F: arch/arm64/include/asm/hyperv-tlfs.h +F: arch/arm64/include/asm/mshyperv.h F: drivers/hid/hid-hyperv.c F: drivers/hv/ F: drivers/input/serio/hyperv-keyboard.c @@ -6846,6 +6848,7 @@ F:drivers/video/fbdev/hyperv_fb.c F: net/vmw_vsock/hyperv_transport.c F: include/linux/hyperv.h F: include/uapi/linux/hyperv.h +F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h new file mode 100644 index ..924e37600e92 --- /dev/null +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * This file contains definitions from the Hyper-V Hypervisor Top-Level + * Functional Specification (TLFS): + * https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fvirtualization%2Fhyper-v-on-windows%2Freference%2Ftlfs&data=02%7C01%7Ckys%40microsoft.com%7Cc831a45fd63e4a4b083908d641216aa8%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636768009113747528&sdata=jRSrs9ZWXdmeS7LQUEpoSyUfBS7a5KLYy%2FolFdE2tI0%3D&reserved=0 + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : Michael Kelley + * + * 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. + */ + +#ifndef _ASM_ARM64_HYPERV_H +#define _ASM_ARM64_HYPERV_H + +#include + +/* + * These Hyper-V registers provide information equivalent to the CPUID + * instruction on x86/x64. + */ +#define HV_REGISTER_HYPERVISOR_VERSION 0x0100 /*CPUID 0x4002 */ +#defineHV_REGISTER_PRIVILEGES_AND_FEATURES 0x0200 /*CPUID 0x4003 */ +#defineHV_REGISTER_FEATURES0x0201 /*CPUID 0x4004 */ +#defineHV_REGISTER_IMPLEMENTATION_LIMITS 0x0202 /*CPUID 0x4005 */ +#define HV_ARM64_REGISTER_INTERFACE_VERSION0x00090006 /*CPUID 0x4001 */ + +/* + * Feature identification. HvRegisterPrivilegesAndFeaturesInfo returns a + * 128-bit value with flags indicating which features are available to the + * partition based upon the current partition privileges. The 128-bit + * value is broken up with different portions stored in different 32-bit + * fields in the ms_hyperv structure. + */ + +/* Partition Reference Counter available*/ +#define HV_MSR_TIME_REF_COUNT_AVAILABLE(1 << 1) + +/* + * Synthetic Timers available + */ +#define HV_MSR_SYNTIMER_AVAILABLE (1 << 3) + +/* Frequency MSRs available */ +#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE(1 << 8) + +/* Reference TSC available */ +#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9) + +/* Crash MSR available */ +#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10) + + +/* + * This group of flags is in the high order 64-bits of the returned + * 128-bit value. + */ + +/* STIMER direct mode is available */ +#define HV_STIMER_DIRECT_MODE_AVAILABLE(1 << 19) + +/* + * Implementation recommendations in register + * HvRegisterFeaturesInfo. Indicates which behaviors the hypervisor + * recommends the OS implement for optimal per
[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64
From: "K. Y. Srinivasan" This series enables Linux guests running on Hyper-V on ARM64 hardware. New ARM64-specific code in arch/arm64/hyperv initializes Hyper-V, including its synthetic clocks and hypercall mechanism. Existing architecture independent drivers for Hyper-V's VMbus and synthetic devices just work when built for ARM64. Hyper-V code is built and included in the image and modules only if CONFIG_HYPERV is enabled. The four patches are organized as follows: 1) Add include files that define the Hyper-V interface as described in the Hyper-V Top Level Functional Spec (TLFS), plus additional definitions specific to Linux running on Hyper-V. 2) Add core Hyper-V support on ARM64, including hypercalls, synthetic clock initialization, and interrupt handlers. 3) Update the existing VMbus driver to generalize interrupt management across x86/x64 and ARM64. 4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64. Some areas of Linux guests on Hyper-V on ARM64 are a work- in-progress, primarily due to work still being done in Hyper-V: * Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only supports guests with a 4 Kbyte page size. Because Hyper-V uses shared pages to communicate between the guest and the hypervisor, there are open design decisions on the page size to use when the guest is using 16K/64K pages. Once those issues are resolved and Hyper-V fully supports 16K/64K guest pages, changes may be needed in the Linux drivers for Hyper-V synthetic devices. * Hyper-V on ARM64 does not currently support mapping PCI devices into the guest address space. The Hyper-V PCI driver at drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is not being built for ARM64. In a few cases, terminology from the x86/x64 world has been carried over into the ARM64 code ("MSR", "TSC"). Hyper-V still uses the x86/x64 terminology and has not replaced it with something more generic, so the code uses the Hyper-V terminology. This will be fixed when Hyper-V updates the usage in the TLFS. Michael Kelley (4): arm64: hyperv: Add core Hyper-V include files arm64: hyperv: Add support for Hyper-V as a hypervisor Drivers: hv: vmbus: Add hooks for per-CPU IRQ Drivers: hv: Enable CONFIG_HYPERV on ARM64 MAINTAINERS | 4 + arch/arm64/Makefile | 1 + arch/arm64/hyperv/Makefile | 2 + arch/arm64/hyperv/hv_hvc.S | 54 arch/arm64/hyperv/hv_init.c | 441 +++ arch/arm64/hyperv/mshyperv.c | 178 +++ arch/arm64/include/asm/hyperv-tlfs.h | 338 arch/arm64/include/asm/mshyperv.h| 116 +++ arch/x86/include/asm/mshyperv.h | 4 + drivers/hv/Kconfig | 3 +- drivers/hv/hv.c | 2 + include/asm-generic/mshyperv.h | 240 +++ 12 files changed, 1382 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/hyperv/Makefile create mode 100644 arch/arm64/hyperv/hv_hvc.S create mode 100644 arch/arm64/hyperv/hv_init.c create mode 100644 arch/arm64/hyperv/mshyperv.c create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h create mode 100644 arch/arm64/include/asm/mshyperv.h create mode 100644 include/asm-generic/mshyperv.h -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64
From: "K. Y. Srinivasan" This series enables Linux guests running on Hyper-V on ARM64 hardware. New ARM64-specific code in arch/arm64/hyperv initializes Hyper-V, including its synthetic clocks and hypercall mechanism. Existing architecture independent drivers for Hyper-V's VMbus and synthetic devices just work when built for ARM64. Hyper-V code is built and included in the image and modules only if CONFIG_HYPERV is enabled. The four patches are organized as follows: 1) Add include files that define the Hyper-V interface as described in the Hyper-V Top Level Functional Spec (TLFS), plus additional definitions specific to Linux running on Hyper-V. 2) Add core Hyper-V support on ARM64, including hypercalls, synthetic clock initialization, and interrupt handlers. 3) Update the existing VMbus driver to generalize interrupt management across x86/x64 and ARM64. 4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64. Some areas of Linux guests on Hyper-V on ARM64 are a work- in-progress, primarily due to work still being done in Hyper-V: * Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only supports guests with a 4 Kbyte page size. Because Hyper-V uses shared pages to communicate between the guest and the hypervisor, there are open design decisions on the page size to use when the guest is using 16K/64K pages. Once those issues are resolved and Hyper-V fully supports 16K/64K guest pages, changes may be needed in the Linux drivers for Hyper-V synthetic devices. * Hyper-V on ARM64 does not currently support mapping PCI devices into the guest address space. The Hyper-V PCI driver at drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is not being built for ARM64. In a few cases, terminology from the x86/x64 world has been carried over into the ARM64 code ("MSR", "TSC"). Hyper-V still uses the x86/x64 terminology and has not replaced it with something more generic, so the code uses the Hyper-V terminology. This will be fixed when Hyper-V updates the usage in the TLFS. Michael Kelley (4): arm64: hyperv: Add core Hyper-V include files arm64: hyperv: Add support for Hyper-V as a hypervisor Drivers: hv: vmbus: Add hooks for per-CPU IRQ Drivers: hv: Enable CONFIG_HYPERV on ARM64 MAINTAINERS | 4 + arch/arm64/Makefile | 1 + arch/arm64/hyperv/Makefile | 2 + arch/arm64/hyperv/hv_hvc.S | 54 arch/arm64/hyperv/hv_init.c | 441 +++ arch/arm64/hyperv/mshyperv.c | 178 +++ arch/arm64/include/asm/hyperv-tlfs.h | 338 arch/arm64/include/asm/mshyperv.h| 116 +++ arch/x86/include/asm/mshyperv.h | 4 + drivers/hv/Kconfig | 3 +- drivers/hv/hv.c | 2 + include/asm-generic/mshyperv.h | 240 +++ 12 files changed, 1382 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/hyperv/Makefile create mode 100644 arch/arm64/hyperv/hv_hvc.S create mode 100644 arch/arm64/hyperv/hv_init.c create mode 100644 arch/arm64/hyperv/mshyperv.c create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h create mode 100644 arch/arm64/include/asm/mshyperv.h create mode 100644 include/asm-generic/mshyperv.h -- 2.19.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 2/5] hv_utils: update name in struct hv_driver util_drv
From: Haiyang Zhang The correct module name is hv_utils. This patch corrects the name in struct hv_driver util_drv. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 423205077bf6..f10eeb120c8b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver util_drv = { - .name = "hv_util", + .name = "hv_utils", .id_table = id_table, .probe = util_probe, .remove = util_remove, -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 4/5] Drivers: hv: kvp: Use %u to print U32
From: Dexuan Cui I didn't find a real issue. Let's just make it consistent with the next "case REG_U64:" where %llu is used. Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index d6106e1a0d4a..5054d1105236 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy) val32 = in_msg->body.kvp_set.data.value_u32; message->body.kvp_set.data.value_size = sprintf(message->body.kvp_set.data.value, - "%d", val32) + 1; + "%u", val32) + 1; break; case REG_U64: -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context
From: "K. Y. Srinivasan" Currently we are replicating state in struct hv_context that is unnecessary - this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu state that is being maintained as a global state in struct hv_context. Get rid of this state in struct hv_context. Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 10 +++--- drivers/hv/hyperv_vmbus.h | 2 -- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 332d7c34be5c..166c2501de17 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -33,9 +33,7 @@ #include "hyperv_vmbus.h" /* The one and only */ -struct hv_context hv_context = { - .synic_initialized = false, -}; +struct hv_context hv_context; /* * If false, we're using the old mechanism for stimer0 interrupts @@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu) hv_set_synic_state(sctrl.as_uint64); - hv_context.synic_initialized = true; - /* * Register the per-cpu clockevent source. */ @@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu) bool channel_found = false; unsigned long flags; - if (!hv_context.synic_initialized) + hv_get_synic_state(sctrl.as_uint64); + if (sctrl.enable != 1) return -EFAULT; /* @@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu) hv_set_siefp(siefp.as_uint64); /* Disable the global synic bit */ - hv_get_synic_state(sctrl.as_uint64); sctrl.enable = 0; hv_set_synic_state(sctrl.as_uint64); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 72eaba3d50fc..f17c06a5e74b 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -230,8 +230,6 @@ struct hv_context { void *tsc_page; - bool synic_initialized; - struct hv_per_cpu_context __percpu *cpu_context; /* -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up
From: Dexuan Cui In kvp_send_key(), we do need call process_ib_ipinfo() if message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out the userland hv_kvp_daemon needs the info of operation, adapter_id and addr_family. With the incorrect fc62c3b1977d, the host can't get the VM's IP via KVP. And, fc62c3b1977d added a "break;", but actually forgot to initialize the key_size/value in the case of KVP_OP_SET, so the default key_size of 0 is passed to the kvp daemon, and the pool files /var/lib/hyperv/.kvp_pool_* can't be updated. This patch effectively rolls back the previous fc62c3b1977d, and correctly fixes the "this statement may fall through" warnings. This patch is tested on WS 2012 R2 and 2016. Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall through" warnings") Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 26 ++ 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index a7513a8a8e37..d6106e1a0d4a 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op) out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; + /* fallthrough */ + + case KVP_OP_GET_IP_INFO: utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id, MAX_ADAPTER_ID_SIZE, UTF16_LITTLE_ENDIAN, @@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy) process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO); break; case KVP_OP_GET_IP_INFO: - /* We only need to pass on message->kvp_hdr.operation. */ + /* +* We only need to pass on the info of operation, adapter_id +* and addr_family to the userland kvp daemon. +*/ + process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO); break; case KVP_OP_SET: switch (in_msg->body.kvp_set.data.value_type) { @@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy) } - break; - - case KVP_OP_GET: + /* +* The key is always a string - utf16 encoding. +*/ message->body.kvp_set.data.key_size = utf16s_to_utf8s( (wchar_t *)in_msg->body.kvp_set.data.key, @@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy) UTF16_LITTLE_ENDIAN, message->body.kvp_set.data.key, HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; + + break; + + case KVP_OP_GET: + message->body.kvp_get.data.key_size = + utf16s_to_utf8s( + (wchar_t *)in_msg->body.kvp_get.data.key, + in_msg->body.kvp_get.data.key_size, + UTF16_LITTLE_ENDIAN, + message->body.kvp_get.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; break; case KVP_OP_DELETE: -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1
From: Dexuan Cui The patch fixes: hv_kvp_daemon.c: In function 'kvp_set_ip_info': hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes into a destination of size 4096 The "(unsigned int)str_len" is to avoid: hv_kvp_daemon.c:1309:30: warning: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Wsign-compare] Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_kvp_daemon.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index bbb2a8ef367c..d7e06fe0270e 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -1178,6 +1178,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) FILE *file; char cmd[PATH_MAX]; char *mac_addr; + int str_len; /* * Set the configuration for the specified interface with @@ -1301,8 +1302,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) * invoke the external script to do its magic. */ - snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s", -"hv_set_ifconfig", if_file); + str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s", + "hv_set_ifconfig", if_file); + /* +* This is a little overcautious, but it's necessary to suppress some +* false warnings from gcc 8.0.1. +*/ + if (str_len <= 0 || (unsigned int)str_len >= sizeof(cmd)) { + syslog(LOG_ERR, "Cmd '%s' (len=%d) may be too long", + cmd, str_len); + return HV_E_FAIL; + } + if (system(cmd)) { syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", cmd, errno, strerror(errno)); -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 0/5] Drivers: hv: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. V2: Addressed comments from Greg. Dexuan Cui (3): Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up Drivers: hv: kvp: Use %u to print U32 Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1 Haiyang Zhang (1): hv_utils: update name in struct hv_driver util_drv K. Y. Srinivasan (1): Drivers: hv: vmbus: Get rid of unnecessary state in hv_context drivers/hv/hv.c | 10 +++--- drivers/hv/hv_kvp.c | 28 +++- drivers/hv/hv_util.c | 2 +- drivers/hv/hyperv_vmbus.h | 2 -- tools/hv/hv_kvp_daemon.c | 15 +-- 5 files changed, 40 insertions(+), 17 deletions(-) -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context
From: "K. Y. Srinivasan" Currently we are replicating state in struct hv_context that is unnecessary - this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu state that is being maintained as a global state in struct hv_context. Get rid of this state in struct hv_context. Reply-To: k...@microsoft.com Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 10 +++--- drivers/hv/hyperv_vmbus.h | 2 -- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 332d7c34be5c..166c2501de17 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -33,9 +33,7 @@ #include "hyperv_vmbus.h" /* The one and only */ -struct hv_context hv_context = { - .synic_initialized = false, -}; +struct hv_context hv_context; /* * If false, we're using the old mechanism for stimer0 interrupts @@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu) hv_set_synic_state(sctrl.as_uint64); - hv_context.synic_initialized = true; - /* * Register the per-cpu clockevent source. */ @@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu) bool channel_found = false; unsigned long flags; - if (!hv_context.synic_initialized) + hv_get_synic_state(sctrl.as_uint64); + if (sctrl.enable != 1) return -EFAULT; /* @@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu) hv_set_siefp(siefp.as_uint64); /* Disable the global synic bit */ - hv_get_synic_state(sctrl.as_uint64); sctrl.enable = 0; hv_set_synic_state(sctrl.as_uint64); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 72eaba3d50fc..f17c06a5e74b 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -230,8 +230,6 @@ struct hv_context { void *tsc_page; - bool synic_initialized; - struct hv_per_cpu_context __percpu *cpu_context; /* -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/5] Drivers: hv: kvp: Use %u to print U32
From: Dexuan Cui I didn't find a real issue. Let's just make it consistent with the next "case REG_U64:" where %llu is used. Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 9fbb15c62c6c..3b8590ff94ba 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy) val32 = in_msg->body.kvp_set.data.value_u32; message->body.kvp_set.data.value_size = sprintf(message->body.kvp_set.data.value, - "%d", val32) + 1; + "%u", val32) + 1; break; case REG_U64: -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1
From: Dexuan Cui The patch fixes: hv_kvp_daemon.c: In function 'kvp_set_ip_info': hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes into a destination of size 4096 Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_kvp_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index bbb2a8ef367c..b7c2cf7eaba5 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -1176,7 +1176,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) int error = 0; char if_file[PATH_MAX]; FILE *file; - char cmd[PATH_MAX]; + char cmd[PATH_MAX * 2]; char *mac_addr; /* -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up
From: Dexuan Cui In kvp_send_key(), we do need call process_ib_ipinfo() if message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out the userland hv_kvp_daemon needs the info of operation, adapter_id and addr_family. With the incorrect fc62c3b1977d, the host can't get the VM's IP via KVP. And, fc62c3b1977d added a "break;", but actually forgot to initialize the key_size/value in the case of KVP_OP_SET, so the default key_size of 0 is passed to the kvp daemon, and the pool files /var/lib/hyperv/.kvp_pool_* can't be updated. This patch effectively rolls back the previous fc62c3b1977d, and correctly fixes the "this statement may fall through" warnings. This patch is tested on WS 2012 R2 and 2016. Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall through" warnings") Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 26 ++ 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index a7513a8a8e37..9fbb15c62c6c 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op) out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; + __attribute__ ((fallthrough)); + + case KVP_OP_GET_IP_INFO: utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id, MAX_ADAPTER_ID_SIZE, UTF16_LITTLE_ENDIAN, @@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy) process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO); break; case KVP_OP_GET_IP_INFO: - /* We only need to pass on message->kvp_hdr.operation. */ + /* +* We only need to pass on the info of operation, adapter_id +* and addr_family to the userland kvp daemon. +*/ + process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO); break; case KVP_OP_SET: switch (in_msg->body.kvp_set.data.value_type) { @@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy) } - break; - - case KVP_OP_GET: + /* +* The key is always a string - utf16 encoding. +*/ message->body.kvp_set.data.key_size = utf16s_to_utf8s( (wchar_t *)in_msg->body.kvp_set.data.key, @@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy) UTF16_LITTLE_ENDIAN, message->body.kvp_set.data.key, HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; + + break; + + case KVP_OP_GET: + message->body.kvp_get.data.key_size = + utf16s_to_utf8s( + (wchar_t *)in_msg->body.kvp_get.data.key, + in_msg->body.kvp_get.data.key_size, + UTF16_LITTLE_ENDIAN, + message->body.kvp_get.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; break; case KVP_OP_DELETE: -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/5] hv_utils: update name in struct hv_driver util_drv
From: Haiyang Zhang The correct module name is hv_utils. This patch corrects the name in struct hv_driver util_drv. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 423205077bf6..f10eeb120c8b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver util_drv = { - .name = "hv_util", + .name = "hv_utils", .id_table = id_table, .probe = util_probe, .remove = util_remove, -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/5] Drivers: hv: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. Dexuan Cui (3): Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up Drivers: hv: kvp: Use %u to print U32 Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1 Haiyang Zhang (1): hv_utils: update name in struct hv_driver util_drv K. Y. Srinivasan (1): Drivers: hv: vmbus: Get rid of unnecessary state in hv_context drivers/hv/hv.c | 10 +++--- drivers/hv/hv_kvp.c | 28 +++- drivers/hv/hv_util.c | 2 +- drivers/hv/hyperv_vmbus.h | 2 -- tools/hv/hv_kvp_daemon.c | 2 +- 5 files changed, 28 insertions(+), 16 deletions(-) -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/4] Drivers: hv: vmbus: Fix the descriptions of some function parameters
From: Dexuan Cui No functional change. Added descriptions for some parameters. Fixed some typos. Removed some out-of-date comments. Signed-off-by: Dexuan Cui Cc: Jonathan Corbet Cc: linux-...@vger.kernel.org Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel.c | 24 +--- drivers/hv/channel_mgmt.c | 23 +-- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 741857d80da1..ab92779271d0 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -709,15 +709,16 @@ EXPORT_SYMBOL_GPL(vmbus_close); /** * vmbus_sendpacket() - Send the specified buffer on the given channel - * @channel: Pointer to vmbus_channel structure. - * @buffer: Pointer to the buffer you want to receive the data into. - * @bufferlen: Maximum size of what the the buffer will hold + * @channel: Pointer to vmbus_channel structure + * @buffer: Pointer to the buffer you want to send the data from. + * @bufferlen: Maximum size of what the buffer holds. * @requestid: Identifier of the request - * @type: Type of packet that is being send e.g. negotiate, time - * packet etc. + * @type: Type of packet that is being sent e.g. negotiate, time + * packet etc. + * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED * - * Sends data in @buffer directly to hyper-v via the vmbus - * This will send the data unparsed to hyper-v. + * Sends data in @buffer directly to Hyper-V via the vmbus. + * This will send the data unparsed to Hyper-V. * * Mainly used by Hyper-V drivers. */ @@ -850,12 +851,13 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc); /** - * vmbus_recvpacket() - Retrieve the user packet on the specified channel - * @channel: Pointer to vmbus_channel structure. + * __vmbus_recvpacket() - Retrieve the user packet on the specified channel + * @channel: Pointer to vmbus_channel structure * @buffer: Pointer to the buffer you want to receive the data into. - * @bufferlen: Maximum size of what the the buffer will hold - * @buffer_actual_len: The actual size of the data after it was received + * @bufferlen: Maximum size of what the buffer can hold. + * @buffer_actual_len: The actual size of the data after it was received. * @requestid: Identifier of the request + * @raw: true means keep the vmpacket_descriptor header in the received data. * * Receives directly from the hyper-v vmbus and puts the data it received * into Buffer. This will receive the data unparsed from hyper-v. diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 0f0e091c117c..e7598b569bea 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -198,24 +198,19 @@ static u16 hv_get_dev_type(const struct vmbus_channel *channel) } /** - * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message + * vmbus_prep_negotiate_resp() - Create default response for Negotiate message * @icmsghdrp: Pointer to msg header structure - * @icmsg_negotiate: Pointer to negotiate message structure * @buf: Raw buffer channel data + * @fw_version: The framework versions we can support. + * @fw_vercnt: The size of @fw_version. + * @srv_version: The service versions we can support. + * @srv_vercnt: The size of @srv_version. + * @nego_fw_version: The selected framework version. + * @nego_srv_version: The selected service version. * - * @icmsghdrp is of type &struct icmsg_hdr. - * Set up and fill in default negotiate response message. - * - * The fw_version and fw_vercnt specifies the framework version that - * we can support. - * - * The srv_version and srv_vercnt specifies the service - * versions we can support. - * - * Versions are given in decreasing order. - * - * nego_fw_version and nego_srv_version store the selected protocol versions. + * Note: Versions are given in decreasing order. * + * Set up and fill in default negotiate response message. * Mainly used by Hyper-V drivers. */ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/4] Drivers: hv: kvp: Fix two "this statement may fall through" warnings
From: Dexuan Cui We don't need to call process_ib_ipinfo() if message->kvp_hdr.operation is KVP_OP_GET_IP_INFO in kvp_send_key(), because here we just need to pass on the op code from the host to the userspace; when the userspace returns the info requested by the host, we pass the info on to the host in kvp_respond_to_host() -> process_ob_ipinfo(). BTW, the current buggy code actually doesn't cause any harm, because only message->kvp_hdr.operation is used by the userspace, in the case of KVP_OP_GET_IP_INFO. The patch also adds a missing "break;" in kvp_send_key(). BTW, the current buggy code actually doesn't cause any harm, because in the case of KVP_OP_SET, the unexpected fall-through corrupts message->body.kvp_set.data.key_size, but that is not really used: see the definition of struct hv_kvp_exchg_msg_value. Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 023bd185d21a..a7513a8a8e37 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -353,7 +353,6 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op) out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; - default: utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id, MAX_ADAPTER_ID_SIZE, UTF16_LITTLE_ENDIAN, @@ -406,7 +405,7 @@ kvp_send_key(struct work_struct *dummy) process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO); break; case KVP_OP_GET_IP_INFO: - process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO); + /* We only need to pass on message->kvp_hdr.operation. */ break; case KVP_OP_SET: switch (in_msg->body.kvp_set.data.value_type) { @@ -446,6 +445,9 @@ kvp_send_key(struct work_struct *dummy) break; } + + break; + case KVP_OP_GET: message->body.kvp_set.data.key_size = utf16s_to_utf8s( -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/4] Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask
From: Dexuan Cui A cpumask structure on the stack can cause a warning with CONFIG_NR_CPUS=8192 (e.g. Ubuntu 16.04 and 18.04 use this): drivers/hv//channel_mgmt.c: In function ‘init_vp_index’: drivers/hv//channel_mgmt.c:702:1: warning: the frame size of 1032 bytes is larger than 1024 bytes [-Wframe-larger-than=] Nowadays it looks most distros enable CONFIG_CPUMASK_OFFSTACK=y, and hence we can work around the warning by using cpumask_var_t. Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Cc: Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index e7598b569bea..d943fa022e34 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -601,16 +601,18 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) bool perf_chn = vmbus_devs[dev_type].perf_device; struct vmbus_channel *primary = channel->primary_channel; int next_node; - struct cpumask available_mask; + cpumask_var_t available_mask; struct cpumask *alloced_mask; if ((vmbus_proto_version == VERSION_WS2008) || - (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) { + (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) || + !alloc_cpumask_var(&available_mask, GFP_KERNEL)) { /* * Prior to win8, all channel interrupts are * delivered on cpu 0. * Also if the channel is not a performance critical * channel, bind it to cpu 0. +* In case alloc_cpumask_var() fails, bind it to cpu 0. */ channel->numa_node = 0; channel->target_cpu = 0; @@ -648,7 +650,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) cpumask_clear(alloced_mask); } - cpumask_xor(&available_mask, alloced_mask, + cpumask_xor(available_mask, alloced_mask, cpumask_of_node(primary->numa_node)); cur_cpu = -1; @@ -666,10 +668,10 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) } while (true) { - cur_cpu = cpumask_next(cur_cpu, &available_mask); + cur_cpu = cpumask_next(cur_cpu, available_mask); if (cur_cpu >= nr_cpu_ids) { cur_cpu = -1; - cpumask_copy(&available_mask, + cpumask_copy(available_mask, cpumask_of_node(primary->numa_node)); continue; } @@ -699,6 +701,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) channel->target_cpu = cur_cpu; channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu); + + free_cpumask_var(available_mask); } static void vmbus_wait_for_unload(void) -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/4] Drivers: hv: kvp: Fix the indentation of some "break" statements
From: Dexuan Cui No functional change. Signed-off-by: Dexuan Cui Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_kvp.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 5eed1e7da15c..023bd185d21a 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -421,7 +421,7 @@ kvp_send_key(struct work_struct *dummy) UTF16_LITTLE_ENDIAN, message->body.kvp_set.data.value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1; - break; + break; case REG_U32: /* @@ -454,7 +454,7 @@ kvp_send_key(struct work_struct *dummy) UTF16_LITTLE_ENDIAN, message->body.kvp_set.data.key, HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; - break; + break; case KVP_OP_DELETE: message->body.kvp_delete.key_size = @@ -464,12 +464,12 @@ kvp_send_key(struct work_struct *dummy) UTF16_LITTLE_ENDIAN, message->body.kvp_delete.key, HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; - break; + break; case KVP_OP_ENUMERATE: message->body.kvp_enum_data.index = in_msg->body.kvp_enum_data.index; - break; + break; } kvp_transaction.state = HVUTIL_USERSPACE_REQ; -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/4] Drivers: hv: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. Dexuan Cui (4): Drivers: hv: vmbus: Fix the descriptions of some function parameters Drivers: hv: kvp: Fix the indentation of some "break" statements Drivers: hv: kvp: Fix two "this statement may fall through" warnings Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask drivers/hv/channel.c | 24 +--- drivers/hv/channel_mgmt.c | 37 ++--- drivers/hv/hv_kvp.c | 14 -- 3 files changed, 39 insertions(+), 36 deletions(-) -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/2] Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect()
From: Dexuan Cui With CONFIG_DEBUG_PREEMPT=y, I always see this warning: BUG: using smp_processor_id() in preemptible [] Fix the false warning by using get/put_cpu(). Here vmbus_connect() sends a message to the host and waits for the host's response. The host will deliver the response message and an interrupt on CPU msg->target_vcpu, and later the interrupt handler will wake up vmbus_connect(). vmbus_connect() doesn't really have to run on the same cpu as CPU msg->target_vcpu, so it's safe to call put_cpu() just here. Signed-off-by: Dexuan Cui Cc: sta...@vger.kernel.org Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/connection.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index ced041899456..f4d08c8ac7f8 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -76,6 +76,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, __u32 version) { int ret = 0; + unsigned int cur_cpu; struct vmbus_channel_initiate_contact *msg; unsigned long flags; @@ -118,9 +119,10 @@ 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_cpu_number_to_vp_number(smp_processor_id()); - vmbus_connection.connect_cpu = smp_processor_id(); + cur_cpu = get_cpu(); + msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu); + vmbus_connection.connect_cpu = cur_cpu; + put_cpu(); } else { msg->target_vcpu = 0; vmbus_connection.connect_cpu = 0; -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/2] tools: hv: fcopy: set 'error' in case an unknown operation was requested
From: Vitaly Kuznetsov 'error' variable is left uninitialized in case we see an unknown operation. As we don't immediately return and proceed to pwrite() we need to set it to something, HV_E_FAIL sounds good enough. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_fcopy_daemon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index d78aed86af09..8ff8cb1a11f4 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c @@ -234,6 +234,7 @@ int main(int argc, char *argv[]) break; default: + error = HV_E_FAIL; syslog(LOG_ERR, "Unknown operation: %d", buffer.hdr.operation); -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/2] Drivers: hv: Miscellaneous fixes
From: "K. Y. Srinivasan" Some miscellaneous fixes. Dexuan Cui (1): Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect() Vitaly Kuznetsov (1): tools: hv: fcopy: set 'error' in case an unknown operation was requested drivers/hv/connection.c| 8 +--- tools/hv/hv_fcopy_daemon.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] vmbus: don't return values for uninitalized channels
From: Stephen Hemminger For unsupported device types, the vmbus channel ringbuffer is never initialized, and therefore reading the sysfs files will return garbage or cause a kernel OOPS. Fixes: c2e5df616e1a ("vmbus: add per-channel sysfs info") Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Cc: # 4.15 --- drivers/hv/vmbus_drv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e6d8fdac6d8b..4bbc420d1213 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1368,6 +1368,9 @@ static ssize_t vmbus_chan_attr_show(struct kobject *kobj, if (!attribute->show) return -EIO; + if (chan->state != CHANNEL_OPENED_STATE) + return -EINVAL; + return attribute->show(chan, buf); } -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/5] uio_hv_generic: drop #ifdef DEBUG
From: Stephen Hemminger DEBUG is leftover from the development phase, remove it. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/uio/uio_hv_generic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c index 35678d08d9d8..ab0c0e7e8a44 100644 --- a/drivers/uio/uio_hv_generic.c +++ b/drivers/uio/uio_hv_generic.c @@ -19,7 +19,6 @@ * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \ *> /sys/bus/vmbus/drivers/uio_hv_generic/bind */ -#define DEBUG 1 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/5] Tools: hv: Fix a bug in the key delete code
From: "K. Y. Srinivasan" Fix a bug in the key delete code - the num_records range from 0 to num_records-1. Signed-off-by: K. Y. Srinivasan Reported-by: David Binderman Cc: --- tools/hv/hv_kvp_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index dbf6e8bd98ba..bbb2a8ef367c 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -286,7 +286,7 @@ static int kvp_key_delete(int pool, const __u8 *key, int key_size) * Found a match; just move the remaining * entries up. */ - if (i == num_records) { + if (i == (num_records - 1)) { kvp_file_info[pool].num_records--; kvp_update_file(pool); return 0; -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 5/5] Drivers: hv: vmbus: Fix synic per-cpu context initialization
From: Michael Kelley If hv_synic_alloc() errors out, the state of the per-cpu context for some CPUs is unknown since the zero'ing is done as each CPU is iterated over. In such case, hv_synic_cleanup() may try to free memory based on uninitialized values. Fix this by zero'ing the per-cpu context for all CPUs before doing any memory allocations that might fail. Signed-off-by: Michael Kelley Reported-by: Dan Carpenter Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 748a1c4172a6..332d7c34be5c 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -189,6 +189,17 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu) int hv_synic_alloc(void) { int cpu; + struct hv_per_cpu_context *hv_cpu; + + /* +* First, zero all per-cpu memory areas so hv_synic_free() can +* detect what memory has been allocated and cleanup properly +* after any failures. +*/ + for_each_present_cpu(cpu) { + hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); + memset(hv_cpu, 0, sizeof(*hv_cpu)); + } hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask), GFP_KERNEL); @@ -198,10 +209,8 @@ int hv_synic_alloc(void) } for_each_present_cpu(cpu) { - struct hv_per_cpu_context *hv_cpu - = per_cpu_ptr(hv_context.cpu_context, cpu); + hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - memset(hv_cpu, 0, sizeof(*hv_cpu)); tasklet_init(&hv_cpu->msg_dpc, vmbus_on_msg_dpc, (unsigned long) hv_cpu); -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/5] vmbus: add driver_override support
From: Stephen Hemminger Add support for overriding the default driver for a VMBus device in the same way that it can be done for PCI devices. This patch adds the /sys/bus/vmbus/devices/.../driver_override file and the logic for matching. This is used by driverctl tool to do driver override. https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.com%2Fdriverctl%2Fdriverctl&data=02%7C01%7Ckys%40microsoft.com%7C42e803feb2c544ef6ea908d5fd538878%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636693457619960040&sdata=kEyYHRIjNZCk%2B37moCSqbrZL426YccNQrsWpENcrZdw%3D&reserved=0 Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- Documentation/ABI/testing/sysfs-bus-vmbus | 21 drivers/hv/vmbus_drv.c| 115 ++ include/linux/hyperv.h| 1 + 3 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus diff --git a/Documentation/ABI/testing/sysfs-bus-vmbus b/Documentation/ABI/testing/sysfs-bus-vmbus new file mode 100644 index ..91e6c065973c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-vmbus @@ -0,0 +1,21 @@ +What: /sys/bus/vmbus/devices/.../driver_override +Date: August 2019 +Contact: Stephen Hemminger +Description: + This file allows the driver for a device to be specified which + will override standard static and dynamic ID matching. When + specified, only a driver with a name matching the value written + to driver_override will have an opportunity to bind to the + device. The override is specified by writing a string to the + driver_override file (echo uio_hv_generic > driver_override) and + may be cleared with an empty string (echo > driver_override). + This returns the device to standard matching rules binding. + Writing to driver_override does not automatically unbind the + device from its current driver or make any attempt to + automatically load the specified driver. If no driver with a + matching name is currently loaded in the kernel, the device + will not bind to any driver. This also allows devices to + opt-out of driver binding using a driver_override name such as + "none". Only a single driver may be specified in the override, + there is no support for parsing delimiters. + diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index b1b548a21f91..e6d8fdac6d8b 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev, } static DEVICE_ATTR_RO(device); +static ssize_t driver_override_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + char *driver_override, *old, *cp; + + /* We need to keep extra room for a newline */ + if (count >= (PAGE_SIZE - 1)) + return -EINVAL; + + driver_override = kstrndup(buf, count, GFP_KERNEL); + if (!driver_override) + return -ENOMEM; + + cp = strchr(driver_override, '\n'); + if (cp) + *cp = '\0'; + + device_lock(dev); + old = hv_dev->driver_override; + if (strlen(driver_override)) { + hv_dev->driver_override = driver_override; + } else { + kfree(driver_override); + hv_dev->driver_override = NULL; + } + device_unlock(dev); + + kfree(old); + + return count; +} + +static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + ssize_t len; + + device_lock(dev); + len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override); + device_unlock(dev); + + return len; +} +static DEVICE_ATTR_RW(driver_override); + /* Set up per device attributes in /sys/bus/vmbus/devices/ */ static struct attribute *vmbus_dev_attrs[] = { &dev_attr_id.attr, @@ -528,6 +576,7 @@ static struct attribute *vmbus_dev_attrs[] = { &dev_attr_channel_vp_mapping.attr, &dev_attr_vendor.attr, &dev_attr_device.attr, + &dev_attr_driver_override.attr, NULL, }; ATTRIBUTE_GROUPS(vmbus_dev); @@ -563,17 +612,26 @@ static inline bool is_null_guid(const uuid_le *guid) return true; } -/* - * Return a matching hv_vmbus_device_id pointer. - * If there is no match, return NULL. - */ -static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv, - const uuid_le *guid) +static const struct hv_vmbus_d
[PATCH 3/5] uio_hv_generic: increase size of receive and send buffers
From: Stephen Hemminger When using DPDK there is significant performance boost by using the largest possible send and receive buffer area. Unfortunately, with UIO model there is not a good way to configure this at run time. But it is okay to have a bigger buffer available even if application only decides to use a smaller piece of it. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/uio/uio_hv_generic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c index c690d100adcd..35678d08d9d8 100644 --- a/drivers/uio/uio_hv_generic.c +++ b/drivers/uio/uio_hv_generic.c @@ -35,13 +35,13 @@ #include "../hv/hyperv_vmbus.h" -#define DRIVER_VERSION "0.02.0" +#define DRIVER_VERSION "0.02.1" #define DRIVER_AUTHOR "Stephen Hemminger " #define DRIVER_DESC"Generic UIO driver for VMBus devices" #define HV_RING_SIZE512/* pages */ -#define SEND_BUFFER_SIZE (15 * 1024 * 1024) -#define RECV_BUFFER_SIZE (15 * 1024 * 1024) +#define SEND_BUFFER_SIZE (16 * 1024 * 1024) +#define RECV_BUFFER_SIZE (31 * 1024 * 1024) /* * List of resources to be mapped to user space -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/5] Miscellaneous fixes/enhancements
From: "K. Y. Srinivasan" Miscellaneous fixes/enhancements. K. Y. Srinivasan (1): Tools: hv: Fix a bug in the key delete code Michael Kelley (1): Drivers: hv: vmbus: Fix synic per-cpu context initialization Stephen Hemminger (3): vmbus: add driver_override support uio_hv_generic: increase size of receive and send buffers uio_hv_generic: drop #ifdef DEBUG Documentation/ABI/testing/sysfs-bus-vmbus | 21 drivers/hv/hv.c | 15 ++- drivers/hv/vmbus_drv.c| 115 ++ drivers/uio/uio_hv_generic.c | 7 +- include/linux/hyperv.h| 1 + tools/hv/hv_kvp_daemon.c | 2 +- 6 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus -- 2.18.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path
From: Michael Kelley clk_evt memory is not being freed when the synic is shutdown or when there is an allocation error. Add the appropriate kfree() call, along with a comment to clarify how the memory gets freed after an allocation error. Make the free path consistent by removing checks for NULL since kfree() and free_page() already do the check. Signed-off-by: Michael Kelley Reported-by: Dan Carpenter Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 312fe5ed7c40..748a1c4172a6 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -242,6 +242,10 @@ int hv_synic_alloc(void) return 0; err: + /* +* Any memory allocations that succeeded will be freed when +* the caller cleans up by calling hv_synic_free() +*/ return -ENOMEM; } @@ -254,12 +258,10 @@ void hv_synic_free(void) struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - if (hv_cpu->synic_event_page) - free_page((unsigned long)hv_cpu->synic_event_page); - if (hv_cpu->synic_message_page) - free_page((unsigned long)hv_cpu->synic_message_page); - if (hv_cpu->post_msg_page) - free_page((unsigned long)hv_cpu->post_msg_page); + kfree(hv_cpu->clk_evt); + free_page((unsigned long)hv_cpu->synic_event_page); + free_page((unsigned long)hv_cpu->synic_message_page); + free_page((unsigned long)hv_cpu->post_msg_page); } kfree(hv_context.hv_numa_map); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys()
From: Michael Kelley slow_virt_to_phys() is only implemented for arch/x86. Remove its use in arch independent Hyper-V drivers, and replace with test for vmalloc() address followed by appropriate v-to-p function. This follows the typical pattern of other drivers and avoids the need to implement slow_virt_to_phys() for Hyper-V on ARM64. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel.c | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index c3949220b770..741857d80da1 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -29,12 +29,26 @@ #include #include #include +#include #include "hyperv_vmbus.h" #define NUM_PAGES_SPANNED(addr, len) \ ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT)) +static unsigned long virt_to_hvpfn(void *addr) +{ + unsigned long paddr; + + if (is_vmalloc_addr(addr)) + paddr = page_to_phys(vmalloc_to_page(addr)) + +offset_in_page(addr); + else + paddr = __pa(addr); + + return paddr >> PAGE_SHIFT; +} + /* * vmbus_setevent- Trigger an event notification on the specified * channel. @@ -298,8 +312,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, gpadl_header->range[0].byte_offset = 0; gpadl_header->range[0].byte_count = size; for (i = 0; i < pfncount; i++) - gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; + gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * i); *msginfo = msgheader; pfnsum = pfncount; @@ -350,9 +364,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, * so the hypervisor guarantees that this is ok. */ for (i = 0; i < pfncurr; i++) - gpadl_body->pfn[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * (pfnsum + i)) >> - PAGE_SHIFT; + gpadl_body->pfn[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * (pfnsum + i)); /* add to msg header */ list_add_tail(&msgbody->msglistentry, @@ -380,8 +393,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, gpadl_header->range[0].byte_offset = 0; gpadl_header->range[0].byte_count = size; for (i = 0; i < pagecount; i++) - gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; + gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * i); *msginfo = msgheader; } -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind()
From: Dexuan Cui Before setting channel->rescind in vmbus_rescind_cleanup(), we should make sure the channel callback won't run any more, otherwise a high-level driver like pci_hyperv, which may be infinitely waiting for the host VSP's response and notices the channel has been rescinded, can't safely give up: e.g., in hv_pci_protocol_negotiation() -> wait_for_response(), it's unsafe to exit from wait_for_response() and proceed with the on-stack variable "comp_pkt" popped. The issue was originally spotted by Michael Kelley . In vmbus_close_internal(), the patch also minimizes the range protected by disabling/enabling channel->callback_event: we don't really need that for the whole function. Signed-off-by: Dexuan Cui Reviewed-by: Michael Kelley Cc: sta...@vger.kernel.org Cc: K. Y. Srinivasan Cc: Stephen Hemminger Cc: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel.c | 40 +++ drivers/hv/channel_mgmt.c | 6 ++ include/linux/hyperv.h| 2 ++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index ba0a092ae085..c3949220b770 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -558,11 +558,8 @@ static void reset_channel_cb(void *arg) channel->onchannel_callback = NULL; } -static int vmbus_close_internal(struct vmbus_channel *channel) +void vmbus_reset_channel_cb(struct vmbus_channel *channel) { - struct vmbus_channel_close_channel *msg; - int ret; - /* * vmbus_on_event(), running in the per-channel tasklet, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when @@ -572,6 +569,29 @@ static int vmbus_close_internal(struct vmbus_channel *channel) */ tasklet_disable(&channel->callback_event); + channel->sc_creation_callback = NULL; + + /* Stop the callback asap */ + if (channel->target_cpu != get_cpu()) { + put_cpu(); + smp_call_function_single(channel->target_cpu, reset_channel_cb, +channel, true); + } else { + reset_channel_cb(channel); + put_cpu(); + } + + /* Re-enable tasklet for use on re-open */ + tasklet_enable(&channel->callback_event); +} + +static int vmbus_close_internal(struct vmbus_channel *channel) +{ + struct vmbus_channel_close_channel *msg; + int ret; + + vmbus_reset_channel_cb(channel); + /* * In case a device driver's probe() fails (e.g., * util_probe() -> vmbus_open() returns -ENOMEM) and the device is @@ -585,16 +605,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) } channel->state = CHANNEL_OPEN_STATE; - channel->sc_creation_callback = NULL; - /* Stop callback and cancel the timer asap */ - if (channel->target_cpu != get_cpu()) { - put_cpu(); - smp_call_function_single(channel->target_cpu, reset_channel_cb, -channel, true); - } else { - reset_channel_cb(channel); - put_cpu(); - } /* Send a closing message */ @@ -639,8 +649,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); out: - /* re-enable tasklet for use on re-open */ - tasklet_enable(&channel->callback_event); return ret; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index f3b551a50653..0f0e091c117c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -892,6 +892,12 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } + /* +* Before setting channel->rescind in vmbus_rescind_cleanup(), we +* should make sure the channel callback is not running any more. +*/ + vmbus_reset_channel_cb(channel); + /* * Now wait for offer handling to complete. */ diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 2330f08062c7..efda23cf32c7 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1061,6 +1061,8 @@ extern int vmbus_establish_gpadl(struct vmbus_channel *channel, extern int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle); +void vmbus_reset_channel_cb(struct vmbus_channel *channel); + extern int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, u32 bufferlen, -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. Dexuan Cui (1): Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() Michael Kelley (2): Drivers: hv: vmbus: Remove use of slow_virt_to_phys() Drivers: hv: vmbus: Cleanup synic memory free path drivers/hv/channel.c | 67 +-- drivers/hv/channel_mgmt.c | 6 drivers/hv/hv.c | 14 include/linux/hyperv.h| 2 ++ 4 files changed, 60 insertions(+), 29 deletions(-) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/4] Drivers: hv: vmbus: add numa_node to sysfs
From: Stephen Hemminger Being able to find the numa_node for a device is useful for userspace drivers (DPDK) and also for diagnosing performance issues. This makes vmbus similar to pci. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- Documentation/ABI/stable/sysfs-bus-vmbus | 7 +++ drivers/hv/vmbus_drv.c | 17 + 2 files changed, 24 insertions(+) diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 3eaffbb2d468..3fed8fdb873d 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -42,6 +42,13 @@ Contact: K. Y. Srinivasan Description: The 16 bit vendor ID of the device Users: tools/hv/lsvmbus and user level RDMA libraries +What: /sys/bus/vmbus/devices//numa_node +Date: Jul 2018 +KernelVersion: 4.19 +Contact: Stephen Hemminger +Description: This NUMA node to which the VMBUS device is + attached, or -1 if the node is unknown. + What: /sys/bus/vmbus/devices//channels/ Date: September. 2017 KernelVersion: 4.14 diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index db145e1a7049..b1b548a21f91 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -210,6 +210,20 @@ static ssize_t modalias_show(struct device *dev, } static DEVICE_ATTR_RO(modalias); +#ifdef CONFIG_NUMA +static ssize_t numa_node_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hv_device *hv_dev = device_to_hv_device(dev); + + if (!hv_dev->channel) + return -ENODEV; + + return sprintf(buf, "%d\n", hv_dev->channel->numa_node); +} +static DEVICE_ATTR_RO(numa_node); +#endif + static ssize_t server_monitor_pending_show(struct device *dev, struct device_attribute *dev_attr, char *buf) @@ -492,6 +506,9 @@ static struct attribute *vmbus_dev_attrs[] = { &dev_attr_class_id.attr, &dev_attr_device_id.attr, &dev_attr_modalias.attr, +#ifdef CONFIG_NUMA + &dev_attr_numa_node.attr, +#endif &dev_attr_server_monitor_pending.attr, &dev_attr_client_monitor_pending.attr, &dev_attr_server_monitor_latency.attr, -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/4] Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr
From: Sunil Muthuswamy The check to free the Hyper-V control table header was reversed. This fixes it. Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") Signed-off-by: Sunil Muthuswamy Signed-off-by: K. Y. Srinivasan --- drivers/hv/vmbus_drv.c | 14 -- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a7f33c1f42c5..5e946b1be54c 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1176,11 +1176,8 @@ static int vmbus_bus_init(void) bus_unregister(&hv_bus); free_page((unsigned long)hv_panic_page); - if (!hv_ctl_table_hdr) { - unregister_sysctl_table(hv_ctl_table_hdr); - hv_ctl_table_hdr = NULL; - } - + unregister_sysctl_table(hv_ctl_table_hdr); + hv_ctl_table_hdr = NULL; return ret; } @@ -1891,11 +1888,8 @@ static void __exit vmbus_exit(void) } free_page((unsigned long)hv_panic_page); - if (!hv_ctl_table_hdr) { - unregister_sysctl_table(hv_ctl_table_hdr); - hv_ctl_table_hdr = NULL; - } - + unregister_sysctl_table(hv_ctl_table_hdr); + hv_ctl_table_hdr = NULL; bus_unregister(&hv_bus); cpuhp_remove_state(hyperv_cpuhp_online); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/4] Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c
From: Sunil Muthuswamy Get rid of ISA specific code from vmus_drv.c which is common code. Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") Signed-off-by: Sunil Muthuswamy Signed-off-by: K. Y. Srinivasan --- arch/x86/include/asm/mshyperv.h | 3 +++ drivers/hv/vmbus_drv.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 156a2e5a97a9..b731c4bf70ed 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -96,6 +96,9 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) #define hv_set_synint_state(int_num, val) \ wrmsrl(HV_X64_MSR_SINT0 + int_num, val) +#define hv_get_crash_ctl(val) \ + rdmsrl(HV_X64_MSR_CRASH_CTL, val) + void hyperv_callback_vector(void); void hyperv_reenlightenment_vector(void); #ifdef CONFIG_TRACING diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 5e946b1be54c..db145e1a7049 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1146,7 +1146,7 @@ static int vmbus_bus_init(void) * Register for panic kmsg callback only if the right * capability is supported by the hypervisor. */ - rdmsrl(HV_X64_MSR_CRASH_CTL, hyperv_crash_ctl); + hv_get_crash_ctl(hyperv_crash_ctl); if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG) { hv_panic_page = (void *)get_zeroed_page(GFP_KERNEL); if (hv_panic_page) { -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/4] Drivers: hv: vmus: Fix the check for return value from kmsg get dump buffer
From: Sunil Muthuswamy The code to support panic control message was checking the return was checking the return value from kmsg_dump_get_buffer as error value, which is not what the routine returns. This fixes it. Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic") Signed-off-by: Sunil Muthuswamy Signed-off-by: K. Y. Srinivasan --- drivers/hv/vmbus_drv.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 05e37283d7c3..a7f33c1f42c5 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1047,13 +1047,10 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper, * Write dump contents to the page. No need to synchronize; panic should * be single-threaded. */ - if (!kmsg_dump_get_buffer(dumper, true, hv_panic_page, - PAGE_SIZE, &bytes_written)) { - pr_err("Hyper-V: Unable to get kmsg data for panic\n"); - return; - } - - hyperv_report_panic_msg(panic_pa, bytes_written); + kmsg_dump_get_buffer(dumper, true, hv_panic_page, PAGE_SIZE, +&bytes_written); + if (bytes_written) + hyperv_report_panic_msg(panic_pa, bytes_written); } static struct kmsg_dumper hv_kmsg_dumper = { -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/4] Drivers: hv: vmbus: Miscellaneous fixes/enhancements
From: "K. Y. Srinivasan" Miscellaneous fixes/enhancements Stephen Hemminger (1): Drivers: hv: vmbus: add numa_node to sysfs Sunil Muthuswamy (3): Drivers: hv: vmus: Fix the check for return value from kmsg get dump buffer Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c Documentation/ABI/stable/sysfs-bus-vmbus | 7 arch/x86/include/asm/mshyperv.h | 3 ++ drivers/hv/vmbus_drv.c | 44 ++-- 3 files changed, 36 insertions(+), 18 deletions(-) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/1] x86/hyper-v: Fix a merge error
From: "K. Y. Srinivasan" When the mapping betwween the Linux notion of CPU ID to the hypervisor's notion of CPU ID is not initialized, we should fall back on the non-enligghtened path for IPI. A merge error introduced this bug; fix it. Fixes: 1268ed0c474a ("Merge branch 'x86/urgent' into x86/hyperv") Reported-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 0c3c9f8fee77..5b0f613428c2 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -168,7 +168,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector) for_each_cpu(cur_cpu, mask) { vcpu = hv_cpu_number_to_vp_number(cur_cpu); if (vcpu == VP_INVAL) - return true; + return false; /* * This particular version of the IPI hypercall can -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/1] Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic
From: Sunil Muthuswamy In the VM mode on Hyper-V, currently, when the kernel panics, an error code and few register values are populated in an MSR and the Hypervisor notified. This information is collected on the host. The amount of information currently collected is found to be limited and not very actionable. To gather more actionable data, such as stack trace, the proposal is to write one page worth of kmsg data on an allocated page and the Hypervisor notified of the page address through the MSR. - Sysctl option to control the behavior, with ON by default. Cc: K. Y. Srinivasan Cc: Stephen Hemminger Signed-off-by: Sunil Muthuswamy Signed-off-by: K. Y. Srinivasan --- Documentation/sysctl/kernel.txt| 11 +++ arch/x86/hyperv/hv_init.c | 27 +++ arch/x86/include/asm/hyperv-tlfs.h | 5 +- arch/x86/include/asm/mshyperv.h| 1 + drivers/hv/vmbus_drv.c | 110 + 5 files changed, 152 insertions(+), 2 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index eded671d55eb..59585030cbaf 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -39,6 +39,7 @@ show up in /proc/sys/kernel: - hung_task_check_count - hung_task_timeout_secs - hung_task_warnings +- hyperv_record_panic_msg - kexec_load_disabled - kptr_restrict - l2cr[ PPC only ] @@ -374,6 +375,16 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled. == +hyperv_record_panic_msg: + +Controls whether the panic kmsg data should be reported to Hyper-V. + +0: do not report panic kmsg data. + +1: report the panic kmsg data. This is the default behavior. + +== + kexec_load_disabled: A toggle indicating if the kexec_load syscall has been disabled. This diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 595e44e8abaa..9c70018a9906 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -423,6 +423,33 @@ void hyperv_report_panic(struct pt_regs *regs, long err) } EXPORT_SYMBOL_GPL(hyperv_report_panic); +/** + * hyperv_report_panic_msg - report panic message to Hyper-V + * @pa: physical address of the panic page containing the message + * @size: size of the message in the page + */ +void hyperv_report_panic_msg(phys_addr_t pa, size_t size) +{ + /* +* P3 to contain the physical address of the panic page & P4 to +* contain the size of the panic data in that page. Rest of the +* registers are no-op when the NOTIFY_MSG flag is set. +*/ + wrmsrl(HV_X64_MSR_CRASH_P0, 0); + wrmsrl(HV_X64_MSR_CRASH_P1, 0); + wrmsrl(HV_X64_MSR_CRASH_P2, 0); + wrmsrl(HV_X64_MSR_CRASH_P3, pa); + wrmsrl(HV_X64_MSR_CRASH_P4, size); + + /* +* Let Hyper-V know there is crash data available along with +* the panic message. +*/ + wrmsrl(HV_X64_MSR_CRASH_CTL, + (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG)); +} +EXPORT_SYMBOL_GPL(hyperv_report_panic_msg); + bool hv_is_hyperv_initialized(void) { union hv_x64_msr_hypercall_contents hypercall_msr; diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 96272e99b64e..6ced78af48da 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -176,9 +176,10 @@ #define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED(1 << 14) /* - * Crash notification flag. + * Crash notification flags. */ -#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63) +#define HV_CRASH_CTL_CRASH_NOTIFY_MSG BIT_ULL(62) +#define HV_CRASH_CTL_CRASH_NOTIFY BIT_ULL(63) /* MSR used to identify the guest OS. */ #define HV_X64_MSR_GUEST_OS_ID 0x4000 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 81e768b8d9eb..156a2e5a97a9 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -299,6 +299,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); void hyperv_report_panic(struct pt_regs *regs, long err); +void hyperv_report_panic_msg(phys_addr_t pa, size_t size); bool hv_is_hyperv_initialized(void); void hyperv_cleanup(void); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index b10fe26c4891..05e37283d7c3 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -56,6 +56,8 @@ static struct completion probe_event; static int hyperv_cpuhp_online; +static void *hv_panic_page; + static int hyperv_panic_event(struct notifier_block *nb, unsigned long val, void *args) { @@ -1018,6 +1020,75 @@ static void vmbus_isr(void) add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); } +/* + * Boolean to control whether to report
[PATCH 1/1] X86/Hyper-V:: Fix the circular dependency in IPI enlightenment.
From: "K. Y. Srinivasan" The IPI hypercalls depend on being able to map the Linux notion of CPU ID to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides this mapping. Code for populating this array depends on the IPI functionality. Break this circular dependency. Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments") Signed-off-by: K. Y. Srinivasan Tested-by: Michael Kelley --- arch/x86/hyperv/hv_apic.c | 5 + arch/x86/hyperv/hv_init.c | 5 - arch/x86/include/asm/mshyperv.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index f68855499391..63d7c196739f 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector) ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); } + if (nr_bank == -1) + goto ipi_mask_ex_done; if (!nr_bank) ipi_arg->vp_set.format = HV_GENERIC_SET_ALL; @@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector) for_each_cpu(cur_cpu, mask) { vcpu = hv_cpu_number_to_vp_number(cur_cpu); + if (vcpu == -1) + goto ipi_mask_done; + /* * This particular version of the IPI hypercall can * only target upto 64 CPUs. diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 4c431e1c1eff..04159893702e 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -265,7 +265,7 @@ void __init hyperv_init(void) { u64 guest_id, required_msrs; union hv_x64_msr_hypercall_contents hypercall_msr; - int cpuhp; + int cpuhp, i; if (x86_hyper_type != X86_HYPER_MS_HYPERV) return; @@ -293,6 +293,9 @@ void __init hyperv_init(void) if (!hv_vp_index) return; + for (i = 0; i < num_possible_cpus(); i++) + hv_vp_index[i] = -1; + hv_vp_assist_page = kcalloc(num_possible_cpus(), sizeof(*hv_vp_assist_page), GFP_KERNEL); if (!hv_vp_assist_page) { diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 3cd14311edfa..dee3f7347253 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -281,6 +281,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, */ for_each_cpu(cpu, cpus) { vcpu = hv_cpu_number_to_vp_number(cpu); + if (vcpu == -1) + return -1; vcpu_bank = vcpu / 64; vcpu_offset = vcpu % 64; __set_bit(vcpu_offset, (unsigned long *) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/1] X86: Fix the circular dependency in IPI enlightenment.
From: "K. Y. Srinivasan" The IPI hypercalls depend on being able to map the Linux notion of CPU ID to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides this mapping. Code for populating this array depends on the IPI functionality. Break this circular dependency. Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments") Signed-off-by: K. Y. Srinivasan Tested-by: Michael Kelley --- arch/x86/hyperv/hv_apic.c | 5 + arch/x86/hyperv/hv_init.c | 3 +++ arch/x86/include/asm/mshyperv.h | 2 ++ 3 files changed, 10 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index f68855499391..63d7c196739f 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector) ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); } + if (nr_bank == -1) + goto ipi_mask_ex_done; if (!nr_bank) ipi_arg->vp_set.format = HV_GENERIC_SET_ALL; @@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector) for_each_cpu(cur_cpu, mask) { vcpu = hv_cpu_number_to_vp_number(cur_cpu); + if (vcpu == -1) + goto ipi_mask_done; + /* * This particular version of the IPI hypercall can * only target upto 64 CPUs. diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 595e44e8abaa..762ce164d733 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -293,6 +293,9 @@ void __init hyperv_init(void) if (!hv_vp_index) return; + for (i = 0; i < num_possible_cpus(); i++) + hv_vp_index[i] = -1; + hv_vp_assist_page = kcalloc(num_possible_cpus(), sizeof(*hv_vp_assist_page), GFP_KERNEL); if (!hv_vp_assist_page) { diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 81e768b8d9eb..299de3dcc319 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -285,6 +285,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, */ for_each_cpu(cpu, cpus) { vcpu = hv_cpu_number_to_vp_number(cpu); + if (vcpu == -1) + return -1; vcpu_bank = vcpu / 64; vcpu_offset = vcpu % 64; __set_bit(vcpu_offset, (unsigned long *) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/8] Drivers: hv: vmbus: Fix the offer_in_progress in vmbus_process_offer()
From: Dexuan Cui I didn't really hit a real bug, but just happened to spot the bug: we have decreased the counter at the beginning of vmbus_process_offer(), so we mustn't decrease it again. Fixes: 6f3d791f3006 ("Drivers: hv: vmbus: Fix rescind handling issues") Signed-off-by: Dexuan Cui Cc: sta...@vger.kernel.org Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Stable # 4.14 and above Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index ecc2bd275a73..f3b551a50653 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -527,10 +527,8 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) struct hv_device *dev = newchannel->primary_channel->device_obj; - if (vmbus_add_channel_kobj(dev, newchannel)) { - atomic_dec(&vmbus_connection.offer_in_progress); + if (vmbus_add_channel_kobj(dev, newchannel)) goto err_free_chan; - } if (channel->sc_creation_callback != NULL) channel->sc_creation_callback(newchannel); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/8] Drivers: hv: vmbus: Add comments on ring buffer signaling
From: Michael Kelley Add comments describing intricacies of Hyper-V ring buffer signaling code. This information is not in Hyper-V public documents, so include here to capture the knowledge for future coders. There are no code changes in this commit. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/ring_buffer.c | 65 +--- include/linux/hyperv.h | 31 ++- 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 8699bb969e7e..ce6ea6dad490 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -429,7 +429,24 @@ static u32 hv_pkt_iter_bytes_read(const struct hv_ring_buffer_info *rbi, } /* - * Update host ring buffer after iterating over packets. + * Update host ring buffer after iterating over packets. If the host has + * stopped queuing new entries because it found the ring buffer full, and + * sufficient space is being freed up, signal the host. But be careful to + * only signal the host when necessary, both for performance reasons and + * because Hyper-V protects itself by throttling guests that signal + * inappropriately. + * + * Determining when to signal is tricky. There are three key data inputs + * that must be handled in this order to avoid race conditions: + * + * 1. Update the read_index + * 2. Read the pending_send_sz + * 3. Read the current write_index + * + * The interrupt_mask is not used to determine when to signal. The + * interrupt_mask is used only on the guest->host ring buffer when + * sending requests to the host. The host does not use it on the host-> + * guest ring buffer to indicate whether it should be signaled. */ void hv_pkt_iter_close(struct vmbus_channel *channel) { @@ -445,22 +462,30 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) start_read_index = rbi->ring_buffer->read_index; rbi->ring_buffer->read_index = rbi->priv_read_index; + /* +* Older versions of Hyper-V (before WS2102 and Win8) do not +* implement pending_send_sz and simply poll if the host->guest +* ring buffer is full. No signaling is needed or expected. +*/ if (!rbi->ring_buffer->feature_bits.feat_pending_send_sz) return; /* * Issue a full memory barrier before making the signaling decision. -* Here is the reason for having this barrier: -* If the reading of the pend_sz (in this function) -* were to be reordered and read before we commit the new read -* index (in the calling function) we could -* have a problem. If the host were to set the pending_sz after we -* have sampled pending_sz and go to sleep before we commit the +* If reading pending_send_sz were to be reordered and happen +* before we commit the new read_index, a race could occur. If the +* host were to set the pending_send_sz after we have sampled +* pending_send_sz, and the ring buffer blocks before we commit the * read index, we could miss sending the interrupt. Issue a full * memory barrier to address this. */ virt_mb(); + /* +* If the pending_send_sz is zero, then the ring buffer is not +* blocked and there is no need to signal. This is far by the +* most common case, so exit quickly for best performance. +*/ pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); if (!pending_sz) return; @@ -474,14 +499,32 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) bytes_read = hv_pkt_iter_bytes_read(rbi, start_read_index); /* -* If there was space before we began iteration, -* then host was not blocked. +* We want to signal the host only if we're transitioning +* from a "not enough free space" state to a "enough free +* space" state. For example, it's possible that this function +* could run and free up enough space to signal the host, and then +* run again and free up additional space before the host has a +* chance to clear the pending_send_sz. The 2nd invocation would +* be a null transition from "enough free space" to "enough free +* space", which doesn't warrant a signal. +* +* Exactly filling the ring buffer is treated as "not enough +* space". The ring buffer always must have at least one byte +* empty so the empty and full conditions are distinguishable. +* hv_get_bytes_to_write() doesn't fully tell the truth in +* this regard. +* +* So first check if we were in the "enough free space" state +* before we began the iteration. If so, the host was not +* blocked, and there's no need to signal. */ - if (curr_write_sz - bytes_read > pending_sz) return; - /
[PATCH 7/8] tools: hv: update lsvmbus to be compatible with python3
From: Olaf Hering Python3 changed the way how 'print' works. Adjust the code to a syntax that is understood by python2 and python3. Signed-off-by: Olaf Hering Acked-by: Dexuan Cui Signed-off-by: K. Y. Srinivasan --- tools/hv/lsvmbus | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus index 353e56768df8..55e7374bade0 100644 --- a/tools/hv/lsvmbus +++ b/tools/hv/lsvmbus @@ -17,7 +17,7 @@ if options.verbose is not None: vmbus_sys_path = '/sys/bus/vmbus/devices' if not os.path.isdir(vmbus_sys_path): - print "%s doesn't exist: exiting..." % vmbus_sys_path + print("%s doesn't exist: exiting..." % vmbus_sys_path) exit(-1) vmbus_dev_dict = { @@ -93,11 +93,11 @@ format2 = '%2s: Class_ID = %s - %s\n\tDevice_ID = %s\n\tSysfs path: %s\n%s' for d in vmbus_dev_list: if verbose == 0: - print ('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc) + print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc)) elif verbose == 1: - print ('VMBUS ID ' + format1) % \ - (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping) + print (('VMBUS ID ' + format1) %\ + (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)) else: - print ('VMBUS ID ' + format2) % \ + print (('VMBUS ID ' + format2) % \ (d.vmbus_id, d.class_id, d.dev_desc, \ - d.device_id, d.sysfs_path, d.chn_vp_mapping) + d.device_id, d.sysfs_path, d.chn_vp_mapping)) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 5/8] Drivers: hv: vmbus: Remove x86 MSR refs in arch independent code
From: Michael Kelley In architecture independent code for manipulating Hyper-V synthetic timers and synthetic interrupts, pass in an ordinal number identifying the timer or interrupt, rather than an actual MSR register address. Then in x86/x64 specific code, map the ordinal number to the appropriate MSR. This change facilitates the introduction of an ARM64 version of Hyper-V, which uses the same synthetic timers and interrupts, but a different mechanism for accessing them. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/include/asm/mshyperv.h | 12 drivers/hv/hv.c | 20 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index b90e79610cf7..caf9035a2758 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -75,8 +75,10 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) } } -#define hv_init_timer(timer, tick) wrmsrl(timer, tick) -#define hv_init_timer_config(config, val) wrmsrl(config, val) +#define hv_init_timer(timer, tick) \ + wrmsrl(HV_X64_MSR_STIMER0_COUNT + (2*timer), tick) +#define hv_init_timer_config(timer, val) \ + wrmsrl(HV_X64_MSR_STIMER0_CONFIG + (2*timer), val) #define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val) #define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val) @@ -89,8 +91,10 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index) -#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val) -#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val) +#define hv_get_synint_state(int_num, val) \ + rdmsrl(HV_X64_MSR_SINT0 + int_num, val) +#define hv_set_synint_state(int_num, val) \ + wrmsrl(HV_X64_MSR_SINT0 + int_num, val) void hyperv_callback_vector(void); void hyperv_reenlightenment_vector(void); diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 9b82549cbbc8..96c403a07906 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -127,14 +127,14 @@ static int hv_ce_set_next_event(unsigned long delta, current_tick = hyperv_cs->read(NULL); current_tick += delta; - hv_init_timer(HV_X64_MSR_STIMER0_COUNT, current_tick); + hv_init_timer(0, current_tick); return 0; } static int hv_ce_shutdown(struct clock_event_device *evt) { - hv_init_timer(HV_X64_MSR_STIMER0_COUNT, 0); - hv_init_timer_config(HV_X64_MSR_STIMER0_CONFIG, 0); + hv_init_timer(0, 0); + hv_init_timer_config(0, 0); if (direct_mode_enabled) hv_disable_stimer0_percpu_irq(stimer0_irq); @@ -164,7 +164,7 @@ static int hv_ce_set_oneshot(struct clock_event_device *evt) timer_cfg.direct_mode = 0; timer_cfg.sintx = VMBUS_MESSAGE_SINT; } - hv_init_timer_config(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64); + hv_init_timer_config(0, timer_cfg.as_uint64); return 0; } @@ -298,8 +298,7 @@ int hv_synic_init(unsigned int cpu) hv_set_siefp(siefp.as_uint64); /* Setup the shared SINT. */ - hv_get_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, - shared_sint.as_uint64); + hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; shared_sint.masked = false; @@ -308,8 +307,7 @@ int hv_synic_init(unsigned int cpu) else shared_sint.auto_eoi = true; - hv_set_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, - shared_sint.as_uint64); + hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); /* Enable the global synic bit */ hv_get_synic_state(sctrl.as_uint64); @@ -405,15 +403,13 @@ int hv_synic_cleanup(unsigned int cpu) put_cpu_ptr(hv_cpu); } - hv_get_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, - shared_sint.as_uint64); + hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); shared_sint.masked = 1; /* Need to correctly cleanup in the case of SMP!!! */ /* Disable the interrupt */ - hv_set_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, - shared_sint.as_uint64); + hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); hv_get_simp(simp.as_uint64); simp.simp_enabled = 0; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/8] use the new async probing feature for the hyperv drivers
From: Arjan van de Ven Recent kernels support asynchronous probing; most hyperv drivers can be probed async easily so set the required flag for this. Signed-off-by: Arjan van de Ven Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hid/hid-hyperv.c | 3 +++ drivers/hv/hv_balloon.c | 3 +++ drivers/hv/hv_util.c | 3 +++ drivers/input/serio/hyperv-keyboard.c | 3 +++ drivers/net/hyperv/netvsc_drv.c | 3 +++ drivers/scsi/storvsc_drv.c| 3 +++ drivers/video/fbdev/hyperv_fb.c | 6 ++ 7 files changed, 24 insertions(+) diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 3aa2bb9f0f81..b372854cf38d 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -598,6 +598,9 @@ static struct hv_driver mousevsc_drv = { .id_table = id_table, .probe = mousevsc_probe, .remove = mousevsc_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int __init mousevsc_init(void) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index b3e9f13f8bc3..b1b788082793 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -1765,6 +1765,9 @@ static struct hv_driver balloon_drv = { .id_table = id_table, .probe = balloon_probe, .remove = balloon_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int __init init_balloon_drv(void) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 14dce25c104f..423205077bf6 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -487,6 +487,9 @@ static struct hv_driver util_drv = { .id_table = id_table, .probe = util_probe, .remove = util_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int hv_ptp_enable(struct ptp_clock_info *info, diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index 25151d9214e0..47a0e81a2989 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -424,6 +424,9 @@ static struct hv_driver hv_kbd_drv = { .id_table = id_table, .probe = hv_kbd_probe, .remove = hv_kbd_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int __init hv_kbd_init(void) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index ecc84954c511..3965c62e79ba 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -2155,6 +2155,9 @@ static struct hv_driver netvsc_drv = { .id_table = id_table, .probe = netvsc_probe, .remove = netvsc_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; /* diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 8c51d628b52e..32027ac60aa4 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1893,6 +1893,9 @@ static struct hv_driver storvsc_drv = { .id_table = id_table, .probe = storvsc_probe, .remove = storvsc_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 2fd49b2358f8..403d8cd3e582 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -912,6 +912,9 @@ static struct hv_driver hvfb_drv = { .id_table = id_table, .probe = hvfb_probe, .remove = hvfb_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int hvfb_pci_stub_probe(struct pci_dev *pdev, @@ -929,6 +932,9 @@ static struct pci_driver hvfb_pci_stub_driver = { .id_table = pci_stub_id_table, .probe =hvfb_pci_stub_probe, .remove = hvfb_pci_stub_remove, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + } }; static int __init hvfb_drv_init(void) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 8/8] Tools: hv: vss: fix loop device detection
From: Vitaly Kuznetsov Commit ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by loop") added skip for filesystems backed by loop device. However, it seems the detection of such cases is incomplete. It was found that with 'devicemapper' storage driver docker creates the following chain: NAMEMAJ:MIN loop0 7:0 ..docker-8:4-8473394-pool 253:0 ..docker-8:4-8473394-eac... 253:1 so when we're looking at the mounted device we see major '253' and not '7'. Solve the issue by walking /sys/dev/block/*/slaves chain and checking if there's a loop device somewhere. Other than that, don't skip mountpoints silently when stat() fails. In case e.g. SELinux is failing stat we don't want to skip freezing everything without letting user know about the failure. Fixes: ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by loop") Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_vss_daemon.c | 65 +--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 34031a297f02..b13300172762 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include /* Don't use syslog() in the function since that can cause write to disk */ static int vss_do_freeze(char *dir, unsigned int cmd) @@ -68,6 +70,55 @@ static int vss_do_freeze(char *dir, unsigned int cmd) return !!ret; } +static bool is_dev_loop(const char *blkname) +{ + char *buffer; + DIR *dir; + struct dirent *entry; + bool ret = false; + + buffer = malloc(PATH_MAX); + if (!buffer) { + syslog(LOG_ERR, "Can't allocate memory!"); + exit(1); + } + + snprintf(buffer, PATH_MAX, "%s/loop", blkname); + if (!access(buffer, R_OK | X_OK)) { + ret = true; + goto free_buffer; + } else if (errno != ENOENT) { + syslog(LOG_ERR, "Can't access: %s; error:%d %s!", + buffer, errno, strerror(errno)); + } + + snprintf(buffer, PATH_MAX, "%s/slaves", blkname); + dir = opendir(buffer); + if (!dir) { + if (errno != ENOENT) + syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!", + buffer, errno, strerror(errno)); + goto free_buffer; + } + + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + + snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname, +entry->d_name); + if (is_dev_loop(buffer)) { + ret = true; + break; + } + } + closedir(dir); +free_buffer: + free(buffer); + return ret; +} + static int vss_operate(int operation) { char match[] = "/dev/"; @@ -75,6 +126,7 @@ static int vss_operate(int operation) struct mntent *ent; struct stat sb; char errdir[1024] = {0}; + char blkdir[23]; /* /sys/dev/block/XXX:XXX */ unsigned int cmd; int error = 0, root_seen = 0, save_errno = 0; @@ -96,10 +148,15 @@ static int vss_operate(int operation) while ((ent = getmntent(mounts))) { if (strncmp(ent->mnt_fsname, match, strlen(match))) continue; - if (stat(ent->mnt_fsname, &sb) == -1) - continue; - if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR) - continue; + if (stat(ent->mnt_fsname, &sb)) { + syslog(LOG_ERR, "Can't stat: %s; error:%d %s!", + ent->mnt_fsname, errno, strerror(errno)); + } else { + sprintf(blkdir, "/sys/dev/block/%d:%d", + major(sb.st_rdev), minor(sb.st_rdev)); + if (is_dev_loop(blkdir)) + continue; + } if (hasmntopt(ent, MNTOPT_RO) != NULL) continue; if (strcmp(ent->mnt_type, "vfat") == 0) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 6/8] Drivers: hv: vmbus: Make TLFS #define names architecture neutral
From: Michael Kelley The Hyper-V feature and hint flags in hyperv-tlfs.h are all defined with the string "X64" in the name. Some of these flags are indeed x86/x64 specific, but others are not. For the ones that are used in architecture independent Hyper-V driver code, or will be used in the upcoming support for Hyper-V for ARM64, this patch removes the "X64" from the name. This patch changes the flags that are currently known to be used on multiple architectures. Hyper-V for ARM64 is still a work-in-progress and the Top Level Functional Spec (TLFS) has not been separated into x86/x64 and ARM64 areas. So additional flags may need to be updated later. This patch only changes symbol names. There are no functional changes. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_init.c | 4 ++-- arch/x86/include/asm/hyperv-tlfs.h | 12 ++-- arch/x86/kernel/cpu/mshyperv.c | 4 ++-- drivers/hv/hv.c| 10 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index cfecc2272f2d..3db87293dce0 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -302,7 +302,7 @@ void hyperv_init(void) * Register Hyper-V specific clocksource. */ #ifdef CONFIG_HYPERV_TSCPAGE - if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { + if (ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE) { union hv_x64_msr_hypercall_contents tsc_msr; tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL); @@ -331,7 +331,7 @@ void hyperv_init(void) */ hyperv_cs = &hyperv_cs_msr; - if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) + if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE) clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); return; diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 416cb0e0c496..44657e07fd59 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -35,9 +35,9 @@ /* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */ #define HV_X64_MSR_VP_RUNTIME_AVAILABLE(1 << 0) /* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/ -#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE(1 << 1) +#define HV_MSR_TIME_REF_COUNT_AVAILABLE(1 << 1) /* Partition reference TSC MSR is available */ -#define HV_X64_MSR_REFERENCE_TSC_AVAILABLE (1 << 9) +#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9) /* A partition's reference time stamp counter (TSC) page */ #define HV_X64_MSR_REFERENCE_TSC 0x4021 @@ -60,7 +60,7 @@ * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through * HV_X64_MSR_STIMER3_COUNT) available */ -#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3) +#define HV_MSR_SYNTIMER_AVAILABLE (1 << 3) /* * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR) * are available @@ -86,7 +86,7 @@ #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10) /* stimer Direct Mode is available */ -#define HV_X64_STIMER_DIRECT_MODE_AVAILABLE(1 << 19) +#define HV_STIMER_DIRECT_MODE_AVAILABLE(1 << 19) /* * Feature identification: EBX indicates which flags were specified at @@ -160,9 +160,9 @@ #define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5) /* - * Virtual APIC support + * Recommend not using Auto End-Of-Interrupt feature */ -#define HV_X64_DEPRECATING_AEOI_RECOMMENDED(1 << 9) +#define HV_DEPRECATING_AEOI_RECOMMENDED(1 << 9) /* Recommend using the newer ExProcessorMasks interface */ #define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 8a49b7ef7b76..ad12733f6058 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -50,7 +50,7 @@ __visible void __irq_entry hyperv_vector_handler(struct pt_regs *regs) if (vmbus_handler) vmbus_handler(); - if (ms_hyperv.hints & HV_X64_DEPRECATING_AEOI_RECOMMENDED) + if (ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED) ack_APIC_irq(); exiting_irq(); @@ -300,7 +300,7 @@ static void __init ms_hyperv_init_platform(void) hyperv_reenlightenment_vector); /* Setup the IDT for stimer0 */ - if (ms_hyperv.misc_features & HV_X64_STIMER_DIRECT_MODE_AVAILABLE) + if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE) alloc_intr_gate(HYPERV_STIMER0_VECTOR, hv_stimer0_callback_vector); #endif diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 96c403a07906..c72e8d7bd7fc 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -64,7 +64,7 @@ int hv_init(void)
[PATCH 2/8] x86/hyperv: Add interrupt handler annotations
From: Michael Kelley Add standard interrupt handler annotations to hyperv_vector_handler(). This does not fix any observed bug, but avoids potential removal of the code by link time optimization and makes it consistent with hv_stimer0_vector_handler in the same source file. Suggested-by: Thomas Gleixner Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/kernel/cpu/mshyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 031082c96db8..8a49b7ef7b76 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -41,7 +41,7 @@ static void (*hv_stimer0_handler)(void); static void (*hv_kexec_handler)(void); static void (*hv_crash_handler)(struct pt_regs *regs); -void hyperv_vector_handler(struct pt_regs *regs) +__visible void __irq_entry hyperv_vector_handler(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/8] Drivers: hv: Miscellaneous fixes/improvements
From: "K. Y. Srinivasan" Some miscellaneous fixes/improvements. Arjan van de Ven (1): use the new async probing feature for the hyperv drivers Dexuan Cui (1): Drivers: hv: vmbus: Fix the offer_in_progress in vmbus_process_offer() Michael Kelley (4): x86/hyperv: Add interrupt handler annotations Drivers: hv: vmbus: Add comments on ring buffer signaling Drivers: hv: vmbus: Remove x86 MSR refs in arch independent code Drivers: hv: vmbus: Make TLFS #define names architecture neutral Olaf Hering (1): tools: hv: update lsvmbus to be compatible with python3 Vitaly Kuznetsov (1): Tools: hv: vss: fix loop device detection arch/x86/hyperv/hv_init.c | 4 +- arch/x86/include/asm/hyperv-tlfs.h| 12 ++--- arch/x86/include/asm/mshyperv.h | 12 +++-- arch/x86/kernel/cpu/mshyperv.c| 6 +-- drivers/hid/hid-hyperv.c | 3 ++ drivers/hv/channel_mgmt.c | 4 +- drivers/hv/hv.c | 30 ++--- drivers/hv/hv_balloon.c | 3 ++ drivers/hv/hv_util.c | 3 ++ drivers/hv/ring_buffer.c | 65 ++- drivers/input/serio/hyperv-keyboard.c | 3 ++ drivers/net/hyperv/netvsc_drv.c | 3 ++ drivers/scsi/storvsc_drv.c| 3 ++ drivers/video/fbdev/hyperv_fb.c | 6 +++ include/linux/hyperv.h| 31 + tools/hv/hv_vss_daemon.c | 65 +-- tools/hv/lsvmbus | 12 ++--- 17 files changed, 201 insertions(+), 64 deletions(-) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V3 5/5] X86: Hyper-V: Consolidate the allocation of the hypercall input page
From: "K. Y. Srinivasan" Consolidate the allocation of the hypercall input page. Signed-off-by: K. Y. Srinivasan Reviewed-by: Michael Kelley --- arch/x86/hyperv/hv_init.c | 2 -- arch/x86/hyperv/mmu.c | 30 ++ arch/x86/include/asm/mshyperv.h | 1 - 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 6bc90d68ac8b..4c431e1c1eff 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -324,8 +324,6 @@ void __init hyperv_init(void) hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - hyper_alloc_mmu(); - hv_apic_init(); /* diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index c9cd28f0bae4..5f053d7d1bd9 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -32,9 +32,6 @@ struct hv_flush_pcpu_ex { /* 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. @@ -77,7 +74,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -85,10 +82,8 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -164,7 +159,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush_ex || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -172,10 +167,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush_ex); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu_ex **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -257,14 +250,3 @@ void hyperv_setup_mmu_ops(void) 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)) - pcpu_flush = alloc_percpu(struct hv_flush_pcpu *); - else - pcpu_flush_ex = alloc_percpu(struct hv_flush_pcpu_ex *); -} diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 0ee82519957b..9aaa493f5756 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -294,7 +294,6 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); -void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); bool hv_is_hyperv_initialized(void); void hyperv_cleanup(void); -- 2.17.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V3 1/5] X86: Hyper-V: Enlighten APIC access
From: "K. Y. Srinivasan" Hyper-V supports MSR based APIC access; implement the enlightenment. Signed-off-by: K. Y. Srinivasan Reviewed-by: Michael Kelley --- arch/x86/hyperv/Makefile| 2 +- arch/x86/hyperv/hv_apic.c | 104 arch/x86/hyperv/hv_init.c | 5 +- arch/x86/include/asm/mshyperv.h | 4 +- 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 367a8203cfcf..00ce4df01a09 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1 +1 @@ -obj-y := hv_init.o mmu.o +obj-y := hv_init.o mmu.o hv_apic.o diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c new file mode 100644 index ..ca20e31d311c --- /dev/null +++ b/arch/x86/hyperv/hv_apic.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Hyper-V specific APIC code. + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : K. Y. Srinivasan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_X86_64 +#if IS_ENABLED(CONFIG_HYPERV) + +static u64 hv_apic_icr_read(void) +{ + u64 reg_val; + + rdmsrl(HV_X64_MSR_ICR, reg_val); + return reg_val; +} + +static void hv_apic_icr_write(u32 low, u32 id) +{ + u64 reg_val; + + reg_val = SET_APIC_DEST_FIELD(id); + reg_val = reg_val << 32; + reg_val |= low; + + wrmsrl(HV_X64_MSR_ICR, reg_val); +} + +static u32 hv_apic_read(u32 reg) +{ + u32 reg_val, hi; + + switch (reg) { + case APIC_EOI: + rdmsr(HV_X64_MSR_EOI, reg_val, hi); + return reg_val; + case APIC_TASKPRI: + rdmsr(HV_X64_MSR_TPR, reg_val, hi); + return reg_val; + + default: + return native_apic_mem_read(reg); + } +} + +static void hv_apic_write(u32 reg, u32 val) +{ + switch (reg) { + case APIC_EOI: + wrmsr(HV_X64_MSR_EOI, val, 0); + break; + case APIC_TASKPRI: + wrmsr(HV_X64_MSR_TPR, val, 0); + break; + default: + native_apic_mem_write(reg, val); + } +} + +static void hv_apic_eoi_write(u32 reg, u32 val) +{ + wrmsr(HV_X64_MSR_EOI, val, 0); +} + +void __init hv_apic_init(void) +{ + if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { + pr_info("Hyper-V: Using MSR based APIC access\n"); + apic_set_eoi_write(hv_apic_eoi_write); + apic->read = hv_apic_read; + apic->write = hv_apic_write; + apic->icr_write = hv_apic_icr_write; + apic->icr_read = hv_apic_icr_read; + } +} + +#endif /* CONFIG_HYPERV */ +#endif /* CONFIG_X86_64 */ diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index cfecc2272f2d..71e50fc2b7ef 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -242,8 +242,9 @@ static int hv_cpu_die(unsigned int cpu) * * 1. Setup the hypercall page. * 2. Register Hyper-V specific clocksource. + * 3. Setup Hyper-V specific APIC entry points. */ -void hyperv_init(void) +void __init hyperv_init(void) { u64 guest_id, required_msrs; union hv_x64_msr_hypercall_contents hypercall_msr; @@ -298,6 +299,8 @@ void hyperv_init(void) hyper_alloc_mmu(); + hv_apic_init(); + /* * Register Hyper-V specific clocksource. */ diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index b90e79610cf7..162977b82e2e 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -258,7 +258,7 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } -void hyperv_init(void); +void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); @@ -269,6 +269,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); +void hv_apic_init(void); #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline bool hv_is_hyperv_initialized(void) { return false; } @@ -277,6 +278,7 @@ static inline void hyperv_setup_
[PATCH V3 3/5] X86: Hyper-V: Enhanced IPI enlightenment
From: "K. Y. Srinivasan" Support enhanced IPI enlightenments (to target more than 64 CPUs). Signed-off-by: K. Y. Srinivasan Reviewed-by: Michael Kelley --- arch/x86/hyperv/hv_apic.c | 42 +- arch/x86/hyperv/mmu.c | 2 +- arch/x86/include/asm/hyperv-tlfs.h | 15 ++- arch/x86/include/asm/mshyperv.h| 33 +++ 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 3e0de61f1a7c..192b6ad6a361 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -93,6 +93,40 @@ static void hv_apic_eoi_write(u32 reg, u32 val) /* * IPI implementation on Hyper-V. */ +static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector) +{ + struct ipi_arg_ex **arg; + struct ipi_arg_ex *ipi_arg; + unsigned long flags; + int nr_bank = 0; + int ret = 1; + + local_irq_save(flags); + arg = (struct ipi_arg_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_ex_done; + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->vp_set.valid_bank_mask = 0; + + if (!cpumask_equal(mask, cpu_present_mask)) { + ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; + nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); + } + if (!nr_bank) + ipi_arg->vp_set.format = HV_GENERIC_SET_ALL; + + ret = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank, + ipi_arg, NULL); + +ipi_mask_ex_done: + local_irq_restore(flags); + return ((ret == 0) ? true : false); +} + static bool __send_ipi_mask(const struct cpumask *mask, int vector) { int cur_cpu, vcpu; @@ -110,6 +144,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector) if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) return false; + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + return __send_ipi_mask_ex(mask, vector); + local_irq_save(flags); arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); @@ -193,7 +230,10 @@ static void hv_send_ipi_self(int vector) void __init hv_apic_init(void) { if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { - pr_info("Hyper-V: Using IPI hypercalls\n"); + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + pr_info("Hyper-V: Using ext hypercalls for IPI\n"); + else + pr_info("Hyper-V: Using IPI hypercalls\n"); /* * Set the IPI entry points. */ diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 56c9ebac946f..adee39a7a3f2 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -239,7 +239,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, 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; + flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K; nr_bank = cpumask_to_vp_set(flush, cpus); } diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 332e786d4deb..3bfa92c2793c 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -344,6 +344,7 @@ struct hv_tsc_emulation_status { #define HVCALL_SEND_IPI0x000b #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013 #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014 +#define HVCALL_SEND_IPI_EX 0x0015 #define HVCALL_POST_MESSAGE0x005c #define HVCALL_SIGNAL_EVENT0x005d @@ -369,7 +370,7 @@ struct hv_tsc_emulation_status { #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3) enum HV_GENERIC_SET_FORMAT { - HV_GENERIC_SET_SPARCE_4K, + HV_GENERIC_SET_SPARSE_4K, HV_GENERIC_SET_ALL, }; @@ -721,4 +722,16 @@ struct ipi_arg_non_ex { u64 cpu_mask; }; +struct hv_vpset { + u64 format; + u64 valid_bank_mask; + u64 bank_contents[]; +}; + +struct ipi_arg_ex { + u32 vector; + u32 reserved; + struct hv_vpset vp_set; +}; + #endif diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 1eff91599c2b..0ee82519957b 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -259,6 +259,39 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } +static inline int cpumask_to_vpset(struct hv_vpset *vpset, + const struct cpumask *cpus) +{ + int cpu, vc
[PATCH V3 2/5] X86: Hyper-V: Enable IPI enlightenments
From: "K. Y. Srinivasan" Hyper-V supports hypercalls to implement IPI; use them. Signed-off-by: K. Y. Srinivasan Reviewed-by: Michael Kelley --- arch/x86/hyperv/hv_apic.c | 117 + arch/x86/hyperv/hv_init.c | 27 +++ arch/x86/include/asm/hyperv-tlfs.h | 15 arch/x86/include/asm/mshyperv.h| 1 + 4 files changed, 160 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index ca20e31d311c..3e0de61f1a7c 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -33,6 +33,8 @@ #ifdef CONFIG_X86_64 #if IS_ENABLED(CONFIG_HYPERV) +static struct apic orig_apic; + static u64 hv_apic_icr_read(void) { u64 reg_val; @@ -88,8 +90,123 @@ static void hv_apic_eoi_write(u32 reg, u32 val) wrmsr(HV_X64_MSR_EOI, val, 0); } +/* + * IPI implementation on Hyper-V. + */ +static bool __send_ipi_mask(const struct cpumask *mask, int vector) +{ + int cur_cpu, vcpu; + struct ipi_arg_non_ex **arg; + struct ipi_arg_non_ex *ipi_arg; + int ret = 1; + unsigned long flags; + + if (cpumask_empty(mask)) + return true; + + if (!hv_hypercall_pg) + return false; + + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + return false; + + local_irq_save(flags); + arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_done; + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->cpu_mask = 0; + + for_each_cpu(cur_cpu, mask) { + vcpu = hv_cpu_number_to_vp_number(cur_cpu); + /* +* This particular version of the IPI hypercall can +* only target upto 64 CPUs. +*/ + if (vcpu >= 64) + goto ipi_mask_done; + + __set_bit(vcpu, (unsigned long *)&ipi_arg->cpu_mask); + } + + ret = hv_do_hypercall(HVCALL_SEND_IPI, ipi_arg, NULL); + +ipi_mask_done: + local_irq_restore(flags); + return ((ret == 0) ? true : false); +} + +static bool __send_ipi_one(int cpu, int vector) +{ + struct cpumask mask = CPU_MASK_NONE; + + cpumask_set_cpu(cpu, &mask); + return __send_ipi_mask(&mask, vector); +} + +static void hv_send_ipi(int cpu, int vector) +{ + if (!__send_ipi_one(cpu, vector)) + orig_apic.send_IPI(cpu, vector); +} + +static void hv_send_ipi_mask(const struct cpumask *mask, int vector) +{ + if (!__send_ipi_mask(mask, vector)) + orig_apic.send_IPI_mask(mask, vector); +} + +static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector) +{ + unsigned int this_cpu = smp_processor_id(); + struct cpumask new_mask; + const struct cpumask *local_mask; + + cpumask_copy(&new_mask, mask); + cpumask_clear_cpu(this_cpu, &new_mask); + local_mask = &new_mask; + if (!__send_ipi_mask(local_mask, vector)) + orig_apic.send_IPI_mask_allbutself(mask, vector); +} + +static void hv_send_ipi_allbutself(int vector) +{ + hv_send_ipi_mask_allbutself(cpu_online_mask, vector); +} + +static void hv_send_ipi_all(int vector) +{ + if (!__send_ipi_mask(cpu_online_mask, vector)) + orig_apic.send_IPI_all(vector); +} + +static void hv_send_ipi_self(int vector) +{ + if (!__send_ipi_one(smp_processor_id(), vector)) + orig_apic.send_IPI_self(vector); +} + void __init hv_apic_init(void) { + if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { + pr_info("Hyper-V: Using IPI hypercalls\n"); + /* +* Set the IPI entry points. +*/ + orig_apic = *apic; + + apic->send_IPI = hv_send_ipi; + apic->send_IPI_mask = hv_send_ipi_mask; + apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself; + apic->send_IPI_allbutself = hv_send_ipi_allbutself; + apic->send_IPI_all = hv_send_ipi_all; + apic->send_IPI_self = hv_send_ipi_self; + } + if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { pr_info("Hyper-V: Using MSR based APIC access\n"); apic_set_eoi_write(hv_apic_eoi_write); diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 71e50fc2b7ef..6bc90d68ac8b 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index); struct hv_vp_assist_page **hv_vp_assist_page; EXPORT_SYMBOL_GPL(hv_vp_assist_page); +void __percpu **hyperv_pcpu_input_arg; +EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); + u32 hv_max_vp_index; static int hv_cpu_init(unsigned int cpu) { u64 msr_vp_index; struct hv_vp_assist_page **hvp = &hv_vp_assis
[PATCH V3 4/5] X86: Hyper-V: Consolidate code for converting cpumask to vpset
From: "K. Y. Srinivasan" Consolidate code for converting cpumask to vpset. Signed-off-by: K. Y. Srinivasan Reviewed-by: Michael Kelley --- arch/x86/hyperv/mmu.c | 43 ++- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index adee39a7a3f2..c9cd28f0bae4 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -25,11 +25,7 @@ struct hv_flush_pcpu { struct hv_flush_pcpu_ex { u64 address_space; u64 flags; - struct { - u64 format; - u64 valid_bank_mask; - u64 bank_contents[]; - } hv_vp_set; + struct hv_vpset hv_vp_set; u64 gva_list[]; }; @@ -70,41 +66,6 @@ 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; - - /* valid_bank_mask can represent up to 64 banks */ - if (hv_max_vp_index / 64 >= 64) - return 0; - - /* -* Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex -* structs are not cleared between calls, we risk flushing unneeded -* vCPUs otherwise. -*/ - for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) - flush->hv_vp_set.bank_contents[vcpu_bank] = 0; - - /* -* 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; - __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, const struct flush_tlb_info *info) { @@ -240,7 +201,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, if (!cpumask_equal(cpus, cpu_present_mask)) { flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K; - nr_bank = cpumask_to_vp_set(flush, cpus); + nr_bank = cpumask_to_vpset(&(flush->hv_vp_set), cpus); } if (!nr_bank) { -- 2.17.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V3 0/5] X86: Hyper-V: APIC enlightenments
From: "K. Y. Srinivasan" Implement APIC related enlightenments. V2: Addressed comments from Thomas Gleixner and Michael Kelley (EOSG) . V3: Address build issues reported by kbuild test robot K. Y. Srinivasan (5): X86: Hyper-V: Enlighten APIC access X86: Hyper-V: Enable IPI enlightenments X86: Hyper-V: Enhanced IPI enlightenment X86: Hyper-V: Consolidate code for converting cpumask to vpset X86: Hyper-V: Consolidate the allocation of the hypercall input page arch/x86/hyperv/Makefile | 2 +- arch/x86/hyperv/hv_apic.c | 261 + arch/x86/hyperv/hv_init.c | 32 +++- arch/x86/hyperv/mmu.c | 75 + arch/x86/include/asm/hyperv-tlfs.h | 30 +++- arch/x86/include/asm/mshyperv.h| 39 - 6 files changed, 367 insertions(+), 72 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c -- 2.17.0 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/1] Drivers: hv: vmbus: enable VMBus protocol version 5.0
From: Dexuan Cui With VMBus protocol 5.0, we're able to better support new features, e.g. running two or more VMBus drivers simultaneously in a single VM -- note: we can't simply load the current VMBus driver twice, instead, a secondary VMBus driver must be implemented. This patch adds the support for the new VMBus protocol, which is available on new Windows hosts, by: 1) We still use SINT2 for compatibility; 2) We must use Connection ID 4 for the Initiate Contact Message, and for subsequent messages, we must use the Message Connection ID field in the host-returned VersionResponse Message. Notes for developers of the secondary VMBus driver: 1) Must use VMBus protocol 5.0 as well; 2) Must use a different SINT number that is not in use. 3) Must use Connection ID 4 for the Initiate Contact Message, and for subsequent messages, must use the Message Connection ID field in the host-returned VersionResponse Message. 4) It's possible that the primary VMBus driver using protocol version 4.0 can work with a secondary VMBus driver using protocol version 5.0, but it's recommended that both should use 5.0 for new Hyper-V features in the future. Signed-off-by: Dexuan Cui Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/connection.c | 44 ++-- drivers/hv/hyperv_vmbus.h | 3 +++ include/linux/hyperv.h| 26 -- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 72855182b191..19e046820fda 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -63,6 +63,9 @@ static __u32 vmbus_get_next_version(__u32 current_version) case (VERSION_WIN10): return VERSION_WIN8_1; + case (VERSION_WIN10_V5): + return VERSION_WIN10; + case (VERSION_WS2008): default: return VERSION_INVAL; @@ -80,9 +83,29 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, msg = (struct vmbus_channel_initiate_contact *)msginfo->msg; + memset(msg, 0, sizeof(*msg)); msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT; msg->vmbus_version_requested = version; - msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); + + /* +* VMBus protocol 5.0 (VERSION_WIN10_V5) requires that we must use +* VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate Contact Message, +* and for subsequent messages, we must use the Message Connection ID +* field in the host-returned Version Response Message. And, with +* VERSION_WIN10_V5, we don't use msg->interrupt_page, but we tell +* the host explicitly that we still use VMBUS_MESSAGE_SINT(2) for +* compatibility. +* +* On old hosts, we should always use VMBUS_MESSAGE_CONNECTION_ID (1). +*/ + if (version >= VERSION_WIN10_V5) { + msg->msg_sint = VMBUS_MESSAGE_SINT; + vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4; + } else { + msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); + vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID; + } + msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); /* @@ -137,6 +160,10 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, /* Check if successful */ if (msginfo->response.version_response.version_supported) { vmbus_connection.conn_state = CONNECTED; + + if (version >= VERSION_WIN10_V5) + vmbus_connection.msg_conn_id = + msginfo->response.version_response.msg_conn_id; } else { return -ECONNREFUSED; } @@ -354,13 +381,14 @@ void vmbus_on_event(unsigned long data) */ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) { + struct vmbus_channel_message_header *hdr; union hv_connection_id conn_id; int ret = 0; int retries = 0; u32 usec = 1; conn_id.asu32 = 0; - conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; + conn_id.u.id = vmbus_connection.msg_conn_id; /* * hv_post_message() can have transient failures because of @@ -372,6 +400,18 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) switch (ret) { case HV_STATUS_INVALID_CONNECTION_ID: + /* +* See vmbus_negotiate_version(): VMBus protocol 5.0 +* requires that we must use +* VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate +* Contact message, but on old hosts that only +* supp
[PATCH 1/1] doc: fix sysfs ABI documentation
From: Stephen Hemminger In 4.9 kernel, the sysfs files for Hyper-V VMBus changed name but the documentation files were not updated. The current sysfs file names are /sys/bus/vmbus/devices//... See commit 9a56e5d6a0ba ("Drivers: hv: make VMBus bus ids persistent") and commit f6b2db084b65 ("vmbus: make sysfs names consistent with PCI") Reported-by: Michael Kelley Signed-off-by: Stephen Hemminger Cc: sta...@vger.kernel.org Signed-off-by: K. Y. Srinivasan --- Documentation/ABI/stable/sysfs-bus-vmbus | 40 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 0c9d9dcd2151..3eaffbb2d468 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -1,25 +1,25 @@ -What: /sys/bus/vmbus/devices/vmbus_*/id +What: /sys/bus/vmbus/devices//id Date: Jul 2009 KernelVersion: 2.6.31 Contact: K. Y. Srinivasan Description: The VMBus child_relid of the device's primary channel Users: tools/hv/lsvmbus -What: /sys/bus/vmbus/devices/vmbus_*/class_id +What: /sys/bus/vmbus/devices//class_id Date: Jul 2009 KernelVersion: 2.6.31 Contact: K. Y. Srinivasan Description: The VMBus interface type GUID of the device Users: tools/hv/lsvmbus -What: /sys/bus/vmbus/devices/vmbus_*/device_id +What: /sys/bus/vmbus/devices//device_id Date: Jul 2009 KernelVersion: 2.6.31 Contact: K. Y. Srinivasan Description: The VMBus interface instance GUID of the device Users: tools/hv/lsvmbus -What: /sys/bus/vmbus/devices/vmbus_*/channel_vp_mapping +What: /sys/bus/vmbus/devices//channel_vp_mapping Date: Jul 2015 KernelVersion: 4.2.0 Contact: K. Y. Srinivasan @@ -28,112 +28,112 @@ Description: The mapping of which primary/sub channels are bound to which Format: Users: tools/hv/lsvmbus -What: /sys/bus/vmbus/devices/vmbus_*/device +What: /sys/bus/vmbus/devices//device Date: Dec. 2015 KernelVersion: 4.5 Contact: K. Y. Srinivasan Description: The 16 bit device ID of the device Users: tools/hv/lsvmbus and user level RDMA libraries -What: /sys/bus/vmbus/devices/vmbus_*/vendor +What: /sys/bus/vmbus/devices//vendor Date: Dec. 2015 KernelVersion: 4.5 Contact: K. Y. Srinivasan Description: The 16 bit vendor ID of the device Users: tools/hv/lsvmbus and user level RDMA libraries -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN +What: /sys/bus/vmbus/devices//channels/ Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Directory for per-channel information NN is the VMBUS relid associtated with the channel. -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/cpu +What: /sys/bus/vmbus/devices//channels//cpu Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: VCPU (sub)channel is affinitized to Users: tools/hv/lsvmbus and other debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/cpu +What: /sys/bus/vmbus/devices//channels//cpu Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: VCPU (sub)channel is affinitized to Users: tools/hv/lsvmbus and other debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/in_mask +What: /sys/bus/vmbus/devices//channels//in_mask Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Host to guest channel interrupt mask Users: Debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/latency +What: /sys/bus/vmbus/devices//channels//latency Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel signaling latency Users: Debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/out_mask +What: /sys/bus/vmbus/devices//channels//out_mask Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Guest to host channel interrupt mask Users: Debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/pending +What: /sys/bus/vmbus/devices//channels//pending Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel interrupt pending state Users: Debugging tools -What: /sys/bus/vmbus/devices/vmbus_*/channels/NN/read_avail +What: /sys/bus/vmbus/devices//channels//read_avail Date: September. 2017 KernelVersion: 4.14 Contact:
[PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments
From: "K. Y. Srinivasan" Hyper-V supports hypercalls to implement IPI; use them. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 118 + arch/x86/hyperv/hv_init.c | 27 + arch/x86/include/asm/hyperv-tlfs.h | 15 + arch/x86/include/asm/mshyperv.h| 1 + 4 files changed, 161 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 41f8b71ca19e..f52d08a7a343 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -31,6 +31,9 @@ #include #if IS_ENABLED(CONFIG_HYPERV) + +static struct apic orig_apic; + static u64 hv_apic_icr_read(void) { u64 reg_val; @@ -86,8 +89,123 @@ static void hv_apic_eoi_write(u32 reg, u32 val) wrmsr(HV_X64_MSR_EOI, val, 0); } +/* + * IPI implementation on Hyper-V. + */ +static bool __send_ipi_mask(const struct cpumask *mask, int vector) +{ + int cur_cpu, vcpu; + struct ipi_arg_non_ex **arg; + struct ipi_arg_non_ex *ipi_arg; + int ret = 1; + unsigned long flags; + + if (cpumask_empty(mask)) + return true; + + if (!hv_hypercall_pg) + return false; + + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + return false; + + local_irq_save(flags); + arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_done; + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->cpu_mask = 0; + + for_each_cpu(cur_cpu, mask) { + vcpu = hv_cpu_number_to_vp_number(cur_cpu); + /* +* This particular version of the IPI hypercall can +* only target upto 64 CPUs. +*/ + if (vcpu >= 64) + goto ipi_mask_done; + + __set_bit(vcpu, (unsigned long *)&ipi_arg->cpu_mask); + } + + ret = hv_do_hypercall(HVCALL_SEND_IPI, ipi_arg, NULL); + +ipi_mask_done: + local_irq_restore(flags); + return ((ret == 0) ? true : false); +} + +static bool __send_ipi_one(int cpu, int vector) +{ + struct cpumask mask = CPU_MASK_NONE; + + cpumask_set_cpu(cpu, &mask); + return __send_ipi_mask(&mask, vector); +} + +static void hv_send_ipi(int cpu, int vector) +{ + if (!__send_ipi_one(cpu, vector)) + orig_apic.send_IPI(cpu, vector); +} + +static void hv_send_ipi_mask(const struct cpumask *mask, int vector) +{ + if (!__send_ipi_mask(mask, vector)) + orig_apic.send_IPI_mask(mask, vector); +} + +static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector) +{ + unsigned int this_cpu = smp_processor_id(); + struct cpumask new_mask; + const struct cpumask *local_mask; + + cpumask_copy(&new_mask, mask); + cpumask_clear_cpu(this_cpu, &new_mask); + local_mask = &new_mask; + if (!__send_ipi_mask(local_mask, vector)) + orig_apic.send_IPI_mask_allbutself(mask, vector); +} + +static void hv_send_ipi_allbutself(int vector) +{ + hv_send_ipi_mask_allbutself(cpu_online_mask, vector); +} + +static void hv_send_ipi_all(int vector) +{ + if (!__send_ipi_mask(cpu_online_mask, vector)) + orig_apic.send_IPI_all(vector); +} + +static void hv_send_ipi_self(int vector) +{ + if (!__send_ipi_one(smp_processor_id(), vector)) + orig_apic.send_IPI_self(vector); +} + void __init hv_apic_init(void) { + if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { + pr_info("Hyper-V: Using IPI hypercalls\n"); + /* +* Set the IPI entry points. +*/ + orig_apic = *apic; + + apic->send_IPI = hv_send_ipi; + apic->send_IPI_mask = hv_send_ipi_mask; + apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself; + apic->send_IPI_allbutself = hv_send_ipi_allbutself; + apic->send_IPI_all = hv_send_ipi_all; + apic->send_IPI_self = hv_send_ipi_self; + } + if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { pr_info("Hyper-V: Using MSR based APIC access\n"); apic_set_eoi_write(hv_apic_eoi_write); diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 71e50fc2b7ef..6bc90d68ac8b 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index); struct hv_vp_assist_page **hv_vp_assist_page; EXPORT_SYMBOL_GPL(hv_vp_assist_page); +void __percpu **hyperv_pcpu_input_arg; +EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); + u32 hv_max_vp_index; static int hv_cpu_init(unsigned int cpu) { u64 msr_vp_index; struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
[PATCH V2 5/5] X86: Hyper-V: Consolidate the allocation of the hypercall input page
From: "K. Y. Srinivasan" Consolidate the allocation of the hypercall input page. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_init.c | 2 -- arch/x86/hyperv/mmu.c | 30 ++ arch/x86/include/asm/mshyperv.h | 1 - 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 6bc90d68ac8b..4c431e1c1eff 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -324,8 +324,6 @@ void __init hyperv_init(void) hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - hyper_alloc_mmu(); - hv_apic_init(); /* diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index c9cd28f0bae4..5f053d7d1bd9 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -32,9 +32,6 @@ struct hv_flush_pcpu_ex { /* 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. @@ -77,7 +74,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -85,10 +82,8 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -164,7 +159,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush_ex || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -172,10 +167,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush_ex); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu_ex **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -257,14 +250,3 @@ void hyperv_setup_mmu_ops(void) 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)) - pcpu_flush = alloc_percpu(struct hv_flush_pcpu *); - else - pcpu_flush_ex = alloc_percpu(struct hv_flush_pcpu_ex *); -} diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 0ee82519957b..9aaa493f5756 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -294,7 +294,6 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); -void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); bool hv_is_hyperv_initialized(void); void hyperv_cleanup(void); -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 4/5] X86: Hyper-V: Consolidate code for converting cpumask to vpset
From: "K. Y. Srinivasan" Consolidate code for converting cpumask to vpset. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/mmu.c | 43 ++- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index adee39a7a3f2..c9cd28f0bae4 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -25,11 +25,7 @@ struct hv_flush_pcpu { struct hv_flush_pcpu_ex { u64 address_space; u64 flags; - struct { - u64 format; - u64 valid_bank_mask; - u64 bank_contents[]; - } hv_vp_set; + struct hv_vpset hv_vp_set; u64 gva_list[]; }; @@ -70,41 +66,6 @@ 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; - - /* valid_bank_mask can represent up to 64 banks */ - if (hv_max_vp_index / 64 >= 64) - return 0; - - /* -* Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex -* structs are not cleared between calls, we risk flushing unneeded -* vCPUs otherwise. -*/ - for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) - flush->hv_vp_set.bank_contents[vcpu_bank] = 0; - - /* -* 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; - __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, const struct flush_tlb_info *info) { @@ -240,7 +201,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, if (!cpumask_equal(cpus, cpu_present_mask)) { flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K; - nr_bank = cpumask_to_vp_set(flush, cpus); + nr_bank = cpumask_to_vpset(&(flush->hv_vp_set), cpus); } if (!nr_bank) { -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 1/5] X86: Hyper-V: Enlighten APIC access
From: "K. Y. Srinivasan" Hyper-V supports MSR based APIC access; implement the enlightenment. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/Makefile| 2 +- arch/x86/hyperv/hv_apic.c | 101 arch/x86/hyperv/hv_init.c | 5 +- arch/x86/include/asm/mshyperv.h | 4 +- 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 367a8203cfcf..00ce4df01a09 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1 +1 @@ -obj-y := hv_init.o mmu.o +obj-y := hv_init.o mmu.o hv_apic.o diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c new file mode 100644 index ..41f8b71ca19e --- /dev/null +++ b/arch/x86/hyperv/hv_apic.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Hyper-V specific APIC code. + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : K. Y. Srinivasan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if IS_ENABLED(CONFIG_HYPERV) +static u64 hv_apic_icr_read(void) +{ + u64 reg_val; + + rdmsrl(HV_X64_MSR_ICR, reg_val); + return reg_val; +} + +static void hv_apic_icr_write(u32 low, u32 id) +{ + u64 reg_val; + + reg_val = SET_APIC_DEST_FIELD(id); + reg_val = reg_val << 32; + reg_val |= low; + + wrmsrl(HV_X64_MSR_ICR, reg_val); +} + +static u32 hv_apic_read(u32 reg) +{ + u32 reg_val, hi; + + switch (reg) { + case APIC_EOI: + rdmsr(HV_X64_MSR_EOI, reg_val, hi); + return reg_val; + case APIC_TASKPRI: + rdmsr(HV_X64_MSR_TPR, reg_val, hi); + return reg_val; + + default: + return native_apic_mem_read(reg); + } +} + +static void hv_apic_write(u32 reg, u32 val) +{ + switch (reg) { + case APIC_EOI: + wrmsr(HV_X64_MSR_EOI, val, 0); + break; + case APIC_TASKPRI: + wrmsr(HV_X64_MSR_TPR, val, 0); + break; + default: + native_apic_mem_write(reg, val); + } +} + +static void hv_apic_eoi_write(u32 reg, u32 val) +{ + wrmsr(HV_X64_MSR_EOI, val, 0); +} + +void __init hv_apic_init(void) +{ + if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { + pr_info("Hyper-V: Using MSR based APIC access\n"); + apic_set_eoi_write(hv_apic_eoi_write); + apic->read = hv_apic_read; + apic->write = hv_apic_write; + apic->icr_write = hv_apic_icr_write; + apic->icr_read = hv_apic_icr_read; + } +} + +#endif /*CONFIG_HYPERV */ diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index cfecc2272f2d..71e50fc2b7ef 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -242,8 +242,9 @@ static int hv_cpu_die(unsigned int cpu) * * 1. Setup the hypercall page. * 2. Register Hyper-V specific clocksource. + * 3. Setup Hyper-V specific APIC entry points. */ -void hyperv_init(void) +void __init hyperv_init(void) { u64 guest_id, required_msrs; union hv_x64_msr_hypercall_contents hypercall_msr; @@ -298,6 +299,8 @@ void hyperv_init(void) hyper_alloc_mmu(); + hv_apic_init(); + /* * Register Hyper-V specific clocksource. */ diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index b90e79610cf7..162977b82e2e 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -258,7 +258,7 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } -void hyperv_init(void); +void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); @@ -269,6 +269,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); +void hv_apic_init(void); #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline bool hv_is_hyperv_initialized(void) { return false; } @@ -277,6 +278,7 @@ static inline void hyperv_setup_mmu_ops(void) {} static inline void set_hv_tscchange_cb(void (*cb)(void))
[PATCH V2 3/5] X86: Hyper-V: Enhanced IPI enlightenment
From: "K. Y. Srinivasan" Support enhanced IPI enlightenments (to target more than 64 CPUs). Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 42 +- arch/x86/hyperv/mmu.c | 2 +- arch/x86/include/asm/hyperv-tlfs.h | 15 +- arch/x86/include/asm/mshyperv.h| 33 ++ 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index f52d08a7a343..1e269a318c27 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -92,6 +92,40 @@ static void hv_apic_eoi_write(u32 reg, u32 val) /* * IPI implementation on Hyper-V. */ +static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector) +{ + struct ipi_arg_ex **arg; + struct ipi_arg_ex *ipi_arg; + unsigned long flags; + int nr_bank = 0; + int ret = 1; + + local_irq_save(flags); + arg = (struct ipi_arg_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_ex_done; + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->vp_set.valid_bank_mask = 0; + + if (!cpumask_equal(mask, cpu_present_mask)) { + ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; + nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); + } + if (!nr_bank) + ipi_arg->vp_set.format = HV_GENERIC_SET_ALL; + + ret = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank, + ipi_arg, NULL); + +ipi_mask_ex_done: + local_irq_restore(flags); + return ((ret == 0) ? true : false); +} + static bool __send_ipi_mask(const struct cpumask *mask, int vector) { int cur_cpu, vcpu; @@ -109,6 +143,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector) if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) return false; + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + return __send_ipi_mask_ex(mask, vector); + local_irq_save(flags); arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); @@ -192,7 +229,10 @@ static void hv_send_ipi_self(int vector) void __init hv_apic_init(void) { if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { - pr_info("Hyper-V: Using IPI hypercalls\n"); + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + pr_info("Hyper-V: Using ext hypercalls for IPI\n"); + else + pr_info("Hyper-V: Using IPI hypercalls\n"); /* * Set the IPI entry points. */ diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 56c9ebac946f..adee39a7a3f2 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -239,7 +239,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, 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; + flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K; nr_bank = cpumask_to_vp_set(flush, cpus); } diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 332e786d4deb..3bfa92c2793c 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -344,6 +344,7 @@ struct hv_tsc_emulation_status { #define HVCALL_SEND_IPI0x000b #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013 #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014 +#define HVCALL_SEND_IPI_EX 0x0015 #define HVCALL_POST_MESSAGE0x005c #define HVCALL_SIGNAL_EVENT0x005d @@ -369,7 +370,7 @@ struct hv_tsc_emulation_status { #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3) enum HV_GENERIC_SET_FORMAT { - HV_GENERIC_SET_SPARCE_4K, + HV_GENERIC_SET_SPARSE_4K, HV_GENERIC_SET_ALL, }; @@ -721,4 +722,16 @@ struct ipi_arg_non_ex { u64 cpu_mask; }; +struct hv_vpset { + u64 format; + u64 valid_bank_mask; + u64 bank_contents[]; +}; + +struct ipi_arg_ex { + u32 vector; + u32 reserved; + struct hv_vpset vp_set; +}; + #endif diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 1eff91599c2b..0ee82519957b 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -259,6 +259,39 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } +static inline int cpumask_to_vpset(struct hv_vpset *vpset, + const struct cpumask *cpus) +{ + int cpu, vcpu, vcpu_ba
[PATCH V2 0/5] X86: Hyper-V: APIC enlightenments
From: "K. Y. Srinivasan" Implement APIC related enlightenments. V2: Addressed comments from Thomas Gleixner and Michael Kelley (EOSG) . K. Y. Srinivasan (5): X86: Hyper-V: Enlighten APIC access X86: Hyper-V: Enable IPI enlightenments X86: Hyper-V: Enhanced IPI enlightenment X86: Hyper-V: Consolidate code for converting cpumask to vpset X86: Hyper-V: Consolidate the allocation of the hypercall input page arch/x86/hyperv/Makefile | 2 +- arch/x86/hyperv/hv_apic.c | 259 + arch/x86/hyperv/hv_init.c | 32 - arch/x86/hyperv/mmu.c | 75 ++- arch/x86/include/asm/hyperv-tlfs.h | 30 - arch/x86/include/asm/mshyperv.h| 39 +- 6 files changed, 365 insertions(+), 72 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/5] X86: Hyper-V: Enhanced IPI enlightenment
From: "K. Y. Srinivasan" Support enhanced IPI enlightenments (to target more than 64 CPUs). Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 49 -- arch/x86/include/asm/hyperv-tlfs.h | 1 + arch/x86/include/asm/mshyperv.h| 39 ++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 7f3322ecfb01..fbb408b91e25 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -36,6 +36,12 @@ struct ipi_arg_non_ex { u64 cpu_mask; }; +struct ipi_arg_ex { + u32 vector; + u32 reserved; + struct hv_vpset vp_set; +}; + static struct apic orig_apic; static u64 hv_apic_icr_read(void) @@ -97,6 +103,40 @@ static void hv_apic_eoi_write(u32 reg, u32 val) * IPI implementation on Hyper-V. */ +static int __send_ipi_mask_ex(const struct cpumask *mask, int vector) +{ + int nr_bank = 0; + struct ipi_arg_ex **arg; + struct ipi_arg_ex *ipi_arg; + int ret = 1; + unsigned long flags; + + local_irq_save(flags); + arg = (struct ipi_arg_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_ex_done; + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->vp_set.valid_bank_mask = 0; + + if (!cpumask_equal(mask, cpu_present_mask)) { + ipi_arg->vp_set.format = HV_GENERIC_SET_SPARCE_4K; + nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); + } + if (!nr_bank) + ipi_arg->vp_set.format = HV_GENERIC_SET_ALL; + + ret = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank, + ipi_arg, NULL); + +ipi_mask_ex_done: + local_irq_restore(flags); + return ret; +} + static int __send_ipi_mask(const struct cpumask *mask, int vector) { int cur_cpu, vcpu; @@ -114,6 +154,9 @@ static int __send_ipi_mask(const struct cpumask *mask, int vector) if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) return ret; + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + return __send_ipi_mask_ex(mask, vector); + local_irq_save(flags); arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); @@ -196,8 +239,10 @@ void __init hv_apic_init(void) if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { if (hyperv_pcpu_input_arg == NULL) goto msr_based_access; - - pr_info("Hyper-V: Using IPI hypercalls\n"); + if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + pr_info("Hyper-V: Using ext hypercalls for IPI\n"); + else + pr_info("Hyper-V: Using IPI hypercalls\n"); /* * Set the IPI entry points. */ diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 646cf2ca2aaa..53ea30d768d9 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -344,6 +344,7 @@ struct hv_tsc_emulation_status { #define HVCALL_SEND_IPI0x000b #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013 #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014 +#define HVCALL_SEND_IPI_EX 0x0015 #define HVCALL_POST_MESSAGE0x005c #define HVCALL_SIGNAL_EVENT0x005d diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index f6045f3611de..956e8603bed2 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -259,6 +259,45 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } +struct hv_vpset { + u64 format; + u64 valid_bank_mask; + u64 bank_contents[]; +}; + +static inline int cpumask_to_vpset(struct hv_vpset *vpset, + const struct cpumask *cpus) +{ + int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1; + + /* valid_bank_mask can represent up to 64 banks */ + if (hv_max_vp_index / 64 >= 64) + return 0; + + /* +* Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex +* structs are not cleared between calls, we risk flushing unneeded +* vCPUs otherwise. +*/ + for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) + vpset->bank_contents[vcpu_bank] = 0; + + /* +* 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; +
[PATCH 0/5] X86: Hyper-V: APIC enlightenments
From: "K. Y. Srinivasan" Implement APIC related enlightenments. K. Y. Srinivasan (5): X86: Hyper-V: Enlighten APIC access X86: Hyper-V: Enable IPI enlightenments X86: Hyper-V: Enhanced IPI enlightenment X86: Hyper-V: Consolidate code for converting cpumask to vpset X86: Hyper-V: Consolidate the allocation of the hypercall input page arch/x86/hyperv/Makefile | 2 +- arch/x86/hyperv/hv_apic.c | 268 + arch/x86/hyperv/hv_init.c | 22 ++- arch/x86/hyperv/mmu.c | 78 ++- arch/x86/include/asm/hyperv-tlfs.h | 12 +- arch/x86/include/asm/mshyperv.h| 47 ++- 6 files changed, 356 insertions(+), 73 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 5/5] X86: Hyper-V: Consolidate the allocation of the hypercall input page
From: "K. Y. Srinivasan" Consolidate the allocation of the hypercall input page. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_init.c | 2 -- arch/x86/hyperv/mmu.c | 33 + arch/x86/include/asm/mshyperv.h | 1 - 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index a895662b6b4c..72befd0e2c35 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -314,8 +314,6 @@ void __init hyperv_init(void) hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); - hyper_alloc_mmu(); - hv_apic_init(); /* diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index c9cd28f0bae4..c4466af72e77 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -32,9 +32,6 @@ struct hv_flush_pcpu_ex { /* 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. @@ -77,7 +74,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -85,10 +82,8 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -164,7 +159,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, trace_hyperv_mmu_flush_tlb_others(cpus, info); - if (!pcpu_flush_ex || !hv_hypercall_pg) + if (!hv_hypercall_pg) goto do_native; if (cpumask_empty(cpus)) @@ -172,10 +167,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, local_irq_save(flags); - flush_pcpu = this_cpu_ptr(pcpu_flush_ex); - - if (unlikely(!*flush_pcpu)) - *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); + flush_pcpu = (struct hv_flush_pcpu_ex **) +this_cpu_ptr(hyperv_pcpu_input_arg); flush = *flush_pcpu; @@ -249,6 +242,9 @@ void hyperv_setup_mmu_ops(void) if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED)) return; + if (hyperv_pcpu_input_arg == NULL) + return; + 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; @@ -257,14 +253,3 @@ void hyperv_setup_mmu_ops(void) 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)) - pcpu_flush = alloc_percpu(struct hv_flush_pcpu *); - else - pcpu_flush_ex = alloc_percpu(struct hv_flush_pcpu_ex *); -} diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 956e8603bed2..9931f9908fe2 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -300,7 +300,6 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); -void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); bool hv_is_hyperv_initialized(void); void hyperv_cleanup(void); -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/5] X86: Hyper-V: Consolidate code for converting cpumask to vpset
From: "K. Y. Srinivasan" Consolidate code for converting cpumask to vpset. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 2 +- arch/x86/hyperv/mmu.c | 45 +++--- arch/x86/include/asm/hyperv-tlfs.h | 2 +- 3 files changed, 5 insertions(+), 44 deletions(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index fbb408b91e25..508889c8499e 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -123,7 +123,7 @@ static int __send_ipi_mask_ex(const struct cpumask *mask, int vector) ipi_arg->vp_set.valid_bank_mask = 0; if (!cpumask_equal(mask, cpu_present_mask)) { - ipi_arg->vp_set.format = HV_GENERIC_SET_SPARCE_4K; + ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask); } if (!nr_bank) diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 56c9ebac946f..c9cd28f0bae4 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -25,11 +25,7 @@ struct hv_flush_pcpu { struct hv_flush_pcpu_ex { u64 address_space; u64 flags; - struct { - u64 format; - u64 valid_bank_mask; - u64 bank_contents[]; - } hv_vp_set; + struct hv_vpset hv_vp_set; u64 gva_list[]; }; @@ -70,41 +66,6 @@ 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; - - /* valid_bank_mask can represent up to 64 banks */ - if (hv_max_vp_index / 64 >= 64) - return 0; - - /* -* Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex -* structs are not cleared between calls, we risk flushing unneeded -* vCPUs otherwise. -*/ - for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) - flush->hv_vp_set.bank_contents[vcpu_bank] = 0; - - /* -* 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; - __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, const struct flush_tlb_info *info) { @@ -239,8 +200,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, 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); + flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K; + nr_bank = cpumask_to_vpset(&(flush->hv_vp_set), cpus); } if (!nr_bank) { diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 53ea30d768d9..b32b87945538 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -370,7 +370,7 @@ struct hv_tsc_emulation_status { #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3) enum HV_GENERIC_SET_FORMAT { - HV_GENERIC_SET_SPARCE_4K, + HV_GENERIC_SET_SPARSE_4K, HV_GENERIC_SET_ALL, }; -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/5] X86: Hyper-V: Enable IPI enlightenments
From: "K. Y. Srinivasan" Hyper-V supports hypercalls to implement IPI; use them. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/hv_apic.c | 125 + arch/x86/hyperv/hv_init.c | 17 + arch/x86/include/asm/hyperv-tlfs.h | 9 +++ arch/x86/include/asm/mshyperv.h| 1 + 4 files changed, 152 insertions(+) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index e0a5b36208fc..7f3322ecfb01 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -30,6 +30,14 @@ #include #include +struct ipi_arg_non_ex { + u32 vector; + u32 reserved; + u64 cpu_mask; +}; + +static struct apic orig_apic; + static u64 hv_apic_icr_read(void) { u64 reg_val; @@ -85,8 +93,125 @@ static void hv_apic_eoi_write(u32 reg, u32 val) wrmsr(HV_X64_MSR_EOI, val, 0); } +/* + * IPI implementation on Hyper-V. + */ + +static int __send_ipi_mask(const struct cpumask *mask, int vector) +{ + int cur_cpu, vcpu; + struct ipi_arg_non_ex **arg; + struct ipi_arg_non_ex *ipi_arg; + int ret = 1; + unsigned long flags; + + if (cpumask_empty(mask)) + return 0; + + if (!hv_hypercall_pg) + return ret; + + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + return ret; + + local_irq_save(flags); + arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); + + ipi_arg = *arg; + if (unlikely(!ipi_arg)) + goto ipi_mask_done; + + + ipi_arg->vector = vector; + ipi_arg->reserved = 0; + ipi_arg->cpu_mask = 0; + + for_each_cpu(cur_cpu, mask) { + vcpu = hv_cpu_number_to_vp_number(cur_cpu); + if (vcpu >= 64) + goto ipi_mask_done; + + __set_bit(vcpu, (unsigned long *)&ipi_arg->cpu_mask); + } + + ret = hv_do_hypercall(HVCALL_SEND_IPI, ipi_arg, NULL); + +ipi_mask_done: + local_irq_restore(flags); + return ret; +} + +static int __send_ipi_one(int cpu, int vector) +{ + struct cpumask mask = CPU_MASK_NONE; + + cpumask_set_cpu(cpu, &mask); + return __send_ipi_mask(&mask, vector); +} + +static void hv_send_ipi(int cpu, int vector) +{ + if (__send_ipi_one(cpu, vector)) + orig_apic.send_IPI(cpu, vector); +} + +static void hv_send_ipi_mask(const struct cpumask *mask, int vector) +{ + if (__send_ipi_mask(mask, vector)) + orig_apic.send_IPI_mask(mask, vector); +} + +static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector) +{ + unsigned int this_cpu = smp_processor_id(); + struct cpumask new_mask; + const struct cpumask *local_mask; + + cpumask_copy(&new_mask, mask); + cpumask_clear_cpu(this_cpu, &new_mask); + local_mask = &new_mask; + if (__send_ipi_mask(local_mask, vector)) + orig_apic.send_IPI_mask_allbutself(mask, vector); +} + +static void hv_send_ipi_allbutself(int vector) +{ + hv_send_ipi_mask_allbutself(cpu_online_mask, vector); +} + +static void hv_send_ipi_all(int vector) +{ + if (__send_ipi_mask(cpu_online_mask, vector)) + orig_apic.send_IPI_all(vector); +} + +static void hv_send_ipi_self(int vector) +{ + if (__send_ipi_one(smp_processor_id(), vector)) + orig_apic.send_IPI_self(vector); +} + void __init hv_apic_init(void) { + if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) { + if (hyperv_pcpu_input_arg == NULL) + goto msr_based_access; + + pr_info("Hyper-V: Using IPI hypercalls\n"); + /* +* Set the IPI entry points. +*/ + orig_apic = *apic; + + apic->send_IPI = hv_send_ipi; + apic->send_IPI_mask = hv_send_ipi_mask; + apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself; + apic->send_IPI_allbutself = hv_send_ipi_allbutself; + apic->send_IPI_all = hv_send_ipi_all; + apic->send_IPI_self = hv_send_ipi_self; + } + +msr_based_access: if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { pr_info("Hyper-V: Using MSR ased APIC access\n"); apic_set_eoi_write(hv_apic_eoi_write); diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 71e50fc2b7ef..a895662b6b4c 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index); struct hv_vp_assist_page **hv_vp_assist_page; EXPORT_SYMBOL_GPL(hv_vp_assist_page); +void __percpu **hyperv_pcpu_input_arg; +EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); + u32 hv_max_vp_index; static int hv_cpu_init(unsigned int cpu) { u64 msr_vp_index; struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
[PATCH 1/5] X86: Hyper-V: Enlighten APIC access
From: "K. Y. Srinivasan" Hyper-V supports MSR based APIC access; implement the enlightenment. Signed-off-by: K. Y. Srinivasan --- arch/x86/hyperv/Makefile| 2 +- arch/x86/hyperv/hv_apic.c | 98 + arch/x86/hyperv/hv_init.c | 5 ++- arch/x86/include/asm/mshyperv.h | 6 ++- 4 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 arch/x86/hyperv/hv_apic.c diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 367a8203cfcf..00ce4df01a09 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1 +1 @@ -obj-y := hv_init.o mmu.o +obj-y := hv_init.o mmu.o hv_apic.o diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c new file mode 100644 index ..e0a5b36208fc --- /dev/null +++ b/arch/x86/hyperv/hv_apic.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Hyper-V specific APIC code. + * + * Copyright (C) 2018, Microsoft, Inc. + * + * Author : K. Y. Srinivasan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u64 hv_apic_icr_read(void) +{ + u64 reg_val; + + rdmsrl(HV_X64_MSR_ICR, reg_val); + return reg_val; +} + +static void hv_apic_icr_write(u32 low, u32 id) +{ + u64 reg_val; + + reg_val = SET_APIC_DEST_FIELD(id); + reg_val = reg_val << 32; + reg_val |= low; + + wrmsrl(HV_X64_MSR_ICR, reg_val); +} + +static u32 hv_apic_read(u32 reg) +{ + u32 reg_val, hi; + + switch (reg) { + case APIC_EOI: + rdmsr(HV_X64_MSR_EOI, reg_val, hi); + return reg_val; + case APIC_TASKPRI: + rdmsr(HV_X64_MSR_TPR, reg_val, hi); + return reg_val; + + default: + return native_apic_mem_read(reg); + } +} + +static void hv_apic_write(u32 reg, u32 val) +{ + switch (reg) { + case APIC_EOI: + wrmsr(HV_X64_MSR_EOI, val, 0); + break; + case APIC_TASKPRI: + wrmsr(HV_X64_MSR_TPR, val, 0); + break; + default: + native_apic_mem_write(reg, val); + } +} + +static void hv_apic_eoi_write(u32 reg, u32 val) +{ + wrmsr(HV_X64_MSR_EOI, val, 0); +} + +void __init hv_apic_init(void) +{ + if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { + pr_info("Hyper-V: Using MSR ased APIC access\n"); + apic_set_eoi_write(hv_apic_eoi_write); + apic->read = hv_apic_read; + apic->write = hv_apic_write; + apic->icr_write = hv_apic_icr_write; + apic->icr_read = hv_apic_icr_read; + } +} diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index cfecc2272f2d..71e50fc2b7ef 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -242,8 +242,9 @@ static int hv_cpu_die(unsigned int cpu) * * 1. Setup the hypercall page. * 2. Register Hyper-V specific clocksource. + * 3. Setup Hyper-V specific APIC entry points. */ -void hyperv_init(void) +void __init hyperv_init(void) { u64 guest_id, required_msrs; union hv_x64_msr_hypercall_contents hypercall_msr; @@ -298,6 +299,8 @@ void hyperv_init(void) hyper_alloc_mmu(); + hv_apic_init(); + /* * Register Hyper-V specific clocksource. */ diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index b90e79610cf7..bcced50037c1 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -258,7 +258,7 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) return hv_vp_index[cpu_number]; } -void hyperv_init(void); +void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); void hyper_alloc_mmu(void); void hyperv_report_panic(struct pt_regs *regs, long err); @@ -269,14 +269,16 @@ 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); +void hv_apic_init(void); #else /* CONFIG_HYPERV */ -static inline void hyperv_init(void) {} +static __init inline void hyperv_init(void) {} static inline bool hv_is_hyperv_initialized(void) { return false; } static inline void hyperv_cleanup(void) {} static inline void hyperv_setup_mmu_ops(void) {} static inline void set_hv_tscchange_cb(void
[PATCH 3/4] hv: add SPDX license to trace
From: Stephen Hemminger Missing license on Hyper-V VMBUS tracing files. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_trace.c | 2 ++ drivers/hv/hv_trace.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/hv/hv_trace.c b/drivers/hv/hv_trace.c index df47acd01a81..38d359cf1e70 100644 --- a/drivers/hv/hv_trace.c +++ b/drivers/hv/hv_trace.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + #include "hyperv_vmbus.h" #define CREATE_TRACE_POINTS diff --git a/drivers/hv/hv_trace.h b/drivers/hv/hv_trace.h index d635ee95b20d..999f80a63bff 100644 --- a/drivers/hv/hv_trace.h +++ b/drivers/hv/hv_trace.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + #undef TRACE_SYSTEM #define TRACE_SYSTEM hyperv -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/4] Drivers: hv: vmbus: respect what we get from hv_get_synint_state()
From: Dexuan Cui I didn't really hit a bug, but just happened to notice the redundant line. Signed-off-by: Dexuan Cui Cc: Stephen Hemminger Cc: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index b1f6793acf4c..8137b3885b99 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -302,7 +302,6 @@ int hv_synic_init(unsigned int cpu) hv_get_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); - shared_sint.as_uint64 = 0; shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; shared_sint.masked = false; if (ms_hyperv.hints & HV_X64_DEPRECATING_AEOI_RECOMMENDED) -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 4/4] hv: add SPDX license id to Kconfig
From: Stephen Hemminger Missing license on Kconfig file. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 50b89ea0e60f..97954f575c3f 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + menu "Microsoft Hyper-V guest support" config HYPERV -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/4] Drivers: hv: vmbus: do not mark HV_PCIE as perf_device
From: Dexuan Cui The pci-hyperv driver's channel callback hv_pci_onchannelcallback() is not really a hot path, so we don't need to mark it as a perf_device, meaning with this patch all HV_PCIE channels' target_cpu will be CPU0. Signed-off-by: Dexuan Cui Cc: sta...@vger.kernel.org Cc: Stephen Hemminger Cc: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index c6d9d19bc04e..ecc2bd275a73 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -71,7 +71,7 @@ static const struct vmbus_device vmbus_devs[] = { /* PCIE */ { .dev_type = HV_PCIE, HV_PCIE_GUID, - .perf_device = true, + .perf_device = false, }, /* Synthetic Frame Buffer */ -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/4] Drivers: hv: vmbus: Miscellaneous fixes
From: "K. Y. Srinivasan" Some miscellaneous fixes and adjustments. Dexuan Cui (2): Drivers: hv: vmbus: respect what we get from hv_get_synint_state() Drivers: hv: vmbus: do not mark HV_PCIE as perf_device Stephen Hemminger (2): hv: add SPDX license to trace hv: add SPDX license id to Kconfig drivers/hv/Kconfig| 2 ++ drivers/hv/channel_mgmt.c | 2 +- drivers/hv/hv.c | 1 - drivers/hv/hv_trace.c | 2 ++ drivers/hv/hv_trace.h | 2 ++ 5 files changed, 7 insertions(+), 2 deletions(-) -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/1] Drivers: hv: vmbus: Fix ring buffer signaling
From: Michael Kelley Fix bugs in signaling the Hyper-V host when freeing space in the host->guest ring buffer: 1. The interrupt_mask must not be used to determine whether to signal on the host->guest ring buffer 2. The ring buffer write_index must be read (via hv_get_bytes_to_write) *after* pending_send_sz is read in order to avoid a race condition 3. Comparisons with pending_send_sz must treat the "equals" case as not-enough-space 4. Don't signal if the pending_send_sz feature is not present. Older versions of Hyper-V that don't implement this feature will poll. Fixes: 03bad714a161 ("vmbus: more host signalling avoidance") Cc: Stable # 4.14 and above Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- drivers/hv/ring_buffer.c | 52 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 1aa17795727b..3cd7f29906ae 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -376,13 +376,24 @@ __hv_pkt_iter_next(struct vmbus_channel *channel, } EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); +/* How many bytes were read in this iterator cycle */ +static u32 hv_pkt_iter_bytes_read(const struct hv_ring_buffer_info *rbi, + u32 start_read_index) +{ + if (rbi->priv_read_index >= start_read_index) + return rbi->priv_read_index - start_read_index; + else + return rbi->ring_datasize - start_read_index + + rbi->priv_read_index; +} + /* * Update host ring buffer after iterating over packets. */ void hv_pkt_iter_close(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; - u32 orig_write_sz = hv_get_bytes_to_write(rbi); + u32 curr_write_sz, pending_sz, bytes_read, start_read_index; /* * Make sure all reads are done before we update the read index since @@ -390,8 +401,12 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) * is updated. */ virt_rmb(); + start_read_index = rbi->ring_buffer->read_index; rbi->ring_buffer->read_index = rbi->priv_read_index; + if (!rbi->ring_buffer->feature_bits.feat_pending_send_sz) + return; + /* * Issue a full memory barrier before making the signaling decision. * Here is the reason for having this barrier: @@ -405,26 +420,29 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) */ virt_mb(); - /* If host has disabled notifications then skip */ - if (rbi->ring_buffer->interrupt_mask) + pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); + if (!pending_sz) return; - if (rbi->ring_buffer->feature_bits.feat_pending_send_sz) { - u32 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); + /* +* Ensure the read of write_index in hv_get_bytes_to_write() +* happens after the read of pending_send_sz. +*/ + virt_rmb(); + curr_write_sz = hv_get_bytes_to_write(rbi); + bytes_read = hv_pkt_iter_bytes_read(rbi, start_read_index); - /* -* If there was space before we began iteration, -* then host was not blocked. Also handles case where -* pending_sz is zero then host has nothing pending -* and does not need to be signaled. -*/ - if (orig_write_sz > pending_sz) - return; + /* +* If there was space before we began iteration, +* then host was not blocked. +*/ - /* If pending write will not fit, don't give false hope. */ - if (hv_get_bytes_to_write(rbi) < pending_sz) - return; - } + if (curr_write_sz - bytes_read > pending_sz) + return; + + /* If pending write will not fit, don't give false hope. */ + if (curr_write_sz <= pending_sz) + return; vmbus_setevent(channel); } -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 08/12] Drivers: hv: vmbus: Implement Direct Mode for stimer0
From: Michael Kelley The 2016 version of Hyper-V offers the option to operate the guest VM per-vcpu stimer's in Direct Mode, which means the timer interupts on its own vector rather than queueing a VMbus message. Direct Mode reduces timer processing overhead in both the hypervisor and the guest, and avoids having timer interrupts pollute the VMbus interrupt stream for the synthetic NIC and storage. This patch enables Direct Mode by default on stimer0 when running on a version of Hyper-V that supports it. In prep for coming support of Hyper-V on ARM64, the arch independent portion of the code contains calls to routines that will be populated on ARM64 but are not needed and do nothing on x86. Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan --- arch/x86/entry/entry_32.S | 3 ++ arch/x86/entry/entry_64.S | 3 ++ arch/x86/include/asm/hardirq.h | 1 + arch/x86/include/asm/irq_vectors.h | 3 +- arch/x86/include/asm/mshyperv.h| 13 + arch/x86/include/uapi/asm/hyperv.h | 3 ++ arch/x86/kernel/cpu/mshyperv.c | 40 ++ arch/x86/kernel/irq.c | 7 + drivers/hv/hv.c| 59 -- drivers/hv/hyperv_vmbus.h | 4 ++- 10 files changed, 131 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 16c2c022540d..e12d60873376 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -903,6 +903,9 @@ BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, BUILD_INTERRUPT3(hyperv_reenlightenment_vector, HYPERV_REENLIGHTENMENT_VECTOR, hyperv_reenlightenment_intr) +BUILD_INTERRUPT3(hv_stimer0_callback_vector, HYPERV_STIMER0_VECTOR, +hv_stimer0_vector_handler) + #endif /* CONFIG_HYPERV */ ENTRY(page_fault) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 8971bd64d515..606118459133 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -1106,6 +1106,9 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \ apicinterrupt3 HYPERV_REENLIGHTENMENT_VECTOR \ hyperv_reenlightenment_vector hyperv_reenlightenment_intr + +apicinterrupt3 HYPERV_STIMER0_VECTOR \ + hv_stimer0_callback_vector hv_stimer0_vector_handler #endif /* CONFIG_HYPERV */ idtentry debug do_debughas_error_code=0 paranoid=1 shift_ist=DEBUG_STACK diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 7c341a74ec8c..5ea2afd4c871 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -40,6 +40,7 @@ typedef struct { #endif #if IS_ENABLED(CONFIG_HYPERV) unsigned int irq_hv_reenlightenment_count; + unsigned int hyperv_stimer0_count; #endif } cacheline_aligned irq_cpustat_t; diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index e71c1120426b..404c5fdff859 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -106,9 +106,10 @@ #if IS_ENABLED(CONFIG_HYPERV) #define HYPERV_REENLIGHTENMENT_VECTOR 0xee +#define HYPERV_STIMER0_VECTOR 0xed #endif -#define LOCAL_TIMER_VECTOR 0xed +#define LOCAL_TIMER_VECTOR 0xec #define NR_VECTORS 256 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 25283f7eb299..e73c4d0c06ad 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -173,6 +173,19 @@ void hv_remove_kexec_handler(void); void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); void hv_remove_crash_handler(void); +/* + * Routines for stimer0 Direct Mode handling. + * On x86/x64, there are no percpu actions to take. + */ +void hv_stimer0_vector_handler(struct pt_regs *regs); +void hv_stimer0_callback_vector(void); +int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void)); +void hv_remove_stimer0_irq(int irq); + +static inline void hv_enable_stimer0_percpu_irq(int irq) {} +static inline void hv_disable_stimer0_percpu_irq(int irq) {} + + #if IS_ENABLED(CONFIG_HYPERV) extern struct clocksource *hyperv_cs; extern void *hv_hypercall_pg; diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 099414345865..6c0c3a3b631c 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -77,6 +77,9 @@ /* Crash MSR available */ #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10) +/* stimer Direct Mode is available */ +#define HV_X64_STIMER_DIRECT_MODE_AVAILABLE(1 << 19) + /* * Feature identification: EBX indicates which flags were specified at * partition creation. The format is the same as the partition creation diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 9340f41ce8d3..4488cf0dd499 100644 --- a/arch/x86/ker
[PATCH V2 10/12] hv_balloon: simplify hv_online_page()/hv_page_online_one()
From: Vitaly Kuznetsov Instead of doing pfn_to_page() and continuosly casting page to unsigned long just cache the pfn of the page with page_to_pfn(). Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_balloon.c | 27 +-- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 1aece72da9ba..5b8e1ad1bcfe 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -612,28 +612,17 @@ static struct notifier_block hv_memory_nb = { /* Check if the particular page is backed and can be onlined and online it. */ static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg) { - unsigned long cur_start_pgp; - unsigned long cur_end_pgp; struct hv_hotadd_gap *gap; - - cur_start_pgp = (unsigned long)pfn_to_page(has->covered_start_pfn); - cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn); + unsigned long pfn = page_to_pfn(pg); /* The page is not backed. */ - if (((unsigned long)pg < cur_start_pgp) || - ((unsigned long)pg >= cur_end_pgp)) + if ((pfn < has->covered_start_pfn) || (pfn >= has->covered_end_pfn)) return; /* Check for gaps. */ list_for_each_entry(gap, &has->gap_list, list) { - cur_start_pgp = (unsigned long) - pfn_to_page(gap->start_pfn); - cur_end_pgp = (unsigned long) - pfn_to_page(gap->end_pfn); - if (((unsigned long)pg >= cur_start_pgp) && - ((unsigned long)pg < cur_end_pgp)) { + if ((pfn >= gap->start_pfn) && (pfn < gap->end_pfn)) return; - } } /* This frame is currently backed; online the page. */ @@ -726,19 +715,13 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, static void hv_online_page(struct page *pg) { struct hv_hotadd_state *has; - unsigned long cur_start_pgp; - unsigned long cur_end_pgp; unsigned long flags; + unsigned long pfn = page_to_pfn(pg); spin_lock_irqsave(&dm_device.ha_lock, flags); list_for_each_entry(has, &dm_device.ha_region_list, list) { - cur_start_pgp = (unsigned long) - pfn_to_page(has->start_pfn); - cur_end_pgp = (unsigned long)pfn_to_page(has->end_pfn); - /* The page belongs to a different HAS. */ - if (((unsigned long)pg < cur_start_pgp) || - ((unsigned long)pg >= cur_end_pgp)) + if ((pfn < has->start_pfn) || (pfn >= has->end_pfn)) continue; hv_page_online_one(has, pg); -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 05/12] tools: hv: include string.h in hv_fcopy_daemon
From: Olaf Hering The usage of strchr requires inclusion of string.h. Fixes: 0c38cda64aec ("tools: hv: remove unnecessary header files and netlink related code") Signed-off-by: Olaf Hering Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_fcopy_daemon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 785f4e95148c..d78aed86af09 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 06/12] vmbus/ring_buffer: remove some redundant helper function.
From: "lantianyu1...@gmail.com" Some hv_get/set** helper functions in ring_buffer code are only called once or not used. This patch is to clear up these codes. Signed-off-by: Tianyu Lan Signed-off-by: K. Y. Srinivasan --- drivers/hv/ring_buffer.c | 49 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 50e071444a5c..1aa17795727b 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -78,46 +78,6 @@ static void hv_signal_on_write(u32 old_write, struct vmbus_channel *channel) vmbus_setevent(channel); } -/* Get the next write location for the specified ring buffer. */ -static inline u32 -hv_get_next_write_location(struct hv_ring_buffer_info *ring_info) -{ - u32 next = ring_info->ring_buffer->write_index; - - return next; -} - -/* Set the next write location for the specified ring buffer. */ -static inline void -hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, -u32 next_write_location) -{ - ring_info->ring_buffer->write_index = next_write_location; -} - -/* Set the next read location for the specified ring buffer. */ -static inline void -hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, - u32 next_read_location) -{ - ring_info->ring_buffer->read_index = next_read_location; - ring_info->priv_read_index = next_read_location; -} - -/* Get the size of the ring buffer. */ -static inline u32 -hv_get_ring_buffersize(const struct hv_ring_buffer_info *ring_info) -{ - return ring_info->ring_datasize; -} - -/* Get the read and write indices as u64 of the specified ring buffer. */ -static inline u64 -hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) -{ - return (u64)ring_info->ring_buffer->write_index << 32; -} - /* * Helper routine to copy from source to ring buffer. * Assume there is enough room. Handles wrap-around in dest case only!! @@ -129,7 +89,7 @@ static u32 hv_copyto_ringbuffer( u32 srclen) { void *ring_buffer = hv_get_ring_buffer(ring_info); - u32 ring_buffer_size = hv_get_ring_buffersize(ring_info); + u32 ring_buffer_size = ring_info->ring_datasize; memcpy(ring_buffer + start_write_offset, src, srclen); @@ -275,8 +235,7 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, } /* Write to the ring buffer */ - next_write_location = hv_get_next_write_location(outring_info); - + next_write_location = outring_info->ring_buffer->write_index; old_write = next_write_location; for (i = 0; i < kv_count; i++) { @@ -287,7 +246,7 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, } /* Set previous packet start */ - prev_indices = hv_get_ring_bufferindices(outring_info); + prev_indices = (u64)outring_info->ring_buffer->write_index << 32; next_write_location = hv_copyto_ringbuffer(outring_info, next_write_location, @@ -298,7 +257,7 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, virt_mb(); /* Now, update the write location */ - hv_set_next_write_location(outring_info, next_write_location); + outring_info->ring_buffer->write_index = next_write_location; spin_unlock_irqrestore(&outring_info->ring_lock, flags); -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 12/12] hv_balloon: trace post_status
From: Vitaly Kuznetsov Hyper-V balloon driver makes non-trivial calculations to convert Linux's representation of free/used memory to what Hyper-V host expects to see. Add a tracepoint to see what's being sent and where the data comes from. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/Makefile | 1 + drivers/hv/hv_balloon.c | 6 ++ drivers/hv/hv_trace_balloon.h | 48 +++ 3 files changed, 55 insertions(+) create mode 100644 drivers/hv/hv_trace_balloon.h diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index 14c22786b519..a1eec7177c2d 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o CFLAGS_hv_trace.o = -I$(src) +CFLAGS_hv_balloon.o = -I$(src) hv_vmbus-y := vmbus_drv.o \ hv.o connection.o channel.o \ diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 7514a32d0de4..b3e9f13f8bc3 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -34,6 +34,9 @@ #include +#define CREATE_TRACE_POINTS +#include "hv_trace_balloon.h" + /* * We begin with definitions supporting the Dynamic Memory protocol * with the host. @@ -1159,6 +1162,9 @@ static void post_status(struct hv_dynmem_device *dm) dm->num_pages_added - dm->num_pages_onlined : 0) + compute_balloon_floor(); + trace_balloon_status(status.num_avail, status.num_committed, +vm_memory_committed(), dm->num_pages_ballooned, +dm->num_pages_added, dm->num_pages_onlined); /* * If our transaction ID is no longer current, just don't * send the status. This can happen if we were interrupted diff --git a/drivers/hv/hv_trace_balloon.h b/drivers/hv/hv_trace_balloon.h new file mode 100644 index ..93082888aec3 --- /dev/null +++ b/drivers/hv/hv_trace_balloon.h @@ -0,0 +1,48 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM hyperv + +#if !defined(_HV_TRACE_BALLOON_H) || defined(TRACE_HEADER_MULTI_READ) +#define _HV_TRACE_BALLOON_H + +#include + +TRACE_EVENT(balloon_status, + TP_PROTO(u64 available, u64 committed, +unsigned long vm_memory_committed, +unsigned long pages_ballooned, +unsigned long pages_added, +unsigned long pages_onlined), + TP_ARGS(available, committed, vm_memory_committed, + pages_ballooned, pages_added, pages_onlined), + TP_STRUCT__entry( + __field(u64, available) + __field(u64, committed) + __field(unsigned long, vm_memory_committed) + __field(unsigned long, pages_ballooned) + __field(unsigned long, pages_added) + __field(unsigned long, pages_onlined) + ), + TP_fast_assign( + __entry->available = available; + __entry->committed = committed; + __entry->vm_memory_committed = vm_memory_committed; + __entry->pages_ballooned = pages_ballooned; + __entry->pages_added = pages_added; + __entry->pages_onlined = pages_onlined; + ), + TP_printk("available %lld, committed %lld; vm_memory_committed %ld;" + " pages_ballooned %ld, pages_added %ld, pages_onlined %ld", + __entry->available, __entry->committed, + __entry->vm_memory_committed, __entry->pages_ballooned, + __entry->pages_added, __entry->pages_onlined + ) + ); + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE hv_trace_balloon +#endif /* _HV_TRACE_BALLOON_H */ + +/* This part must be outside protection */ +#include -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 03/12] hv: Synthetic typo correction
From: Joe Perches Just a trivial tyop fix. Signed-off-by: Joe Perches Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index b6cacc4cccf2..31142b72f1b9 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -217,7 +217,7 @@ void hv_synic_free(void) } /* - * hv_synic_init - Initialize the Synthethic Interrupt Controller. + * hv_synic_init - Initialize the Synthetic Interrupt Controller. * * If it is already initialized by another entity (ie x2v shim), we need to * retrieve the initialized message and event pages. Otherwise, we create and -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 04/12] tools: hv: fix compiler warnings about major/target_fname
From: Dexuan Cui This patch fixes the below warnings with new glibc and gcc: hv_vss_daemon.c:100:13: warning: In the GNU C Library, "major" is defined by . For historical compatibility, it is currently defined by as well, but we plan to remove this soon. To use "major", include directly. hv_fcopy_daemon.c:42:2: note: 'snprintf' output between 2 and 1040 bytes into a destination of size 260 Signed-off-by: Dexuan Cui Cc: Stephen Hemminger Cc: K. Y. Srinivasan Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_fcopy_daemon.c | 3 ++- tools/hv/hv_vss_daemon.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 457a1521f32f..785f4e95148c 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c @@ -23,13 +23,14 @@ #include #include #include +#include #include #include #include #include static int target_fd; -static char target_fname[W_MAX_PATH]; +static char target_fname[PATH_MAX]; static unsigned long long filesize; static int hv_start_fcopy(struct hv_start_fcopy *smsg) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index b2b4ebffab8c..34031a297f02 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 09/12] hv_balloon: fix printk loglevel
From: Vitaly Kuznetsov We have a mix of different ideas of which loglevel should be used. Unify on the following: - pr_info() for normal operation - pr_warn() for 'strange' host behavior - pr_err() for all errors. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_balloon.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index db0e6652d7ef..1aece72da9ba 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -691,7 +691,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, (HA_CHUNK << PAGE_SHIFT)); if (ret) { - pr_warn("hot_add memory failed error is %d\n", ret); + pr_err("hot_add memory failed error is %d\n", ret); if (ret == -EEXIST) { /* * This error indicates that the error @@ -1014,7 +1014,7 @@ static void hot_add_req(struct work_struct *dummy) resp.result = 0; if (!do_hot_add || (resp.page_count == 0)) - pr_info("Memory hot add failed\n"); + pr_err("Memory hot add failed\n"); dm->state = DM_INITIALIZED; resp.hdr.trans_id = atomic_inc_return(&trans_id); @@ -1041,7 +1041,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) break; default: - pr_info("Received Unknown type: %d\n", info_hdr->type); + pr_warn("Received Unknown type: %d\n", info_hdr->type); } } @@ -1290,7 +1290,7 @@ static void balloon_up(struct work_struct *dummy) /* * Free up the memory we allocatted. */ - pr_info("Balloon response failed\n"); + pr_err("Balloon response failed\n"); for (i = 0; i < bl_resp->range_count; i++) free_balloon_pages(&dm_device, @@ -1421,7 +1421,7 @@ static void cap_resp(struct hv_dynmem_device *dm, struct dm_capabilities_resp_msg *cap_resp) { if (!cap_resp->is_accepted) { - pr_info("Capabilities not accepted by host\n"); + pr_err("Capabilities not accepted by host\n"); dm->state = DM_INIT_ERROR; } complete(&dm->host_event); @@ -1508,7 +1508,7 @@ static void balloon_onchannelcallback(void *context) break; default: - pr_err("Unhandled message: type: %d\n", dm_hdr->type); + pr_warn("Unhandled message: type: %d\n", dm_hdr->type); } } -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 11/12] hv_balloon: fix bugs in num_pages_onlined accounting
From: Vitaly Kuznetsov Our num_pages_onlined accounting is buggy: 1) In case we're offlining a memory block which was present at boot (e.g. when there was no hotplug at all) we subtract 32k from 0 and as num_pages_onlined is unsigned get a very big positive number. 2) Commit 6df8d9aaf3af ("Drivers: hv: balloon: Correctly update onlined page count") made num_pages_onlined counter accurate on onlining but totally incorrect on offlining for partly populated regions: no matter how many pages were onlined and what was actually added to num_pages_onlined counter we always subtract the full region (32k) so again, num_pages_onlined can wrap around zero. By onlining/offlining the same partly populated region multiple times we can make the situation worse. Solve these issues by doing accurate accounting on offlining: walk HAS list, check for covered range and gaps. Fixes: 6df8d9aaf3af ("Drivers: hv: balloon: Correctly update onlined page count") Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_balloon.c | 82 + 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 5b8e1ad1bcfe..7514a32d0de4 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -576,11 +576,65 @@ static struct hv_dynmem_device dm_device; static void post_status(struct hv_dynmem_device *dm); #ifdef CONFIG_MEMORY_HOTPLUG +static inline bool has_pfn_is_backed(struct hv_hotadd_state *has, +unsigned long pfn) +{ + struct hv_hotadd_gap *gap; + + /* The page is not backed. */ + if ((pfn < has->covered_start_pfn) || (pfn >= has->covered_end_pfn)) + return false; + + /* Check for gaps. */ + list_for_each_entry(gap, &has->gap_list, list) { + if ((pfn >= gap->start_pfn) && (pfn < gap->end_pfn)) + return false; + } + + return true; +} + +static unsigned long hv_page_offline_check(unsigned long start_pfn, + unsigned long nr_pages) +{ + unsigned long pfn = start_pfn, count = 0; + struct hv_hotadd_state *has; + bool found; + + while (pfn < start_pfn + nr_pages) { + /* +* Search for HAS which covers the pfn and when we find one +* count how many consequitive PFNs are covered. +*/ + found = false; + list_for_each_entry(has, &dm_device.ha_region_list, list) { + while ((pfn >= has->start_pfn) && + (pfn < has->end_pfn) && + (pfn < start_pfn + nr_pages)) { + found = true; + if (has_pfn_is_backed(has, pfn)) + count++; + pfn++; + } + } + + /* +* This PFN is not in any HAS (e.g. we're offlining a region +* which was present at boot), no need to account for it. Go +* to the next one. +*/ + if (!found) + pfn++; + } + + return count; +} + static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) { struct memory_notify *mem = (struct memory_notify *)v; - unsigned long flags; + unsigned long flags, pfn_count; switch (val) { case MEM_ONLINE: @@ -593,7 +647,19 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, case MEM_OFFLINE: spin_lock_irqsave(&dm_device.ha_lock, flags); - dm_device.num_pages_onlined -= mem->nr_pages; + pfn_count = hv_page_offline_check(mem->start_pfn, + mem->nr_pages); + if (pfn_count <= dm_device.num_pages_onlined) { + dm_device.num_pages_onlined -= pfn_count; + } else { + /* +* We're offlining more pages than we managed to online. +* This is unexpected. In any case don't let +* num_pages_onlined wrap around zero. +*/ + WARN_ON_ONCE(1); + dm_device.num_pages_onlined = 0; + } spin_unlock_irqrestore(&dm_device.ha_lock, flags); break; case MEM_GOING_ONLINE: @@ -612,19 +678,9 @@ static struct notifier_block hv_memory_nb = { /* Check if the particular page is backed and can be onlined and online it. */ static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg) { - struct hv_hotadd_gap *gap; - unsigned long pf
[PATCH V2 01/12] tools/hv: Fix IP reporting by KVP daemon with SRIOV
From: Haiyang Zhang On Hyper-V the VF NIC has the same MAC as the related synthetic NIC. VF NIC can work under the synthetic NIC transparently, without its own IP address. The existing KVP daemon only gets IP from the first NIC matching a MAC address, and may not be able to find the IP in this case. This patch fixes the problem by searching the NIC matching the MAC, and having an IP address. So, the IP address will be found and reported to the host successfully. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan --- tools/hv/hv_kvp_daemon.c | 138 ++- 1 file changed, 65 insertions(+), 73 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 4c99c57736ce..dbf6e8bd98ba 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -634,64 +634,6 @@ static char *kvp_if_name_to_mac(char *if_name) return mac_addr; } - -/* - * Retrieve the interface name given tha MAC address. - */ - -static char *kvp_mac_to_if_name(char *mac) -{ - DIR *dir; - struct dirent *entry; - FILE*file; - char*p, *x; - char*if_name = NULL; - charbuf[256]; - char dev_id[PATH_MAX]; - unsigned int i; - - dir = opendir(KVP_NET_DIR); - if (dir == NULL) - return NULL; - - while ((entry = readdir(dir)) != NULL) { - /* -* Set the state for the next pass. -*/ - snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR, -entry->d_name); - - file = fopen(dev_id, "r"); - if (file == NULL) - continue; - - p = fgets(buf, sizeof(buf), file); - if (p) { - x = strchr(p, '\n'); - if (x) - *x = '\0'; - - for (i = 0; i < strlen(p); i++) - p[i] = toupper(p[i]); - - if (!strcmp(p, mac)) { - /* -* Found the MAC match; return the interface -* name. The caller will free the memory. -*/ - if_name = strdup(entry->d_name); - fclose(file); - break; - } - } - fclose(file); - } - - closedir(dir); - return if_name; -} - - static void kvp_process_ipconfig_file(char *cmd, char *config_buf, unsigned int len, int element_size, int offset) @@ -997,6 +939,70 @@ kvp_get_ip_info(int family, char *if_name, int op, return error; } +/* + * Retrieve the IP given the MAC address. + */ +static int kvp_mac_to_ip(struct hv_kvp_ipaddr_value *kvp_ip_val) +{ + char *mac = (char *)kvp_ip_val->adapter_id; + DIR *dir; + struct dirent *entry; + FILE*file; + char*p, *x; + char*if_name = NULL; + charbuf[256]; + char dev_id[PATH_MAX]; + unsigned int i; + int error = HV_E_FAIL; + + dir = opendir(KVP_NET_DIR); + if (dir == NULL) + return HV_E_FAIL; + + while ((entry = readdir(dir)) != NULL) { + /* +* Set the state for the next pass. +*/ + snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR, +entry->d_name); + + file = fopen(dev_id, "r"); + if (file == NULL) + continue; + + p = fgets(buf, sizeof(buf), file); + fclose(file); + if (!p) + continue; + + x = strchr(p, '\n'); + if (x) + *x = '\0'; + + for (i = 0; i < strlen(p); i++) + p[i] = toupper(p[i]); + + if (strcmp(p, mac)) + continue; + + /* +* Found the MAC match. +* A NIC (e.g. VF) matching the MAC, but without IP, is skipped. +*/ + if_name = entry->d_name; + if (!if_name) + continue; + + error = kvp_get_ip_info(0, if_name, KVP_OP_GET_IP_INFO, + kvp_ip_val, MAX_IP_ADDR_SIZE * 2); + + if (!error && strlen((char *)kvp_ip_val->ip_addr)) + break; + } + + closedir(dir); + return error; +} static int expand_ipv6(char *addr, int type) { @@ -1472,26 +1478,12 @@ int main(int argc, char *argv[]) switch (op) { case KVP_OP_GET_IP_INFO: kvp_ip_val = &hv_msg->body.kvp_ip_val; -
[PATCH V2 07/12] hv_vmbus: Correct the stale comments regarding cpu affinity
From: Haiyang Zhang The comments doesn't match what the current code does, also have a typo. This patch corrects them. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 6 ++ include/linux/hyperv.h| 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index c21020b69114..c6d9d19bc04e 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -596,10 +596,8 @@ static int next_numa_node_id; /* * Starting with Win8, we can statically distribute the incoming * channel interrupt load by binding a channel to VCPU. - * We do this in a hierarchical fashion: - * First distribute the primary channels across available NUMA nodes - * and then distribute the subchannels amongst the CPUs in the NUMA - * node assigned to the primary channel. + * We distribute the interrupt loads to one or more NUMA nodes based on + * the channel's affinity_policy. * * For pre-win8 hosts or non-performance critical channels we assign the * first CPU in the first NUMA node. diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 93bd6fcd6e62..2048f3c3b68a 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -844,7 +844,7 @@ struct vmbus_channel { /* * NUMA distribution policy: -* We support teo policies: +* We support two policies: * 1) Balanced: Here all performance critical channels are *distributed evenly amongst all the NUMA nodes. *This policy will be the default policy. -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 02/12] hyper-v: use GFP_KERNEL for hv_context.hv_numa_map
From: Jia-Ju Bai The kzalloc function is called with GFP_ATOMIC. But according to driver call graph, it is not in atomic context, namely no spinlock is held nor in an interrupt handler. This GFP_ATOMIC is unnecessary, and replace with GFP_KERNEL. Signed-off-by: Jia-Ju Bai Reviewed-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index fe96aab9e794..b6cacc4cccf2 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -147,7 +147,7 @@ int hv_synic_alloc(void) int cpu; hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids, -GFP_ATOMIC); +GFP_KERNEL); if (hv_context.hv_numa_map == NULL) { pr_err("Unable to allocate NUMA map\n"); goto err; -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V2 00/12] Drivers: hv: Miscellaneous fixes
From: "K. Y. Srinivasan" Miscellaneous fixes. V2: Only the patch "Drivers: hv: vmbus: Implement Direct Mode for stimer0" has been modified to address review comments from Dan Carpenter. Dexuan Cui (1): tools: hv: fix compiler warnings about major/target_fname Haiyang Zhang (2): tools/hv: Fix IP reporting by KVP daemon with SRIOV hv_vmbus: Correct the stale comments regarding cpu affinity Jia-Ju Bai (1): hyper-v: use GFP_KERNEL for hv_context.hv_numa_map Joe Perches (1): hv: Synthetic typo correction Michael Kelley (1): Drivers: hv: vmbus: Implement Direct Mode for stimer0 Olaf Hering (1): tools: hv: include string.h in hv_fcopy_daemon Vitaly Kuznetsov (4): hv_balloon: fix printk loglevel hv_balloon: simplify hv_online_page()/hv_page_online_one() hv_balloon: fix bugs in num_pages_onlined accounting hv_balloon: trace post_status lantianyu1...@gmail.com (1): vmbus/ring_buffer: remove some redundant helper function. arch/x86/entry/entry_32.S | 3 + arch/x86/entry/entry_64.S | 3 + arch/x86/include/asm/hardirq.h | 1 + arch/x86/include/asm/irq_vectors.h | 3 +- arch/x86/include/asm/mshyperv.h| 13 arch/x86/include/uapi/asm/hyperv.h | 3 + arch/x86/kernel/cpu/mshyperv.c | 40 +++ arch/x86/kernel/irq.c | 7 ++ drivers/hv/Makefile| 1 + drivers/hv/channel_mgmt.c | 6 +- drivers/hv/hv.c| 63 +++-- drivers/hv/hv_balloon.c| 121 ++-- drivers/hv/hv_trace_balloon.h | 48 + drivers/hv/hyperv_vmbus.h | 4 +- drivers/hv/ring_buffer.c | 49 ++--- include/linux/hyperv.h | 2 +- tools/hv/hv_fcopy_daemon.c | 4 +- tools/hv/hv_kvp_daemon.c | 138 + tools/hv/hv_vss_daemon.c | 1 + 19 files changed, 341 insertions(+), 169 deletions(-) create mode 100644 drivers/hv/hv_trace_balloon.h -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 03/12] hv: Synthetic typo correction
From: Joe Perches Just a trivial tyop fix. Signed-off-by: Joe Perches Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index b6cacc4cccf2..31142b72f1b9 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -217,7 +217,7 @@ void hv_synic_free(void) } /* - * hv_synic_init - Initialize the Synthethic Interrupt Controller. + * hv_synic_init - Initialize the Synthetic Interrupt Controller. * * If it is already initialized by another entity (ie x2v shim), we need to * retrieve the initialized message and event pages. Otherwise, we create and -- 2.15.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel