hyperv-fixes for v7.1-rc8

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEIbPD0id6easf0xsudhRwX5BBoF4FAmomTIwTHHdlaS5saXVA
 a2VybmVsLm9yZwAKCRB2FHBfkEGgXqyECADL9eYwEkfwQDB+CmyemmINo/wvOfGu
 u6husKyGqs3eBe7sPtERarHtN8UlQMGLMVd2CR8QqtD+P9yZjSnNX54ljtweEdIr
 eAijVHEFmw1e1Lo/lGOv8eldNP3FuUGopz6rkfuQ2S+6xZ9MHIYda5MCZ3I0rbOe
 Mq+aB17Qhvqp+O4+zfk5wDh9OJ1Wa5c0U0xfKx51SX4qf1KDL7AUIz0Cyy7P8h5q
 u7MDYFaE4U9d8M5GbRQUGyHr6W0YQuMMUW5Ip04OsQXRKyMR5W20dFtiwoqI4UbF
 loWUakk4RkC9tEMs6WeLSvqrLgKqbqfDOScYB8OPEUlh5CRMhYp7uhkA
 =fcaL
 -----END PGP SIGNATURE-----

Merge tag 'hyperv-fixes-signed-20260607' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv fixes from Wei Liu:

 - MSHV driver fixes from various people (Anirudh Rayabharam, Can Peng,
   Dexuan Cui, Michael Kelley, Jork Loeser, Wei Liu)

 - Hyper-V user space tools fixes (Thorsten Blum)

 - Allow VMBus to be unloaded after frame buffer is flushed (Michael
   Kelley)

* tag 'hyperv-fixes-signed-20260607' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  mshv: support 1G hugepages by passing them as 2M-aligned chunks
  Drivers: hv: vmbus: Improve the logic of reserving fb_mmio on Gen2 VMs
  mshv: use kmalloc_array in mshv_root_scheduler_init
  mshv: Add conditional VMBus dependency
  hyperv: Clean up and fix the guest ID comment in hvgdk.h
  drm/hyperv: During panic do VMBus unload after frame buffer is flushed
  Drivers: hv: vmbus: Provide option to skip VMBus unload on panic
  mshv: unmap debugfs stats pages on kexec
  mshv: clean up SynIC state on kexec for L1VH
  mshv: limit SynIC management to MSHV-owned resources
  hv: utils: replace deprecated strcpy with strscpy in kvp_register
  hv: utils: handle and propagate errors in kvp_register
  mshv: add a missing padding field
This commit is contained in:
Linus Torvalds 2026-06-08 07:31:41 -07:00
commit e92a762877
15 changed files with 206 additions and 111 deletions

View file

@ -150,6 +150,10 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
goto err_free_mmio;
}
/* If DRM panic path is stubbed out VMBus code must do the unload */
if (IS_ENABLED(CONFIG_DRM_PANIC))
vmbus_set_skip_unload(true);
drm_client_setup(dev, NULL);
return 0;
@ -169,6 +173,7 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
struct drm_device *dev = hv_get_drvdata(hdev);
struct hyperv_drm_device *hv = to_hv(dev);
vmbus_set_skip_unload(false);
drm_dev_unplug(dev);
drm_atomic_helper_shutdown(dev);
vmbus_close(hdev->channel);

View file

@ -212,15 +212,16 @@ static void hyperv_plane_panic_flush(struct drm_plane *plane)
struct hyperv_drm_device *hv = to_hv(plane->dev);
struct drm_rect rect;
if (!plane->state || !plane->state->fb)
return;
if (plane->state && plane->state->fb) {
rect.x1 = 0;
rect.y1 = 0;
rect.x2 = plane->state->fb->width;
rect.y2 = plane->state->fb->height;
rect.x1 = 0;
rect.y1 = 0;
rect.x2 = plane->state->fb->width;
rect.y2 = plane->state->fb->height;
hyperv_update_dirt(hv->hdev, &rect);
}
hyperv_update_dirt(hv->hdev, &rect);
vmbus_initiate_unload(true);
}
static const struct drm_plane_helper_funcs hyperv_plane_helper_funcs = {

View file

@ -74,6 +74,7 @@ config MSHV_ROOT
# e.g. When withdrawing memory, the hypervisor gives back 4k pages in
# no particular order, making it impossible to reassemble larger pages
depends on PAGE_SIZE_4KB
depends on HYPERV_VMBUS if HYPERV_VMBUS
select EVENTFD
select VIRT_XFER_TO_GUEST_WORK
select HMM_MIRROR

View file

@ -952,6 +952,7 @@ void vmbus_initiate_unload(bool crash)
else
vmbus_wait_for_unload();
}
EXPORT_SYMBOL_GPL(vmbus_initiate_unload);
static void vmbus_setup_channel_state(struct vmbus_channel *channel,
struct vmbus_channel_offer_channel *offer)

