@@ -161,11 +161,20 @@ config XEN_ALIGN_2M
endchoice
+config XEN_DETECT
+ def_bool y
+ prompt "Xen Detection"
+ ---help---
+ Support for Xen detecting when it is running under Xen.
+
+ If unsure, say Y.
+
config XEN_GUEST
def_bool n
prompt "Xen Guest"
+ depends on XEN_DETECT
---help---
- Support for Xen detecting when it is running under Xen.
+ Common PVH_GUEST and PV_SHIM logic for Xen as a Xen-aware guest.
If unsure, say N.
@@ -1,7 +1,7 @@
subdir-y += acpi
subdir-y += cpu
subdir-y += genapic
-subdir-$(CONFIG_XEN_GUEST) += guest
+subdir-$(CONFIG_XEN_DETECT) += guest
subdir-$(CONFIG_HVM) += hvm
subdir-y += mm
subdir-$(CONFIG_XENOPROF) += oprofile
@@ -1247,7 +1247,7 @@ static int __init calibrate_APIC_clock(void)
*/
__setup_APIC_LVTT(1000000000);
- if ( !xen_guest )
+ if ( !xen_detected )
/*
* The timer chip counts down to zero. Let's wait
* for a wraparound to start exact measurement:
@@ -1267,7 +1267,7 @@ static int __init calibrate_APIC_clock(void)
* Let's wait LOOPS ticks:
*/
for (i = 0; i < LOOPS; i++)
- if ( !xen_guest )
+ if ( !xen_detected )
wait_8254_wraparound();
else
wait_tick_pvh();
@@ -1,4 +1,4 @@
-obj-y += hypercall_page.o
+obj-$(CONFIG_XEN_GUEST) += hypercall_page.o
obj-y += xen.o
obj-$(CONFIG_XEN_GUEST) += xen-guest.o
@@ -35,6 +35,8 @@
#include <public/arch-x86/cpuid.h>
#include <public/hvm/params.h>
+extern char hypercall_page[];
+
bool __read_mostly xen_guest;
static struct rangeset *mem;
@@ -45,6 +47,14 @@ static struct vcpu_info *vcpu_info;
static unsigned long vcpu_info_mapped[BITS_TO_LONGS(NR_CPUS)];
DEFINE_PER_CPU(struct vcpu_info *, vcpu_info);
+void xen_guest_enable(void)
+{
+ /* Fill the hypercall page. */
+ wrmsrl(cpuid_ebx(hypervisor_cpuid_base() + 2), __pa(hypercall_page));
+
+ xen_guest = true;
+}
+
static void map_shared_info(void)
{
mfn_t mfn;
@@ -33,8 +33,10 @@
#include <public/arch-x86/cpuid.h>
#include <public/hvm/params.h>
+/* xen_detected: Xen running on Xen detected */
+bool __read_mostly xen_detected;
+
static __read_mostly uint32_t xen_cpuid_base;
-extern char hypercall_page[];
static void __init find_xen_leaves(void)
{
@@ -58,7 +60,7 @@ static void __init find_xen_leaves(void)
void __init probe_hypervisor(void)
{
- if ( xen_guest )
+ if ( xen_detected )
return;
/* Too early to use cpu_has_hypervisor */
@@ -70,10 +72,21 @@ void __init probe_hypervisor(void)
if ( !xen_cpuid_base )
return;
- /* Fill the hypercall page. */
- wrmsrl(cpuid_ebx(xen_cpuid_base + 2), __pa(hypercall_page));
+ xen_detected = true;
+
+ xen_guest_enable();
+}
+
+void __init hypervisor_print_info(void)
+{
+ uint32_t eax, ebx, ecx, edx;
+ unsigned int major, minor;
+
+ cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
- xen_guest = true;
+ major = eax >> 16;
+ minor = eax & 0xffff;
+ printk("Nested Xen version %u.%u.\n", major, minor);
}
uint32_t hypervisor_cpuid_base(void)
@@ -774,6 +774,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
ehci_dbgp_init();
console_init_preirq();
+ if ( xen_detected )
+ hypervisor_print_info();
+
if ( pvh_boot )
pvh_print_info();
@@ -24,20 +24,37 @@
#include <asm/e820.h>
#include <asm/fixmap.h>
-#define XEN_shared_info ((struct shared_info *)fix_to_virt(FIX_XEN_SHARED_INFO))
+#ifdef CONFIG_XEN_DETECT
+
+extern bool xen_detected;
+
+void probe_hypervisor(void);
+void hypervisor_print_info(void);
+uint32_t hypervisor_cpuid_base(void);
+
+#else
+
+#define xen_detected 0
+
+static inline void probe_hypervisor(void) {}
+static inline void hypervisor_print_info(void) {
+ ASSERT_UNREACHABLE();
+}
+
+#endif /* CONFIG_XEN_DETECT */
#ifdef CONFIG_XEN_GUEST
+#define XEN_shared_info ((struct shared_info *)fix_to_virt(FIX_XEN_SHARED_INFO))
extern bool xen_guest;
extern bool pv_console;
-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);
+void xen_guest_enable(void);
DECLARE_PER_CPU(unsigned int, vcpu_id);
DECLARE_PER_CPU(struct vcpu_info *, vcpu_info);
@@ -47,8 +64,6 @@ 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();
@@ -57,6 +72,7 @@ static inline void hypervisor_ap_setup(void)
{
ASSERT_UNREACHABLE();
}
+static inline void xen_guest_enable(void) {}
#endif /* CONFIG_XEN_GUEST */
#endif /* __X86_GUEST_XEN_H__ */
Add Kconfig option XEN_DETECT for: "Support for Xen detecting when it is running under Xen". If running under Xen is detected, a boot message will indicate the hypervisor version obtained from cpuid. Update the XEN_GUEST Kconfig option text to reflect its current purpose: "Common PVH_GUEST and PV_SHIM logic for Xen as a Xen-aware guest". Update calibrate_APIC_clock to use Xen-specific init if nested Xen is detected, even if not operating as a PV shim or booted as PVH. This work is a precursor to adding the interface for support of PV drivers on nested Xen. Signed-off-by: Christopher Clark <christopher.clark@starlab.io> --- xen/arch/x86/Kconfig | 11 ++++++++++- xen/arch/x86/Makefile | 2 +- xen/arch/x86/apic.c | 4 ++-- xen/arch/x86/guest/Makefile | 2 +- xen/arch/x86/guest/xen-guest.c | 10 ++++++++++ xen/arch/x86/guest/xen.c | 23 ++++++++++++++++++----- xen/arch/x86/setup.c | 3 +++ xen/include/asm-x86/guest/xen.h | 26 +++++++++++++++++++++----- 8 files changed, 66 insertions(+), 15 deletions(-)