Skip to content

Commit

Permalink
x86/hyperv: handling hypercall page setup for root
Browse files Browse the repository at this point in the history
When Linux is running as the root partition, the hypercall page will
have already been setup by Hyper-V. Copy the content over to the
allocated page.

Add checks to hv_suspend & co to bail early because they are not
supported in this setup yet.

Signed-off-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Co-Developed-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
Co-Developed-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20210203150435.27941-8-wei.liu@kernel.org
  • Loading branch information
Wei Liu committed Feb 11, 2021
1 parent 99a0f46 commit 80f73c9
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions arch/x86/hyperv/hv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/cpuhotplug.h>
#include <linux/syscore_ops.h>
#include <clocksource/hyperv_timer.h>
#include <linux/highmem.h>

int hyperv_init_cpuhp;
u64 hv_current_partition_id = ~0ull;
Expand Down Expand Up @@ -286,6 +287,9 @@ static int hv_suspend(void)
union hv_x64_msr_hypercall_contents hypercall_msr;
int ret;

if (hv_root_partition)
return -EPERM;

/*
* Reset the hypercall page as it is going to be invalidated
* accross hibernation. Setting hv_hypercall_pg to NULL ensures
Expand Down Expand Up @@ -454,8 +458,35 @@ void __init hyperv_init(void)

rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
hypercall_msr.enable = 1;
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);

if (hv_root_partition) {
struct page *pg;
void *src, *dst;

/*
* For the root partition, the hypervisor will set up its
* hypercall page. The hypervisor guarantees it will not show
* up in the root's address space. The root can't change the
* location of the hypercall page.
*
* Order is important here. We must enable the hypercall page
* so it is populated with code, then copy the code to an
* executable page.
*/
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);

pg = vmalloc_to_page(hv_hypercall_pg);
dst = kmap(pg);
src = memremap(hypercall_msr.guest_physical_address << PAGE_SHIFT, PAGE_SIZE,
MEMREMAP_WB);
BUG_ON(!(src && dst));
memcpy(dst, src, HV_HYP_PAGE_SIZE);
memunmap(src);
kunmap(pg);
} else {
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
}

/*
* hyperv_init() is called before LAPIC is initialized: see
Expand Down Expand Up @@ -604,7 +635,7 @@ EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);

bool hv_is_hibernation_supported(void)
{
return acpi_sleep_state_supported(ACPI_STATE_S4);
return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);
}
EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);

Expand Down

0 comments on commit 80f73c9

Please sign in to comment.