View file

@ -272,6 +272,9 @@ void hv_synic_free(void)
/*
* hv_hyp_synic_enable_regs - Initialize the Synthetic Interrupt Controller
* with the hypervisor.
*
* Note: When MSHV is present, mshv_synic_cpu_init() intializes further
* registers later.
*/
void hv_hyp_synic_enable_regs(unsigned int cpu)
{

View file

@ -27,6 +27,7 @@
#include <linux/connector.h>
#include <linux/workqueue.h>
#include <linux/hyperv.h>
#include <linux/string.h>
#include <hyperv/hvhdk.h>
#include "hyperv_vmbus.h"
@ -93,7 +94,7 @@ static void kvp_send_key(struct work_struct *dummy);
static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
static void kvp_timeout_func(struct work_struct *dummy);
static void kvp_host_handshake_func(struct work_struct *dummy);
static void kvp_register(int);
static int kvp_register(int);
static DECLARE_DELAYED_WORK(kvp_timeout_work, kvp_timeout_func);
static DECLARE_DELAYED_WORK(kvp_host_handshake_work, kvp_host_handshake_func);
@ -127,24 +128,23 @@ static void kvp_register_done(void)
hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
}
static void
static int
kvp_register(int reg_value)
{
struct hv_kvp_msg *kvp_msg;
char *version;
int ret;
kvp_msg = kzalloc_obj(*kvp_msg);
if (!kvp_msg)
return -ENOMEM;
if (kvp_msg) {
version = kvp_msg->body.kvp_register.version;
kvp_msg->kvp_hdr.operation = reg_value;
strcpy(version, HV_DRV_VERSION);
kvp_msg->kvp_hdr.operation = reg_value;
strscpy(kvp_msg->body.kvp_register.version, HV_DRV_VERSION);
hvutil_transport_send(hvt, kvp_msg, sizeof(*kvp_msg),
kvp_register_done);
kfree(kvp_msg);
}
ret = hvutil_transport_send(hvt, kvp_msg, sizeof(*kvp_msg),
kvp_register_done);
kfree(kvp_msg);
return ret;
}
static void kvp_timeout_func(struct work_struct *dummy)
@ -186,9 +186,8 @@ static int kvp_handle_handshake(struct hv_kvp_msg *msg)
*/
pr_debug("KVP: userspace daemon ver. %d connected\n",
msg->kvp_hdr.operation);
kvp_register(dm_reg_value);
return 0;
return kvp_register(dm_reg_value);
}

View file

@ -441,7 +441,6 @@ void hv_vss_deinit(void);
int hv_vss_pre_suspend(void);
int hv_vss_pre_resume(void);
void hv_vss_onchannelcallback(void *context);
void vmbus_initiate_unload(bool crash);
static inline void hv_poll_channel(struct vmbus_channel *channel,
void (*cb)(void *))

View file

