From: K. Y. Srinivasan <k...@microsoft.com>

As part of the effort to separate out architecture specific code, move the
hypercall page setup to an architecture specific file.

Signed-off-by: K. Y. Srinivasan <k...@microsoft.com>
---
 arch/x86/Kbuild                 |    3 ++
 arch/x86/hyperv/Makefile        |    1 +
 arch/x86/hyperv/hv_init.c       |   62 +++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/mshyperv.h |    5 +++
 arch/x86/kernel/cpu/mshyperv.c  |    7 ++++
 drivers/hv/hv.c                 |   45 ++--------------------------
 6 files changed, 81 insertions(+), 42 deletions(-)
 create mode 100644 arch/x86/hyperv/Makefile
 create mode 100644 arch/x86/hyperv/hv_init.c

diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index eb3abf8..586b786 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
 # Xen paravirtualization support
 obj-$(CONFIG_XEN) += xen/
 
+# Hyper-V paravirtualization support
+obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
+
 # lguest paravirtualization support
 obj-$(CONFIG_LGUEST_GUEST) += lguest/
 
diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
new file mode 100644
index 0000000..171ae09
--- /dev/null
+++ b/arch/x86/hyperv/Makefile
@@ -0,0 +1 @@
+obj-y          := hv_init.o
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
new file mode 100644
index 0000000..3206bfda
--- /dev/null
+++ b/arch/x86/hyperv/hv_init.c
@@ -0,0 +1,62 @@
+/*
+ * X86 specific Hyper-V initialization code.
+ *
+ * Copyright (C) 2016, Microsoft, Inc.
+ *
+ * Author : K. Y. Srinivasan <k...@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);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 15a0c27..e5f57e1 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -80,4 +80,9 @@ static inline  __u64 generate_guest_id(__u64 d_info1, __u64 
kernel_version,
 void hv_remove_kexec_handler(void);
 void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
 void hv_remove_crash_handler(void);
+
+#if IS_ENABLED(CONFIG_HYPERV)
+void hyperv_init(void);
+extern void *hv_hypercall_pg;
+#endif
 #endif
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 8f44c5a..8b376f8 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -204,6 +204,13 @@ static void __init ms_hyperv_init_platform(void)
         */
        if (efi_enabled(EFI_BOOT))
                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 = {
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 04a0fd8..a11e827 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -193,7 +193,6 @@ int hv_init(void)
 {
        int max_leaf;
        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_message_page, 0,
@@ -211,33 +210,15 @@ int hv_init(void)
 
        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 */
-       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;
        rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
 
        if (!hypercall_msr.enable)
-               goto cleanup;
+               return -ENOTSUPP;
 
-       hv_context.hypercall_page = virtaddr;
+       hv_context.hypercall_page = hv_hypercall_pg;
 
 #ifdef CONFIG_X86_64
        if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
@@ -261,15 +242,6 @@ int hv_init(void)
        return 0;
 
 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;
 }
 
@@ -280,20 +252,9 @@ int hv_init(void)
  */
 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
+       union hv_x64_msr_hypercall_contents hypercall_msr;
        /*
         * Cleanup the TSC page based CS.
         */
-- 
1.7.4.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to