diff --git a/xen/arch/x86/guest/Makefile b/xen/arch/x86/guest/Makefile
index 6806f04947..f63d64bbee 100644
--- a/xen/arch/x86/guest/Makefile
+++ b/xen/arch/x86/guest/Makefile
@@ -1 +1,3 @@
+obj-y += hypervisor.o
+
 subdir-$(CONFIG_XEN_GUEST) += xen
diff --git a/xen/arch/x86/guest/hypervisor.c b/xen/arch/x86/guest/hypervisor.c
new file mode 100644
index 0000000000..b0a724bf13
--- /dev/null
+++ b/xen/arch/x86/guest/hypervisor.c
@@ -0,0 +1,112 @@
+/******************************************************************************
+ * arch/x86/guest/hypervisor.c
+ *
+ * Support for detecting and running under a hypervisor.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2017 Citrix Systems Ltd.
+ */
+
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/rangeset.h>
+
+#include <asm/guest.h>
+#include <asm/processor.h>
+
+static struct rangeset *mem;
+
+void __init probe_hypervisor(void)
+{
+    /* Too early to use cpu_has_hypervisor */
+    if ( !(cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_HYPERVISOR)) )
+        return;
+
+    probe_xen();
+}
+
+static void __init init_memmap(void)
+{
+    unsigned int i;
+
+    mem = rangeset_new(NULL, "host memory map", 0);
+    if ( !mem )
+        panic("failed to allocate PFN usage rangeset\n");
+
+    /*
+     * Mark up to the last memory page (or 4GiB) as RAM. This is done because
+     * Xen doesn't know the position of possible MMIO holes, so at least try to
+     * avoid the know MMIO hole below 4GiB. Note that this is subject to future
+     * discussion and improvements.
+     */
+    if ( rangeset_add_range(mem, 0, max_t(unsigned long, max_page - 1,
+                                          PFN_DOWN(GB(4) - 1))) )
+        panic("unable to add RAM to in-use PFN rangeset\n");
+
+    for ( i = 0; i < e820.nr_map; i++ )
+    {
+        struct e820entry *e = &e820.map[i];
+
+        if ( rangeset_add_range(mem, PFN_DOWN(e->addr),
+                                PFN_UP(e->addr + e->size - 1)) )
+            panic("unable to add range [%#lx, %#lx] to in-use PFN rangeset\n",
+                  PFN_DOWN(e->addr), PFN_UP(e->addr + e->size - 1));
+    }
+}
+
+void __init hypervisor_setup(void)
+{
+    init_memmap();
+
+    xen_setup();
+}
+
+void hypervisor_ap_setup(void)
+{
+    xen_ap_setup();
+}
+
+int hypervisor_alloc_unused_page(mfn_t *mfn)
+{
+    unsigned long m;
+    int rc;
+
+    rc = rangeset_claim_range(mem, 1, &m);
+    if ( !rc )
+        *mfn = _mfn(m);
+
+    return rc;
+}
+
+int hypervisor_free_unused_page(mfn_t mfn)
+{
+    return rangeset_remove_range(mem, mfn_x(mfn), mfn_x(mfn));
+}
+
+void hypervisor_resume(void)
+{
+    xen_resume();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff --git a/xen/arch/x86/guest/xen/xen.c b/xen/arch/x86/guest/xen/xen.c
index f93c8fbd1c..a730e6ad1b 100644
--- a/xen/arch/x86/guest/xen/xen.c
+++ b/xen/arch/x86/guest/xen/xen.c
@@ -39,7 +39,6 @@ bool __read_mostly xen_guest;
 
 __read_mostly uint32_t xen_cpuid_base;
 extern char hypercall_page[];
-static struct rangeset *mem;
 
 DEFINE_PER_CPU(unsigned int, vcpu_id);
 
@@ -67,15 +66,11 @@ static void __init find_xen_leaves(void)
     }
 }
 
-static void __init probe_xen(void)
+void __init probe_xen(void)
 {
     if ( xen_guest )
         return;
 
-    /* Too early to use cpu_has_hypervisor */
-    if ( !(cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_HYPERVISOR)) )
-        return;
-
     find_xen_leaves();
 
     if ( !xen_cpuid_base )
@@ -87,11 +82,6 @@ static void __init probe_xen(void)
     xen_guest = true;
 }
 
-void __init probe_hypervisor(void)
-{
-    probe_xen();
-}
-
 static void map_shared_info(void)
 {
     mfn_t mfn;
@@ -166,35 +156,6 @@ static void set_vcpu_id(void)
         this_cpu(vcpu_id) = smp_processor_id();
 }
 
-static void __init init_memmap(void)
-{
-    unsigned int i;
-
-    mem = rangeset_new(NULL, "host memory map", 0);
-    if ( !mem )
-        panic("failed to allocate PFN usage rangeset\n");
-
-    /*
-     * Mark up to the last memory page (or 4GiB) as RAM. This is done because
-     * Xen doesn't know the position of possible MMIO holes, so at least try to
-     * avoid the know MMIO hole below 4GiB. Note that this is subject to future
-     * discussion and improvements.
-     */
-    if ( rangeset_add_range(mem, 0, max_t(unsigned long, max_page - 1,
-                                          PFN_DOWN(GB(4) - 1))) )
-        panic("unable to add RAM to in-use PFN rangeset\n");
-
-    for ( i = 0; i < e820.nr_map; i++ )
-    {
-        struct e820entry *e = &e820.map[i];
-
-        if ( rangeset_add_range(mem, PFN_DOWN(e->addr),
-                                PFN_UP(e->addr + e->size - 1)) )
-            panic("unable to add range [%#lx, %#lx] to in-use PFN rangeset\n",
-                  PFN_DOWN(e->addr), PFN_UP(e->addr + e->size - 1));
-    }
-}
-
 static void xen_evtchn_upcall(struct cpu_user_regs *regs)
 {
     struct vcpu_info *vcpu_info = this_cpu(vcpu_info);
@@ -254,7 +215,7 @@ static void init_evtchn(void)
     }
 }
 