@ -674,8 +674,10 @@ int __init mshv_debugfs_init(void)
mshv_debugfs = debugfs_create_dir("mshv", NULL);
if (IS_ERR(mshv_debugfs)) {
err = PTR_ERR(mshv_debugfs);
mshv_debugfs = NULL;
pr_err("%s: failed to create debugfs directory\n", __func__);
return PTR_ERR(mshv_debugfs);
return err;
}
if (hv_root_partition()) {
@ -710,6 +712,9 @@ remove_mshv_dir:
void mshv_debugfs_exit(void)
{
if (!mshv_debugfs)
return;
mshv_debugfs_parent_partition_remove();
if (hv_root_partition()) {

View file

@ -29,29 +29,27 @@
* Uses huge page stride if the backing page is huge and the guest mapping
* is properly aligned; otherwise falls back to single page stride.
*
* Return: Stride in pages, or -EINVAL if page order is unsupported.
* Return: Stride in pages.
*/
static int mshv_chunk_stride(struct page *page,
u64 gfn, u64 page_count)
static unsigned int mshv_chunk_stride(struct page *page, u64 gfn,
u64 page_count)
{
unsigned int page_order;
unsigned int page_order = folio_order(page_folio(page));
/*
* Use single page stride by default. For huge page stride, the
* page must be compound and point to the head of the compound
* page, and both gfn and page_count must be huge-page aligned.
* folio order must be at least PMD_ORDER, the page's PFN must be
* 2M-aligned (so that a 2M-aligned tail page of a larger folio is
* acceptable), and both gfn and page_count must be 2M-aligned.
*/
if (!PageCompound(page) || !PageHead(page) ||
if (page_order < PMD_ORDER ||
!IS_ALIGNED(page_to_pfn(page), PTRS_PER_PMD) ||
!IS_ALIGNED(gfn, PTRS_PER_PMD) ||
!IS_ALIGNED(page_count, PTRS_PER_PMD))
return 1;
page_order = folio_order(page_folio(page));
/* The hypervisor only supports 2M huge page */
if (page_order != PMD_ORDER)
return -EINVAL;
return 1 << page_order;
/* Use 2M stride always i.e. process 1G folios as 2M chunks */
return 1 << PMD_ORDER;
}
/**
@ -86,15 +84,14 @@ static long mshv_region_process_chunk(struct mshv_mem_region *region,
u64 gfn = region->start_gfn + page_offset;
u64 count;
struct page *page;
int stride, ret;
unsigned int stride;
int ret;
page = region->mreg_pages[page_offset];
if (!page)
return -EINVAL;
stride = mshv_chunk_stride(page, gfn, page_count);
if (stride < 0)
return stride;
/* Start at stride since the first stride is validated */
for (count = stride; count < page_count; count += stride) {

View file

@ -2241,7 +2241,7 @@ static int mshv_root_scheduler_init(unsigned int cpu)
outputarg = (void **)this_cpu_ptr(root_scheduler_output);
/* Allocate two consecutive pages. One for input, one for output. */
p = kmalloc(2 * HV_HYP_PAGE_SIZE, GFP_KERNEL);
p = kmalloc_array(2, HV_HYP_PAGE_SIZE, GFP_KERNEL);
if (!p)
return -ENOMEM;

View file

@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/cpuhotplug.h>
#include <linux/hyperv.h>
#include <linux/reboot.h>
#include <asm/mshyperv.h>
#include <linux/acpi.h>
@ -456,46 +457,75 @@ static int mshv_synic_cpu_init(unsigned int cpu)
union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
union hv_synic_sint sint;
union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
struct hv_synic_event_ring_page **event_ring_page =
&spages->synic_event_ring_page;
/*
* VMBus owns SIMP/SIEFP/SCONTROL when it is active.
* See hv_hyp_synic_enable_regs() for that initialization.
*/
bool vmbus_active = hv_vmbus_exists();
/* Setup the Synic's message page */
/*
* Map the SYNIC message page. When VMBus is not active the
* hypervisor pre-provisions the SIMP GPA but may not set
* simp_enabled enable it here.
*/
simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
simp.simp_enabled = true;
if (!vmbus_active) {
simp.simp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
}
*msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE,
MEMREMAP_WB);
if (!(*msg_page))
return -EFAULT;
goto cleanup_simp;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
/* Setup the Synic's event flags page */
/*
* Map the event flags page. Same as SIMP: enable when
* VMBus is not active, already enabled by VMBus otherwise.
*/
siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
siefp.siefp_enabled = true;
*event_flags_page = memremap(siefp.base_siefp_gpa << PAGE_SHIFT,
PAGE_SIZE, MEMREMAP_WB);
if (!vmbus_active) {
siefp.siefp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
}
*event_flags_page = memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE, MEMREMAP_WB);
if (!(*event_flags_page))
goto cleanup;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
goto cleanup_siefp;
/* Setup the Synic's event ring page */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
if (hv_root_partition()) {
*event_ring_page = memremap(sirbp.base_sirbp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE, MEMREMAP_WB);
if (!(*event_ring_page))
goto cleanup_siefp;
} else {
/*
* On L1VH the hypervisor does not provide a SIRBP page.
* Allocate one and program its GPA into the MSR.
*/
*event_ring_page = (struct hv_synic_event_ring_page *)
get_zeroed_page(GFP_KERNEL);
if (!(*event_ring_page))
goto cleanup_siefp;
sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page)
>> HV_HYP_PAGE_SHIFT;
}
sirbp.sirbp_enabled = true;
*event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
PAGE_SIZE, MEMREMAP_WB);
if (!(*event_ring_page))
goto cleanup;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
if (mshv_sint_irq != -1)
@ -518,28 +548,30 @@ static int mshv_synic_cpu_init(unsigned int cpu)
hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
sint.as_uint64);
/* Enable global synic bit */
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
sctrl.enable = 1;
hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
/* When VMBus is active it already enabled SCONTROL. */
if (!vmbus_active) {
union hv_synic_scontrol sctrl;
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
sctrl.enable = 1;
hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
}
return 0;
cleanup:
if (*event_ring_page) {
sirbp.sirbp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
memunmap(*event_ring_page);
}
if (*event_flags_page) {
cleanup_siefp:
if (*event_flags_page)
memunmap(*event_flags_page);
if (!vmbus_active) {
siefp.siefp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
memunmap(*event_flags_page);
}
if (*msg_page) {
cleanup_simp:
if (*msg_page)
memunmap(*msg_page);
if (!vmbus_active) {
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
memunmap(*msg_page);
}
return -EFAULT;
@ -548,16 +580,15 @@ cleanup:
static int mshv_synic_cpu_exit(unsigned int cpu)
{
union hv_synic_sint sint;
union hv_synic_simp simp;
union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
struct hv_synic_event_ring_page **event_ring_page =
&spages->synic_event_ring_page;
/* VMBus owns SIMP/SIEFP/SCONTROL when it is active */
bool vmbus_active = hv_vmbus_exists();
/* Disable the interrupt */
sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX);
@ -574,28 +605,47 @@ static int mshv_synic_cpu_exit(unsigned int cpu)
if (mshv_sint_irq != -1)
disable_percpu_irq(mshv_sint_irq);
/* Disable Synic's event ring page */
/* Disable SYNIC event ring page owned by MSHV */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
sirbp.sirbp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
memunmap(*event_ring_page);
/* Disable Synic's event flags page */
siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
siefp.siefp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
if (hv_root_partition()) {
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
memunmap(*event_ring_page);
} else {
sirbp.base_sirbp_gpa = 0;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
free_page((unsigned long)*event_ring_page);
}
/*
* Release our mappings of the message and event flags pages.
* When VMBus is not active, we enabled SIMP/SIEFP disable
* them. Otherwise VMBus owns the MSRs leave them.
*/
memunmap(*event_flags_page);
if (!vmbus_active) {
union hv_synic_simp simp;
union hv_synic_siefp siefp;
/* Disable Synic's message page */
simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
siefp.siefp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
}
memunmap(*msg_page);
/* Disable global synic bit */
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
sctrl.enable = 0;
hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
/* When VMBus is active it owns SCONTROL — leave it. */
if (!vmbus_active) {
union hv_synic_scontrol sctrl;
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
sctrl.enable = 0;
hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
}
return 0;
}
@ -673,9 +723,7 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid)
static int mshv_synic_reboot_notify(struct notifier_block *nb,
unsigned long code, void *unused)
{
if (!hv_root_partition())
return 0;
mshv_debugfs_exit();
cpuhp_remove_state(synic_cpuhp_online);
return 0;
}

