Message ID | 1584200119-18594-6-git-send-email-mikelley@microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Subject: Enable Linux guests on Hyper-V on ARM64 | expand |
On Sat, Mar 14, 2020 at 4:36 PM Michael Kelley <mikelley@microsoft.com> wrote: > > Add ARM64-specific code to set up and handle the interrupts > generated by Hyper-V for VMbus messages and for stimer expiration. > > This code is architecture dependent and is mostly driven by > architecture independent code in the VMbus driver and the > Hyper-V timer clocksource driver. > > This code is built only when CONFIG_HYPERV is enabled. > > Signed-off-by: Michael Kelley <mikelley@microsoft.com> This looks like it should be a nested irqchip driver instead, so your device drivers can use the normal request_irq() functions etc. Is anything preventing you from doing that? If so, please describe that in the changelog and in a comment in the driver. Arnd
From: Arnd Bergmann <arnd@arndb.de> > > On Sat, Mar 14, 2020 at 4:36 PM Michael Kelley <mikelley@microsoft.com> wrote: > > > > Add ARM64-specific code to set up and handle the interrupts > > generated by Hyper-V for VMbus messages and for stimer expiration. > > > > This code is architecture dependent and is mostly driven by > > architecture independent code in the VMbus driver and the > > Hyper-V timer clocksource driver. > > > > This code is built only when CONFIG_HYPERV is enabled. > > > > Signed-off-by: Michael Kelley <mikelley@microsoft.com> > > This looks like it should be a nested irqchip driver instead, so your > device drivers can use the normal request_irq() functions etc. > > Is anything preventing you from doing that? If so, please describe > that in the changelog and in a comment in the driver. > As mentioned in my reply on Patch 1, Hyper-V offers a limited synthetic interrupt controller managed by Linux code that's been around the last 10 years on the x86 side. For reasons that pre-date me, it was not written as an irqchip driver. Modulo the small routines you see in this patch, the code is architecture independent, and it seems we ought to keep the high degree of commonality. Re-architecting the arch independent code to model as an irqchip driver seems to carry some risk to the x86 side that has a lot of real-world usage today, but I'll take a look and see what the risks look like and if it adds any clarity.
On Wed, Mar 18, 2020 at 1:16 AM Michael Kelley <mikelley@microsoft.com> wrote: > From: Arnd Bergmann <arnd@arndb.de> > > On Sat, Mar 14, 2020 at 4:36 PM Michael Kelley <mikelley@microsoft.com> wrote: > > > > > > Add ARM64-specific code to set up and handle the interrupts > > > generated by Hyper-V for VMbus messages and for stimer expiration. > > > > > > This code is architecture dependent and is mostly driven by > > > architecture independent code in the VMbus driver and the > > > Hyper-V timer clocksource driver. > > > > > > This code is built only when CONFIG_HYPERV is enabled. > > > > > > Signed-off-by: Michael Kelley <mikelley@microsoft.com> > > > > This looks like it should be a nested irqchip driver instead, so your > > device drivers can use the normal request_irq() functions etc. > > > > Is anything preventing you from doing that? If so, please describe > > that in the changelog and in a comment in the driver. > > > > As mentioned in my reply on Patch 1, Hyper-V offers a limited synthetic > interrupt controller managed by Linux code that's been around the last > 10 years on the x86 side. For reasons that pre-date me, it was not written > as an irqchip driver. I think the reason is just that 10 years ago, we did not have the concept of irqchips as device drivers. > Modulo the small routines you see in this patch, the code is architecture > independent, and it seems we ought to keep the high degree of commonality. > Re-architecting the arch independent code to model as an irqchip driver seems > to carry some risk to the x86 side that has a lot of real-world usage today, but > I'll take a look and see what the risks look like and if it adds any clarity. How many drivers link against the custom interface? If it's less than 10, making it a real driver is probably not too hard to do. Arnd
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile index 1697d30..87c31c0 100644 --- a/arch/arm64/hyperv/Makefile +++ b/arch/arm64/hyperv/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 -obj-y := hv_core.o +obj-y := hv_core.o mshyperv.o diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c new file mode 100644 index 0000000..ae6ece6 --- /dev/null +++ b/arch/arm64/hyperv/mshyperv.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Core routines for interacting with Microsoft's Hyper-V hypervisor, + * including setting up VMbus and STIMER interrupts, and handling + * crashes and kexecs. These interactions are through a set of + * static "handler" variables set by the architecture independent + * VMbus and STIMER drivers. + * + * Copyright (C) 2019, Microsoft, Inc. + * + * Author : Michael Kelley <mikelley@microsoft.com> + */ + +#include <linux/types.h> +#include <linux/export.h> +#include <linux/interrupt.h> +#include <linux/kexec.h> +#include <linux/acpi.h> +#include <linux/ptrace.h> +#include <asm/hyperv-tlfs.h> +#include <asm/mshyperv.h> + +static void (*vmbus_handler)(void); +static void (*hv_stimer0_handler)(void); + +static int vmbus_irq; +static long __percpu *vmbus_evt; +static long __percpu *stimer0_evt; + +irqreturn_t hyperv_vector_handler(int irq, void *dev_id) +{ + vmbus_handler(); + return IRQ_HANDLED; +} + +/* Must be done just once */ +void hv_setup_vmbus_irq(void (*handler)(void)) +{ + int result; + + vmbus_handler = handler; + vmbus_irq = acpi_register_gsi(NULL, HYPERVISOR_CALLBACK_VECTOR, + ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + if (vmbus_irq <= 0) { + pr_err("Can't register Hyper-V VMBus GSI. Error %d", + vmbus_irq); + vmbus_irq = 0; + return; + } + vmbus_evt = alloc_percpu(long); + result = request_percpu_irq(vmbus_irq, hyperv_vector_handler, + "Hyper-V VMbus", vmbus_evt); + if (result) { + pr_err("Can't request Hyper-V VMBus IRQ %d. Error %d", + vmbus_irq, result); + free_percpu(vmbus_evt); + acpi_unregister_gsi(vmbus_irq); + vmbus_irq = 0; + } +} +EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq); + +/* Must be done just once */ +void hv_remove_vmbus_irq(void) +{ + if (vmbus_irq) { + free_percpu_irq(vmbus_irq, vmbus_evt); + free_percpu(vmbus_evt); + acpi_unregister_gsi(vmbus_irq); + } +} +EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq); + +/* Must be done by each CPU */ +void hv_enable_vmbus_irq(void) +{ + enable_percpu_irq(vmbus_irq, 0); +} +EXPORT_SYMBOL_GPL(hv_enable_vmbus_irq); + +/* Must be done by each CPU */ +void hv_disable_vmbus_irq(void) +{ + disable_percpu_irq(vmbus_irq); +} +EXPORT_SYMBOL_GPL(hv_disable_vmbus_irq); + +/* Routines to do per-architecture handling of STIMER0 when in Direct Mode */ + +static irqreturn_t hv_stimer0_vector_handler(int irq, void *dev_id) +{ + if (hv_stimer0_handler) + hv_stimer0_handler(); + return IRQ_HANDLED; +} + +int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void)) +{ + int localirq; + int result; + + localirq = acpi_register_gsi(NULL, HV_STIMER0_IRQNR, + ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + if (localirq <= 0) { + pr_err("Can't register Hyper-V stimer0 GSI. Error %d", + localirq); + *irq = 0; + return -1; + } + stimer0_evt = alloc_percpu(long); + result = request_percpu_irq(localirq, hv_stimer0_vector_handler, + "Hyper-V stimer0", stimer0_evt); + if (result) { + pr_err("Can't request Hyper-V stimer0 IRQ %d. Error %d", + localirq, result); + free_percpu(stimer0_evt); + acpi_unregister_gsi(localirq); + *irq = 0; + return -1; + } + + hv_stimer0_handler = handler; + *vector = HV_STIMER0_IRQNR; + *irq = localirq; + return 0; +} +EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq); + +void hv_remove_stimer0_irq(int irq) +{ + hv_stimer0_handler = NULL; + if (irq) { + free_percpu_irq(irq, stimer0_evt); + free_percpu(stimer0_evt); + acpi_unregister_gsi(irq); + } +} +EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
Add ARM64-specific code to set up and handle the interrupts generated by Hyper-V for VMbus messages and for stimer expiration. This code is architecture dependent and is mostly driven by architecture independent code in the VMbus driver and the Hyper-V timer clocksource driver. This code is built only when CONFIG_HYPERV is enabled. Signed-off-by: Michael Kelley <mikelley@microsoft.com> --- arch/arm64/hyperv/Makefile | 2 +- arch/arm64/hyperv/mshyperv.c | 139 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/hyperv/mshyperv.c