-static void __init xen_setup(void)
+void __init xen_setup(void)
 {
     map_shared_info();
 
@@ -280,49 +241,20 @@ static void __init xen_setup(void)
     init_evtchn();
 }
 
-void __init hypervisor_setup(void)
-{
-    init_memmap();
-
-    xen_setup();
-}
-
-static void xen_ap_setup(void)
+void xen_ap_setup(void)
 {
     set_vcpu_id();
     map_vcpuinfo();
     init_evtchn();
 }
 
-void hypervisor_ap_setup(void)
-{
-    xen_ap_setup();
-}
-
-int hypervisor_alloc_unused_page(mfn_t *mfn)
-{
-    unsigned long m;
-    int rc;
-
-    rc = rangeset_claim_range(mem, 1, &m);
-    if ( !rc )
-        *mfn = _mfn(m);
-
-    return rc;
-}
-
-int hypervisor_free_unused_page(mfn_t mfn)
-{
-    return rangeset_remove_range(mem, mfn_x(mfn), mfn_x(mfn));
-}
-
 static void ap_resume(void *unused)
 {
     map_vcpuinfo();
     init_evtchn();
 }
 
-static void xen_resume(void)
+void xen_resume(void)
 {
     /* Reset shared info page. */
     map_shared_info();
@@ -345,11 +277,6 @@ static void xen_resume(void)
         pv_console_init();
 }
 
-void hypervisor_resume(void)
-{
-    xen_resume();
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-x86/guest.h b/xen/include/asm-x86/guest.h
index a38c6b5b3f..8e167165ae 100644
--- a/xen/include/asm-x86/guest.h
+++ b/xen/include/asm-x86/guest.h
@@ -20,6 +20,7 @@
 #define __X86_GUEST_H__
 
 #include <asm/guest/hypercall.h>
+#include <asm/guest/hypervisor.h>
 #include <asm/guest/pvh-boot.h>
 #include <asm/guest/xen.h>
 #include <asm/pv/shim.h>
diff --git a/xen/include/asm-x86/guest/hypervisor.h b/xen/include/asm-x86/guest/hypervisor.h
new file mode 100644
index 0000000000..135ad36f72
--- /dev/null
+++ b/xen/include/asm-x86/guest/hypervisor.h
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * asm-x86/guest/hypervisor.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions 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.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __X86_GUEST_HYPERVISOR_H__
+#define __X86_GUEST_HYPERVISOR_H__
+
+#ifdef CONFIG_GUEST
+
+#include <xen/mm.h>
+
+void probe_hypervisor(void);
+void hypervisor_setup(void);
+void hypervisor_ap_setup(void);
+int hypervisor_alloc_unused_page(mfn_t *mfn);
+int hypervisor_free_unused_page(mfn_t mfn);
+uint32_t hypervisor_cpuid_base(void);
+void hypervisor_resume(void);
+
+#else
+
+#include <xen/lib.h>
+
+static inline void probe_hypervisor(void) {}
+
+static inline void hypervisor_setup(void)
+{
+    ASSERT_UNREACHABLE();
+}
+static inline void hypervisor_ap_setup(void)
+{
+    ASSERT_UNREACHABLE();
+}
+
+#endif /* CONFIG_GUEST */
+#endif /* __X86_GUEST_HYPERVISOR_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/guest/xen.h b/xen/include/asm-x86/guest/xen.h
index b015ed1883..d031f1f70d 100644
--- a/xen/include/asm-x86/guest/xen.h
+++ b/xen/include/asm-x86/guest/xen.h
@@ -32,12 +32,10 @@ extern bool xen_guest;
 extern bool pv_console;
 extern uint32_t xen_cpuid_base;
 
-void probe_hypervisor(void);
-void hypervisor_setup(void);
-void hypervisor_ap_setup(void);
-int hypervisor_alloc_unused_page(mfn_t *mfn);
-int hypervisor_free_unused_page(mfn_t mfn);
-void hypervisor_resume(void);
+void probe_xen(void);
+void xen_setup(void);
+void xen_ap_setup(void);
+void xen_resume(void);
 
 DECLARE_PER_CPU(unsigned int, vcpu_id);
 DECLARE_PER_CPU(struct vcpu_info *, vcpu_info);
@@ -47,16 +45,7 @@ DECLARE_PER_CPU(struct vcpu_info *, vcpu_info);
 #define xen_guest 0
 #define pv_console 0
 
-static inline void probe_hypervisor(void) {}
-
-static inline void hypervisor_setup(void)
-{
-    ASSERT_UNREACHABLE();
-}
-static inline void hypervisor_ap_setup(void)
-{
-    ASSERT_UNREACHABLE();
-}
+static inline void probe_xen(void) {}
 
 #endif /* CONFIG_XEN_GUEST */
 #endif /* __X86_GUEST_XEN_H__ */