View file

@ -69,19 +69,29 @@ bool vmbus_is_confidential(void)
}
EXPORT_SYMBOL_GPL(vmbus_is_confidential);
static bool skip_vmbus_unload;
/*
* Allow a VMBus framebuffer driver to specify that in the case of a panic,
* it will do the VMbus unload operation once it has flushed any dirty
* portions of the framebuffer to the Hyper-V host.
*/
void vmbus_set_skip_unload(bool skip)
{
skip_vmbus_unload = skip;
}
EXPORT_SYMBOL_GPL(vmbus_set_skip_unload);
/*
* The panic notifier below is responsible solely for unloading the
* vmbus connection, which is necessary in a panic event.
*
* Notice an intrincate relation of this notifier with Hyper-V
* framebuffer panic notifier exists - we need vmbus connection alive
* there in order to succeed, so we need to order both with each other
* [see hvfb_on_panic()] - this is done using notifiers' priorities.
*/
static int hv_panic_vmbus_unload(struct notifier_block *nb, unsigned long val,
void *args)
{
vmbus_initiate_unload(true);
if (!skip_vmbus_unload)
vmbus_initiate_unload(true);
return NOTIFY_DONE;
}
static struct notifier_block hyperv_panic_vmbus_unload_block = {
@ -2317,8 +2327,8 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
return AE_NO_MEMORY;
/* If this range overlaps the virtual TPM, truncate it. */
if (end > VTPM_BASE_ADDRESS && start < VTPM_BASE_ADDRESS)
end = VTPM_BASE_ADDRESS;
if (end >= VTPM_BASE_ADDRESS && start < VTPM_BASE_ADDRESS)
end = VTPM_BASE_ADDRESS - 1;
new_res->name = "hyperv mmio";
new_res->flags = IORESOURCE_MEM;
@ -2385,6 +2395,7 @@ static void vmbus_mmio_remove(void)
static void __maybe_unused vmbus_reserve_fb(void)
{
resource_size_t start = 0, size;
resource_size_t low_mmio_base;
struct pci_dev *pdev;
if (efi_enabled(EFI_BOOT)) {
@ -2392,6 +2403,24 @@ static void __maybe_unused vmbus_reserve_fb(void)
if (IS_ENABLED(CONFIG_SYSFB)) {
start = sysfb_primary_display.screen.lfb_base;
size = max_t(__u32, sysfb_primary_display.screen.lfb_size, 0x800000);
low_mmio_base = hyperv_mmio->start;
if (!low_mmio_base || upper_32_bits(low_mmio_base) ||
(start && start < low_mmio_base)) {
pr_warn("Unexpected low mmio base %pa\n", &low_mmio_base);
} else {
/*
* If the kdump/kexec or CVM kernel's lfb_base
* is 0, fall back to the low mmio base.
*/
if (!start)
start = low_mmio_base;
/*
* Reserve half of the space below 4GB for high
* resolutions, but cap the reservation to 128MB.
*/
size = min((SZ_4G - start) / 2, SZ_128M);
}
}
} else {
/* Gen1 VM: get FB base from PCI */
@ -2412,8 +2441,10 @@ static void __maybe_unused vmbus_reserve_fb(void)
pci_dev_put(pdev);
}
if (!start)
if (!start) {
pr_warn("Unexpected framebuffer mmio base of zero\n");
return;
}
/*
* Make a claim for the frame buffer in the resource tree under the
@ -2423,6 +2454,8 @@ static void __maybe_unused vmbus_reserve_fb(void)
*/
for (; !fb_mmio && (size >= 0x100000); size >>= 1)
fb_mmio = __request_region(hyperv_mmio, start, size, fb_mmio_name, 0);
pr_info("hv_mmio=%pR,%pR fb=%pR\n", hyperv_mmio, hyperv_mmio->sibling, fb_mmio);
}
/**
@ -2897,7 +2930,8 @@ static void hv_crash_handler(struct pt_regs *regs)
{
int cpu;
vmbus_initiate_unload(true);
if (!skip_vmbus_unload)
vmbus_initiate_unload(true);
/*
* In crash handler we can't schedule synic cleanup for all CPUs,
* doing the cleanup for current CPU only. This should be sufficient

View file

@ -10,18 +10,12 @@
/*
* The guest OS needs to register the guest ID with the hypervisor.
* The guest ID is a 64 bit entity and the structure of this ID is
* The guest ID is a 64-bit entity and the structure of this ID is
* specified in the Hyper-V TLFS specification.
*
* While the current guideline does not specify how Linux guest ID(s)
* need to be generated, our plan is to publish the guidelines for
* Linux and other guest operating systems that currently are hosted
* on Hyper-V. The implementation here conforms to this yet
* unpublished guidelines.
*
* Bit(s)
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
* 62:56 - Os Type; Linux is 0x100
* 62:56 - OS Type; Linux is 0x1
* 55:48 - Distro specific identification
* 47:16 - Linux kernel version number
* 15:0 - Distro specific identification

View file

@ -79,6 +79,7 @@ struct hv_vp_register_page {
u64 registers[18];
};
u8 reserved[8];
/* Volatile XMM registers (HV_X64_REGISTER_CLASS_XMM) */
union {
struct {

View file

@ -1304,7 +1304,11 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
struct device *hv_get_vmbus_root_device(void);
#if IS_ENABLED(CONFIG_HYPERV_VMBUS)
bool hv_vmbus_exists(void);
#else
static inline bool hv_vmbus_exists(void) { return false; }
#endif
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
@ -1336,6 +1340,9 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
bool fb_overlap_ok);
void vmbus_free_mmio(resource_size_t start, resource_size_t size);
void vmbus_initiate_unload(bool crash);
void vmbus_set_skip_unload(bool skip);
/*
* GUID definitions of various offer types - services offered to the guest.
*/