From afca4d95dd7d7936d46a0ff02169cc40f534a6a3 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Wed, 14 Jul 2021 11:34:45 -0700 Subject: Drivers: hv: Make portions of Hyper-V init code be arch neutral The code to allocate and initialize the hv_vp_index array is architecture neutral. Similarly, the code to allocate and populate the hypercall input and output arg pages is architecture neutral. Move both sets of code out from arch/x86 and into utility functions in drivers/hv/hv_common.c that can be shared by Hyper-V initialization on ARM64. No functional changes. However, the allocation of the hypercall input and output arg pages is done differently so that the size is always the Hyper-V page size, even if not the same as the guest page size (such as with ARM64's 64K page size). Signed-off-by: Michael Kelley Link: https://lore.kernel.org/r/1626287687-2045-2-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu --- drivers/hv/hv_common.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) (limited to 'drivers') diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 7f42da98d377..e836002bc0ce 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -15,9 +15,147 @@ #include #include #include +#include +#include #include #include +/* + * hv_root_partition and ms_hyperv are defined here with other Hyper-V + * specific globals so they are shared across all architectures and are + * built only when CONFIG_HYPERV is defined. But on x86, + * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not + * defined, and it uses these two variables. So mark them as __weak + * here, allowing for an overriding definition in the module containing + * ms_hyperv_init_platform(). + */ +bool __weak hv_root_partition; +EXPORT_SYMBOL_GPL(hv_root_partition); + +struct ms_hyperv_info __weak ms_hyperv; +EXPORT_SYMBOL_GPL(ms_hyperv); + +u32 *hv_vp_index; +EXPORT_SYMBOL_GPL(hv_vp_index); + +u32 hv_max_vp_index; +EXPORT_SYMBOL_GPL(hv_max_vp_index); + +void __percpu **hyperv_pcpu_input_arg; +EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); + +void __percpu **hyperv_pcpu_output_arg; +EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); + +/* + * Hyper-V specific initialization and shutdown code that is + * common across all architectures. Called from architecture + * specific initialization functions. + */ + +void __init hv_common_free(void) +{ + kfree(hv_vp_index); + hv_vp_index = NULL; + + free_percpu(hyperv_pcpu_output_arg); + hyperv_pcpu_output_arg = NULL; + + free_percpu(hyperv_pcpu_input_arg); + hyperv_pcpu_input_arg = NULL; +} + +int __init hv_common_init(void) +{ + int i; + + /* + * Allocate the per-CPU state for the hypercall input arg. + * If this allocation fails, we will not be able to setup + * (per-CPU) hypercall input page and thus this failure is + * fatal on Hyper-V. + */ + hyperv_pcpu_input_arg = alloc_percpu(void *); + BUG_ON(!hyperv_pcpu_input_arg); + + /* Allocate the per-CPU state for output arg for root */ + if (hv_root_partition) { + hyperv_pcpu_output_arg = alloc_percpu(void *); + BUG_ON(!hyperv_pcpu_output_arg); + } + + hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), + GFP_KERNEL); + if (!hv_vp_index) { + hv_common_free(); + return -ENOMEM; + } + + for (i = 0; i < num_possible_cpus(); i++) + hv_vp_index[i] = VP_INVAL; + + return 0; +} + +/* + * Hyper-V specific initialization and die code for + * individual CPUs that is common across all architectures. + * Called by the CPU hotplug mechanism. + */ + +int hv_common_cpu_init(unsigned int cpu) +{ + void **inputarg, **outputarg; + u64 msr_vp_index; + gfp_t flags; + int pgcount = hv_root_partition ? 2 : 1; + + /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */ + flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL; + + inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); + *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); + if (!(*inputarg)) + return -ENOMEM; + + if (hv_root_partition) { + outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); + *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE; + } + + msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX); + + hv_vp_index[cpu] = msr_vp_index; + + if (msr_vp_index > hv_max_vp_index) + hv_max_vp_index = msr_vp_index; + + return 0; +} + +int hv_common_cpu_die(unsigned int cpu) +{ + unsigned long flags; + void **inputarg, **outputarg; + void *mem; + + local_irq_save(flags); + + inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); + mem = *inputarg; + *inputarg = NULL; + + if (hv_root_partition) { + outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); + *outputarg = NULL; + } + + local_irq_restore(flags); + + kfree(mem); + + return 0; +} /* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */ bool hv_query_ext_cap(u64 cap_query) -- cgit From 9d7cf2c9675838c12cd5cf5a4ebe2ba41bd78a44 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Wed, 14 Jul 2021 11:34:46 -0700 Subject: Drivers: hv: Add arch independent default functions for some Hyper-V handlers Architecture independent Hyper-V code calls various arch-specific handlers when needed. To aid in supporting multiple architectures, provide weak defaults that can be overridden by arch-specific implementations where appropriate. But when arch-specific overrides aren't needed or haven't been implemented yet for a particular architecture, these stubs reduce the amount of clutter under arch/. No functional change. Signed-off-by: Michael Kelley Link: https://lore.kernel.org/r/1626287687-2045-3-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu --- drivers/hv/hv_common.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index e836002bc0ce..fe333f410d1d 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -202,3 +203,51 @@ bool hv_query_ext_cap(u64 cap_query) return hv_extended_cap & cap_query; } EXPORT_SYMBOL_GPL(hv_query_ext_cap); + +/* These __weak functions provide default "no-op" behavior and + * may be overridden by architecture specific versions. Architectures + * for which the default "no-op" behavior is sufficient can leave + * them unimplemented and not be cluttered with a bunch of stub + * functions in arch-specific code. + */ + +bool __weak hv_is_isolation_supported(void) +{ + return false; +} +EXPORT_SYMBOL_GPL(hv_is_isolation_supported); + +void __weak hv_setup_vmbus_handler(void (*handler)(void)) +{ +} +EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler); + +void __weak hv_remove_vmbus_handler(void) +{ +} +EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler); + +void __weak hv_setup_kexec_handler(void (*handler)(void)) +{ +} +EXPORT_SYMBOL_GPL(hv_setup_kexec_handler); + +void __weak hv_remove_kexec_handler(void) +{ +} +EXPORT_SYMBOL_GPL(hv_remove_kexec_handler); + +void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)) +{ +} +EXPORT_SYMBOL_GPL(hv_setup_crash_handler); + +void __weak hv_remove_crash_handler(void) +{ +} +EXPORT_SYMBOL_GPL(hv_remove_crash_handler); + +void __weak hyperv_cleanup(void) +{ +} +EXPORT_SYMBOL_GPL(hyperv_cleanup); -- cgit From 6dc77fa5ac2cf26f846a51492dbe42526e26d0f2 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Wed, 14 Jul 2021 11:34:47 -0700 Subject: Drivers: hv: Move Hyper-V misc functionality to arch-neutral code The check for whether hibernation is possible, and the enabling of Hyper-V panic notification during kexec, are both architecture neutral. Move the code from under arch/x86 and into drivers/hv/hv_common.c where it can also be used for ARM64. No functional change. Signed-off-by: Michael Kelley Link: https://lore.kernel.org/r/1626287687-2045-4-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu --- drivers/hv/hv_common.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index fe333f410d1d..46658de78050 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -13,9 +13,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -70,6 +72,16 @@ int __init hv_common_init(void) { int i; + /* + * Hyper-V expects to get crash register data or kmsg when + * crash enlightment is available and system crashes. Set + * crash_kexec_post_notifiers to be true to make sure that + * calling crash enlightment interface before running kdump + * kernel. + */ + if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) + crash_kexec_post_notifiers = true; + /* * Allocate the per-CPU state for the hypercall input arg. * If this allocation fails, we will not be able to setup @@ -204,6 +216,12 @@ bool hv_query_ext_cap(u64 cap_query) } EXPORT_SYMBOL_GPL(hv_query_ext_cap); +bool hv_is_hibernation_supported(void) +{ + return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4); +} +EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); + /* These __weak functions provide default "no-op" behavior and * may be overridden by architecture specific versions. Architectures * for which the default "no-op" behavior is sufficient can leave -- cgit From 31e5e64694cf9879e63b2802007fa934f4131126 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Tue, 13 Jul 2021 17:01:46 -0700 Subject: drivers: hv: Decouple Hyper-V clock/timer code from VMbus drivers Hyper-V clock/timer code in hyperv_timer.c is mostly independent from other VMbus drivers, but building for ARM64 without hyperv_timer.c shows some remaining entanglements. A default implementation of hv_read_reference_counter can just read a Hyper-V synthetic register and be independent of hyperv_timer.c, so move this code out and into hv_common.c. Then it can be used by the timesync driver even if hyperv_timer.c isn't built on a particular architecture. If hyperv_timer.c *is* built, it can override with a faster implementation. Also provide stubs for stimer functions called by the VMbus driver when hyperv_timer.c isn't built. No functional changes. Signed-off-by: Michael Kelley Link: https://lore.kernel.org/r/1626220906-22629-1-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu --- drivers/clocksource/hyperv_timer.c | 3 --- drivers/hv/hv_common.c | 14 ++++++++++++++ drivers/hv/hv_util.c | 5 ----- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index d6ece7bbce89..ff188ab68496 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -361,9 +361,6 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup); * Hyper-V and 32-bit x86. The TSC reference page version is preferred. */ -u64 (*hv_read_reference_counter)(void); -EXPORT_SYMBOL_GPL(hv_read_reference_counter); - static union { struct ms_hyperv_tsc_page page; u8 reserved[PAGE_SIZE]; diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 46658de78050..c0d9048a4112 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -222,6 +222,20 @@ bool hv_is_hibernation_supported(void) } EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); +/* + * Default function to read the Hyper-V reference counter, independent + * of whether Hyper-V enlightened clocks/timers are being used. But on + * architectures where it is used, Hyper-V enlightenment code in + * hyperv_timer.c may override this function. + */ +static u64 __hv_read_ref_counter(void) +{ + return hv_get_register(HV_REGISTER_TIME_REF_COUNT); +} + +u64 (*hv_read_reference_counter)(void) = __hv_read_ref_counter; +EXPORT_SYMBOL_GPL(hv_read_reference_counter); + /* These __weak functions provide default "no-op" behavior and * may be overridden by architecture specific versions. Architectures * for which the default "no-op" behavior is sufficient can leave diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 136576cba26f..835e6039c186 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "hyperv_vmbus.h" @@ -735,10 +734,6 @@ static struct ptp_clock *hv_ptp_clock; static int hv_timesync_init(struct hv_util_service *srv) { - /* TimeSync requires Hyper-V clocksource. */ - if (!hv_read_reference_counter) - return -ENODEV; - spin_lock_init(&host_ts.lock); INIT_WORK(&adj_time_work, hv_set_host_time); -- cgit From 7aff79e297ee1aa0126924921fd87a4ae59d2467 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Wed, 4 Aug 2021 08:52:39 -0700 Subject: Drivers: hv: Enable Hyper-V code to be built on ARM64 Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on ARM64, causing the Hyper-V specific code to be built. Exclude the Hyper-V enlightened clocks/timers code from being built for ARM64. Signed-off-by: Michael Kelley Reviewed-by: Boqun Feng Acked-by: Marc Zyngier Acked-by: Mark Rutland Acked-by: Catalin Marinas Link: https://lore.kernel.org/r/1628092359-61351-6-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu --- drivers/hv/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 66c794d92391..d1123ceb38f3 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -4,15 +4,16 @@ menu "Microsoft Hyper-V guest support" config HYPERV tristate "Microsoft Hyper-V client drivers" - depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST + depends on ACPI && ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \ + || (ARM64 && !CPU_BIG_ENDIAN)) select PARAVIRT - select X86_HV_CALLBACK_VECTOR + select X86_HV_CALLBACK_VECTOR if X86 help Select this option to run Linux as a Hyper-V client operating system. config HYPERV_TIMER - def_bool HYPERV + def_bool HYPERV && X86 config HYPERV_UTILS tristate "Microsoft Hyper-V Utilities driver" -- cgit From 9d68cd9120e4e3af38f843e165631c323b86b4e4 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 25 Aug 2021 15:38:57 +0200 Subject: hv_utils: Set the maximum packet size for VSS driver to the length of the receive buffer Commit adae1e931acd ("Drivers: hv: vmbus: Copy packets sent by Hyper-V out of the ring buffer") introduced a notion of maximum packet size and for KVM and FCOPY drivers set it to the length of the receive buffer. VSS driver wasn't updated, this means that the maximum packet size is now VMBUS_DEFAULT_MAX_PKT_SIZE (4k). Apparently, this is not enough. I'm observing a packet of 6304 bytes which is being truncated to 4096. When VSS driver tries to read next packet from ring buffer it starts from the wrong offset and receives garbage. Set the maximum packet size to 'HV_HYP_PAGE_SIZE * 2' in VSS driver. This matches the length of the receive buffer and is in line with other utils drivers. Fixes: adae1e931acd ("Drivers: hv: vmbus: Copy packets sent by Hyper-V out of the ring buffer") Signed-off-by: Vitaly Kuznetsov Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20210825133857.847866-1-vkuznets@redhat.com Signed-off-by: Wei Liu --- drivers/hv/hv_snapshot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 2267bd4c3472..6018b9d1b1fb 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c @@ -375,6 +375,7 @@ hv_vss_init(struct hv_util_service *srv) } recv_buffer = srv->recv_buffer; vss_transaction.recv_channel = srv->channel; + vss_transaction.recv_channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2; /* * When this driver loads, the user level daemon that -- cgit