From bedc61a922f9dbbe3bfb26ec2745f8cd63b57637 Mon Sep 17 00:00:00 2001 From: Andrea Parri Date: Tue, 15 Oct 2019 13:46:44 +0200 Subject: Drivers: hv: vmbus: Introduce table of VMBus protocol versions The technique used to get the next VMBus version seems increasisly clumsy as the number of VMBus versions increases. Performance is not a concern since this is only done once during system boot; it's just that we'll end up with more lines of code than is really needed. As an alternative, introduce a table with the version numbers listed in order (from the most recent to the oldest). vmbus_connect() loops through the versions listed in the table until it gets an accepted connection or gets to the end of the table (invalid version). Suggested-by: Michael Kelley Signed-off-by: Andrea Parri Reviewed-by: Wei Liu Reviewed-by: Michael Kelley Signed-off-by: Sasha Levin --- include/linux/hyperv.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index b4a017093b69..c08b62dbd151 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -192,10 +192,6 @@ static inline u32 hv_get_avail_to_write_percent( #define VERSION_WIN10 ((4 << 16) | (0)) #define VERSION_WIN10_V5 ((5 << 16) | (0)) -#define VERSION_INVAL -1 - -#define VERSION_CURRENT VERSION_WIN10_V5 - /* Make maximum size of pipe payload of 16K */ #define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384) -- cgit v1.2.3 From 2d4f49b3e1e3a24ce16dfeeb2235688c8aba57ef Mon Sep 17 00:00:00 2001 From: Andrea Parri Date: Tue, 15 Oct 2019 13:46:45 +0200 Subject: Drivers: hv: vmbus: Enable VMBus protocol versions 4.1, 5.1 and 5.2 Hyper-V has added VMBus protocol versions 5.1 and 5.2 in recent release versions. Allow Linux guests to negotiate these new protocol versions on versions of Hyper-V that support them. While on this, also allow guests to negotiate the VMBus protocol version 4.1 (which was missing). Signed-off-by: Andrea Parri Reviewed-by: Wei Liu Reviewed-by: Michael Kelley Signed-off-by: Sasha Levin --- drivers/hv/connection.c | 13 ++++++++----- include/linux/hyperv.h | 8 +++++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 8dc48f53c1ac..cadfb34b38d8 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -44,7 +44,10 @@ EXPORT_SYMBOL_GPL(vmbus_proto_version); * Table of VMBus versions listed from newest to oldest. */ static __u32 vmbus_versions[] = { + VERSION_WIN10_V5_2, + VERSION_WIN10_V5_1, VERSION_WIN10_V5, + VERSION_WIN10_V4_1, VERSION_WIN10, VERSION_WIN8_1, VERSION_WIN8, @@ -68,12 +71,12 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) msg->vmbus_version_requested = version; /* - * VMBus protocol 5.0 (VERSION_WIN10_V5) requires that we must use - * VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate Contact Message, + * VMBus protocol 5.0 (VERSION_WIN10_V5) and higher require 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 + * VERSION_WIN10_V5 and higher, 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). @@ -399,7 +402,7 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) case HV_STATUS_INVALID_CONNECTION_ID: /* * See vmbus_negotiate_version(): VMBus protocol 5.0 - * requires that we must use + * and higher require that we must use * VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate * Contact message, but on old hosts that only * support VMBus protocol 4.0 or lower, here we get diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c08b62dbd151..f17f2cd22e39 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -182,15 +182,21 @@ static inline u32 hv_get_avail_to_write_percent( * 2 . 4 (Windows 8) * 3 . 0 (Windows 8 R2) * 4 . 0 (Windows 10) + * 4 . 1 (Windows 10 RS3) * 5 . 0 (Newer Windows 10) + * 5 . 1 (Windows 10 RS4) + * 5 . 2 (Windows Server 2019, RS5) */ #define VERSION_WS2008 ((0 << 16) | (13)) #define VERSION_WIN7 ((1 << 16) | (1)) #define VERSION_WIN8 ((2 << 16) | (4)) #define VERSION_WIN8_1 ((3 << 16) | (0)) -#define VERSION_WIN10 ((4 << 16) | (0)) +#define VERSION_WIN10 ((4 << 16) | (0)) +#define VERSION_WIN10_V4_1 ((4 << 16) | (1)) #define VERSION_WIN10_V5 ((5 << 16) | (0)) +#define VERSION_WIN10_V5_1 ((5 << 16) | (1)) +#define VERSION_WIN10_V5_2 ((5 << 16) | (2)) /* Make maximum size of pipe payload of 16K */ #define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384) -- cgit v1.2.3 From af9ca6f9bb16e446a44393a797d0ae74d356a5c7 Mon Sep 17 00:00:00 2001 From: Branden Bonaby Date: Thu, 3 Oct 2019 17:01:49 -0400 Subject: drivers: hv: vmbus: Introduce latency testing Introduce user specified latency in the packet reception path By exposing the test parameters as part of the debugfs channel attributes. We will control the testing state via these attributes. Signed-off-by: Branden Bonaby Reviewed-by: Michael Kelley Signed-off-by: Sasha Levin --- Documentation/ABI/testing/debugfs-hyperv | 23 ++++ MAINTAINERS | 1 + drivers/hv/Makefile | 1 + drivers/hv/connection.c | 1 + drivers/hv/hv_debugfs.c | 178 +++++++++++++++++++++++++++++++ drivers/hv/hyperv_vmbus.h | 31 ++++++ drivers/hv/ring_buffer.c | 2 + drivers/hv/vmbus_drv.c | 6 ++ include/linux/hyperv.h | 19 ++++ lib/Kconfig.debug | 7 ++ 10 files changed, 269 insertions(+) create mode 100644 Documentation/ABI/testing/debugfs-hyperv create mode 100644 drivers/hv/hv_debugfs.c (limited to 'include') diff --git a/Documentation/ABI/testing/debugfs-hyperv b/Documentation/ABI/testing/debugfs-hyperv new file mode 100644 index 000000000000..9185e1b06bba --- /dev/null +++ b/Documentation/ABI/testing/debugfs-hyperv @@ -0,0 +1,23 @@ +What: /sys/kernel/debug/hyperv//fuzz_test_state +Date: October 2019 +KernelVersion: 5.5 +Contact: Branden Bonaby +Description: Fuzz testing status of a vmbus device, whether its in an ON + state or a OFF state +Users: Debugging tools + +What: /sys/kernel/debug/hyperv//delay/fuzz_test_buffer_interrupt_delay +Date: October 2019 +KernelVersion: 5.5 +Contact: Branden Bonaby +Description: Fuzz testing buffer interrupt delay value between 0 - 1000 + microseconds (inclusive). +Users: Debugging tools + +What: /sys/kernel/debug/hyperv//delay/fuzz_test_message_delay +Date: October 2019 +KernelVersion: 5.5 +Contact: Branden Bonaby +Description: Fuzz testing message delay value between 0 - 1000 microseconds + (inclusive). +Users: Debugging tools diff --git a/MAINTAINERS b/MAINTAINERS index cba1095547fd..e7febfbf44ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7578,6 +7578,7 @@ F: include/uapi/linux/hyperv.h F: include/asm-generic/mshyperv.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus +F: Documentation/ABI/testing/debugfs-hyperv HYPERBUS SUPPORT M: Vignesh Raghavendra diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index a1eec7177c2d..94daf8240c95 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -9,4 +9,5 @@ CFLAGS_hv_balloon.o = -I$(src) hv_vmbus-y := vmbus_drv.o \ hv.o connection.o channel.o \ channel_mgmt.o ring_buffer.o hv_trace.o +hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o hv_utils_transport.o diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 0475be4356dd..e947c39d4cc7 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -363,6 +363,7 @@ void vmbus_on_event(unsigned long data) trace_vmbus_on_event(channel); + hv_debug_delay_test(channel, INTERRUPT_DELAY); do { void (*callback_fn)(void *); diff --git a/drivers/hv/hv_debugfs.c b/drivers/hv/hv_debugfs.c new file mode 100644 index 000000000000..8a2878573582 --- /dev/null +++ b/drivers/hv/hv_debugfs.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Authors: + * Branden Bonaby + */ + +#include +#include +#include +#include + +#include "hyperv_vmbus.h" + +struct dentry *hv_debug_root; + +static int hv_debugfs_delay_get(void *data, u64 *val) +{ + *val = *(u32 *)data; + return 0; +} + +static int hv_debugfs_delay_set(void *data, u64 val) +{ + if (val > 1000) + return -EINVAL; + *(u32 *)data = val; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(hv_debugfs_delay_fops, hv_debugfs_delay_get, + hv_debugfs_delay_set, "%llu\n"); + +static int hv_debugfs_state_get(void *data, u64 *val) +{ + *val = *(bool *)data; + return 0; +} + +static int hv_debugfs_state_set(void *data, u64 val) +{ + if (val == 1) + *(bool *)data = true; + else if (val == 0) + *(bool *)data = false; + else + return -EINVAL; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(hv_debugfs_state_fops, hv_debugfs_state_get, + hv_debugfs_state_set, "%llu\n"); + +/* Setup delay files to store test values */ +static int hv_debug_delay_files(struct hv_device *dev, struct dentry *root) +{ + struct vmbus_channel *channel = dev->channel; + char *buffer = "fuzz_test_buffer_interrupt_delay"; + char *message = "fuzz_test_message_delay"; + int *buffer_val = &channel->fuzz_testing_interrupt_delay; + int *message_val = &channel->fuzz_testing_message_delay; + struct dentry *buffer_file, *message_file; + + buffer_file = debugfs_create_file(buffer, 0644, root, + buffer_val, + &hv_debugfs_delay_fops); + if (IS_ERR(buffer_file)) { + pr_debug("debugfs_hyperv: file %s not created\n", buffer); + return PTR_ERR(buffer_file); + } + + message_file = debugfs_create_file(message, 0644, root, + message_val, + &hv_debugfs_delay_fops); + if (IS_ERR(message_file)) { + pr_debug("debugfs_hyperv: file %s not created\n", message); + return PTR_ERR(message_file); + } + + return 0; +} + +/* Setup test state value for vmbus device */ +static int hv_debug_set_test_state(struct hv_device *dev, struct dentry *root) +{ + struct vmbus_channel *channel = dev->channel; + bool *state = &channel->fuzz_testing_state; + char *status = "fuzz_test_state"; + struct dentry *test_state; + + test_state = debugfs_create_file(status, 0644, root, + state, + &hv_debugfs_state_fops); + if (IS_ERR(test_state)) { + pr_debug("debugfs_hyperv: file %s not created\n", status); + return PTR_ERR(test_state); + } + + return 0; +} + +/* Bind hv device to a dentry for debugfs */ +static void hv_debug_set_dir_dentry(struct hv_device *dev, struct dentry *root) +{ + if (hv_debug_root) + dev->debug_dir = root; +} + +/* Create all test dentry's and names for fuzz testing */ +int hv_debug_add_dev_dir(struct hv_device *dev) +{ + const char *device = dev_name(&dev->device); + char *delay_name = "delay"; + struct dentry *delay, *dev_root; + int ret; + + if (!IS_ERR(hv_debug_root)) { + dev_root = debugfs_create_dir(device, hv_debug_root); + if (IS_ERR(dev_root)) { + pr_debug("debugfs_hyperv: hyperv/%s/ not created\n", + device); + return PTR_ERR(dev_root); + } + hv_debug_set_test_state(dev, dev_root); + hv_debug_set_dir_dentry(dev, dev_root); + delay = debugfs_create_dir(delay_name, dev_root); + + if (IS_ERR(delay)) { + pr_debug("debugfs_hyperv: hyperv/%s/%s/ not created\n", + device, delay_name); + return PTR_ERR(delay); + } + ret = hv_debug_delay_files(dev, delay); + + return ret; + } + pr_debug("debugfs_hyperv: hyperv/ not in root debugfs path\n"); + return PTR_ERR(hv_debug_root); +} + +/* Remove dentry associated with released hv device */ +void hv_debug_rm_dev_dir(struct hv_device *dev) +{ + if (!IS_ERR(hv_debug_root)) + debugfs_remove_recursive(dev->debug_dir); +} + +/* Remove all dentrys associated with vmbus testing */ +void hv_debug_rm_all_dir(void) +{ + debugfs_remove_recursive(hv_debug_root); +} + +/* Delay buffer/message reads on a vmbus channel */ +void hv_debug_delay_test(struct vmbus_channel *channel, enum delay delay_type) +{ + struct vmbus_channel *test_channel = channel->primary_channel ? + channel->primary_channel : + channel; + bool state = test_channel->fuzz_testing_state; + + if (state) { + if (delay_type == 0) + udelay(test_channel->fuzz_testing_interrupt_delay); + else + udelay(test_channel->fuzz_testing_message_delay); + } +} + +/* Initialize top dentry for vmbus testing */ +int hv_debug_init(void) +{ + hv_debug_root = debugfs_create_dir("hyperv", NULL); + if (IS_ERR(hv_debug_root)) { + pr_debug("debugfs_hyperv: hyperv/ not created\n"); + return PTR_ERR(hv_debug_root); + } + return 0; +} diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index af9379a3bf89..20edcfd3b96c 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -385,4 +385,35 @@ enum hvutil_device_state { HVUTIL_DEVICE_DYING, /* driver unload is in progress */ }; +enum delay { + INTERRUPT_DELAY = 0, + MESSAGE_DELAY = 1, +}; + +#ifdef CONFIG_HYPERV_TESTING + +int hv_debug_add_dev_dir(struct hv_device *dev); +void hv_debug_rm_dev_dir(struct hv_device *dev); +void hv_debug_rm_all_dir(void); +int hv_debug_init(void); +void hv_debug_delay_test(struct vmbus_channel *channel, enum delay delay_type); + +#else /* CONFIG_HYPERV_TESTING */ + +static inline void hv_debug_rm_dev_dir(struct hv_device *dev) {}; +static inline void hv_debug_rm_all_dir(void) {}; +static inline void hv_debug_delay_test(struct vmbus_channel *channel, + enum delay delay_type) {}; +static inline int hv_debug_init(void) +{ + return -1; +} + +static inline int hv_debug_add_dev_dir(struct hv_device *dev) +{ + return -1; +} + +#endif /* CONFIG_HYPERV_TESTING */ + #endif /* _HYPERV_VMBUS_H */ diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 9a03b163cbbd..356e22159e83 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -396,6 +396,7 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) struct hv_ring_buffer_info *rbi = &channel->inbound; struct vmpacket_descriptor *desc; + hv_debug_delay_test(channel, MESSAGE_DELAY); if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) return NULL; @@ -421,6 +422,7 @@ __hv_pkt_iter_next(struct vmbus_channel *channel, u32 packetlen = desc->len8 << 3; u32 dsize = rbi->ring_datasize; + hv_debug_delay_test(channel, MESSAGE_DELAY); /* bump offset to next potential packet */ rbi->priv_read_index += packetlen + VMBUS_PKT_TRAILER; if (rbi->priv_read_index >= dsize) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0ac874faf720..125991820278 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -960,6 +960,8 @@ static void vmbus_device_release(struct device *device) struct hv_device *hv_dev = device_to_hv_device(device); struct vmbus_channel *channel = hv_dev->channel; + hv_debug_rm_dev_dir(hv_dev); + mutex_lock(&vmbus_connection.channel_mutex); hv_process_channel_removal(channel); mutex_unlock(&vmbus_connection.channel_mutex); @@ -1814,6 +1816,7 @@ int vmbus_device_register(struct hv_device *child_device_obj) pr_err("Unable to register primary channeln"); goto err_kset_unregister; } + hv_debug_add_dev_dir(child_device_obj); return 0; @@ -2374,6 +2377,7 @@ static int __init hv_acpi_init(void) ret = -ETIMEDOUT; goto cleanup; } + hv_debug_init(); ret = vmbus_bus_init(); if (ret) @@ -2410,6 +2414,8 @@ static void __exit vmbus_exit(void) tasklet_kill(&hv_cpu->msg_dpc); } + hv_debug_rm_all_dir(); + vmbus_free_channels(); if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index f17f2cd22e39..26f3aeeae1ca 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -934,6 +934,21 @@ struct vmbus_channel { * full outbound ring buffer. */ u64 out_full_first; + + /* enabling/disabling fuzz testing on the channel (default is false)*/ + bool fuzz_testing_state; + + /* + * Interrupt delay will delay the guest from emptying the ring buffer + * for a specific amount of time. The delay is in microseconds and will + * be between 1 to a maximum of 1000, its default is 0 (no delay). + * The Message delay will delay guest reading on a per message basis + * in microseconds between 1 to 1000 with the default being 0 + * (no delay). + */ + u32 fuzz_testing_interrupt_delay; + u32 fuzz_testing_message_delay; + }; static inline bool is_hvsock_channel(const struct vmbus_channel *c) @@ -1182,6 +1197,10 @@ struct hv_device { struct vmbus_channel *channel; struct kset *channels_kset; + + /* place holder to keep track of the dir for hv device in debugfs */ + struct dentry *debug_dir; + }; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 93d97f9b0157..55eebbc0b0fb 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2127,4 +2127,11 @@ config IO_STRICT_DEVMEM source "arch/$(SRCARCH)/Kconfig.debug" +config HYPERV_TESTING + bool "Microsoft Hyper-V driver testing" + default n + depends on HYPERV && DEBUG_FS + help + Select this option to enable Hyper-V vmbus testing. + endmenu # Kernel hacking -- cgit v1.2.3 From b96f86534fa3102fd07246cf8b6cb5cc96788597 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Tue, 19 Nov 2019 23:16:04 -0800 Subject: x86/hyperv: Implement hv_is_hibernation_supported() The API will be used by the hv_balloon and hv_vmbus drivers. Balloon up/down and hot-add of memory must not be active if the user wants the Linux VM to support hibernation, because they are incompatible with hibernation according to Hyper-V team, e.g. upon suspend the balloon VSP doesn't save any info about the ballooned-out pages (if any); so, after Linux resumes, Linux balloon VSC expects that the VSP will return the pages if Linux is under memory pressure, but the VSP will never do that, since the VSP thinks it never stole the pages from the VM. So, if the user wants Linux VM to support hibernation, Linux must forbid balloon up/down and hot-add, and the only functionality of the balloon VSC driver is reporting the VM's memory pressure to the host. Ideally, when Linux detects that the user wants it to support hibernation, the balloon VSC should tell the VSP that it does not support ballooning and hot-add. However, the current version of the VSP requires the VSC should support these capabilities, otherwise the capability negotiation fails and the VSC can not load at all, so with the later changes to the VSC driver, Linux VM still reports to the VSP that the VSC supports these capabilities, but the VSC ignores the VSP's requests of balloon up/down and hot add, and reports an error to the VSP, when applicable. BTW, in the future the balloon VSP driver will allow the VSC to not support the capabilities of balloon up/down and hot add. The ACPI S4 state is not a must for hibernation to work, because Linux is able to hibernate as long as the system can shut down. However in practice we decide to artificially use the presence of the virtual ACPI S4 state as an indicator of the user's intent of using hibernation, because Linux VM must find a way to know if the user wants to use the hibernation feature or not. By default, Hyper-V does not enable the virtual ACPI S4 state; on recent Hyper-V hosts (e.g. RS5, 19H1), the administrator is able to enable the state for a VM by WMI commands. Once all the vmbus and VSC patches for the hibernation feature are accepted, an extra patch will be submitted to forbid hibernation if the virtual ACPI S4 state is absent, i.e. hv_is_hibernation_supported() is false. Signed-off-by: Dexuan Cui Reviewed-by: Michael Kelley Acked-by: Thomas Gleixner Signed-off-by: Sasha Levin --- arch/x86/hyperv/hv_init.c | 7 +++++++ include/asm-generic/mshyperv.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index b2daf0ebdb19..7552fe196d83 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -7,6 +7,7 @@ * Author : K. Y. Srinivasan */ +#include #include #include #include @@ -439,3 +440,9 @@ bool hv_is_hyperv_initialized(void) return hypercall_msr.enable; } EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized); + +bool hv_is_hibernation_supported(void) +{ + return acpi_sleep_state_supported(ACPI_STATE_S4); +} +EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 18d8e2d8210f..b3f1082cc435 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -166,10 +166,12 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset, 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); +bool hv_is_hibernation_supported(void); void hyperv_cleanup(void); void hv_setup_sched_clock(void *sched_clock); #else /* CONFIG_HYPERV */ static inline bool hv_is_hyperv_initialized(void) { return false; } +static inline bool hv_is_hibernation_supported(void) { return false; } static inline void hyperv_cleanup(void) {} #endif /* CONFIG_HYPERV */ -- cgit v1.2.3