Commit 8730046c authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by Greg Kroah-Hartman

Drivers: hv vmbus: Move Hypercall page setup out of common code

As part of the effort to separate out architecture specific code, move the
hypercall page setup to an architecture specific file.
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 352c9624
...@@ -5962,6 +5962,7 @@ S: Maintained ...@@ -5962,6 +5962,7 @@ S: Maintained
F: arch/x86/include/asm/mshyperv.h F: arch/x86/include/asm/mshyperv.h
F: arch/x86/include/uapi/asm/hyperv.h F: arch/x86/include/uapi/asm/hyperv.h
F: arch/x86/kernel/cpu/mshyperv.c F: arch/x86/kernel/cpu/mshyperv.c
F: arch/x86/hyperv
F: drivers/hid/hid-hyperv.c F: drivers/hid/hid-hyperv.c
F: drivers/hv/ F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c F: drivers/input/serio/hyperv-keyboard.c
......
...@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/ ...@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
# Xen paravirtualization support # Xen paravirtualization support
obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_XEN) += xen/
# Hyper-V paravirtualization support
obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
# lguest paravirtualization support # lguest paravirtualization support
obj-$(CONFIG_LGUEST_GUEST) += lguest/ obj-$(CONFIG_LGUEST_GUEST) += lguest/
......
obj-y := hv_init.o
/*
* X86 specific Hyper-V initialization code.
*
* Copyright (C) 2016, Microsoft, Inc.
*
* Author : K. Y. Srinivasan <kys@microsoft.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
*/
#include <linux/types.h>
#include <asm/hypervisor.h>
#include <asm/hyperv.h>
#include <asm/mshyperv.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
void *hv_hypercall_pg;
/*
* This function is to be invoked early in the boot sequence after the
* hypervisor has been detected.
*
* 1. Setup the hypercall page.
*/
void hyperv_init(void)
{
u64 guest_id;
union hv_x64_msr_hypercall_contents hypercall_msr;
if (x86_hyper != &x86_hyper_ms_hyperv)
return;
/*
* Setup the hypercall page and enable hypercalls.
* 1. Register the guest ID
* 2. Enable the hypercall and register the hypercall page
*/
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (hv_hypercall_pg == NULL) {
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
return;
}
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);
}
EXPORT_SYMBOL_GPL(hv_hypercall_pg);
...@@ -80,4 +80,9 @@ void hv_setup_kexec_handler(void (*handler)(void)); ...@@ -80,4 +80,9 @@ void hv_setup_kexec_handler(void (*handler)(void));
void hv_remove_kexec_handler(void); void hv_remove_kexec_handler(void);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void); void hv_remove_crash_handler(void);
#if IS_ENABLED(CONFIG_HYPERV)
void hyperv_init(void);
extern void *hv_hypercall_pg;
#endif
#endif #endif
...@@ -227,6 +227,13 @@ static void __init ms_hyperv_init_platform(void) ...@@ -227,6 +227,13 @@ static void __init ms_hyperv_init_platform(void)
*/ */
if (efi_enabled(EFI_BOOT)) if (efi_enabled(EFI_BOOT))
x86_platform.get_nmi_reason = hv_get_nmi_reason; x86_platform.get_nmi_reason = hv_get_nmi_reason;
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Setup the hook to get control post apic initialization.
*/
x86_platform.apic_post_init = hyperv_init;
#endif
} }
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
......
...@@ -193,7 +193,6 @@ int hv_init(void) ...@@ -193,7 +193,6 @@ int hv_init(void)
{ {
int max_leaf; int max_leaf;
union hv_x64_msr_hypercall_contents hypercall_msr; union hv_x64_msr_hypercall_contents hypercall_msr;
void *virtaddr = NULL;
memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
memset(hv_context.synic_message_page, 0, memset(hv_context.synic_message_page, 0,
...@@ -211,33 +210,15 @@ int hv_init(void) ...@@ -211,33 +210,15 @@ int hv_init(void)
max_leaf = query_hypervisor_info(); max_leaf = query_hypervisor_info();
/*
* Write our OS ID.
*/
hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0);
wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
/* See if the hypercall page is already set */ /* See if the hypercall page is already set */
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (!virtaddr)
goto cleanup;
hypercall_msr.enable = 1;
hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr);
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
/* Confirm that hypercall page did get setup. */
hypercall_msr.as_uint64 = 0; hypercall_msr.as_uint64 = 0;
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
if (!hypercall_msr.enable) if (!hypercall_msr.enable)
goto cleanup; return -ENOTSUPP;
hv_context.hypercall_page = virtaddr; hv_context.hypercall_page = hv_hypercall_pg;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
...@@ -261,15 +242,6 @@ int hv_init(void) ...@@ -261,15 +242,6 @@ int hv_init(void)
return 0; return 0;
cleanup: cleanup:
if (virtaddr) {
if (hypercall_msr.enable) {
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
}
vfree(virtaddr);
}
return -ENOTSUPP; return -ENOTSUPP;
} }
...@@ -280,20 +252,9 @@ int hv_init(void) ...@@ -280,20 +252,9 @@ int hv_init(void)
*/ */
void hv_cleanup(bool crash) void hv_cleanup(bool crash)
{ {
union hv_x64_msr_hypercall_contents hypercall_msr;
/* Reset our OS id */
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
if (hv_context.hypercall_page) {
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
if (!crash)
vfree(hv_context.hypercall_page);
hv_context.hypercall_page = NULL;
}
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
union hv_x64_msr_hypercall_contents hypercall_msr;
/* /*
* Cleanup the TSC page based CS. * Cleanup the TSC page based CS.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment