[PATCH 2/2] xen: add sysfs node for guest type

From: Juergen Gross
Date: Mon May 22 2017 - 04:57:25 EST


Currently there is no reliable user interface inside a Xen guest to
determine its type (e.g. HVM, PV or PVH). Instead of letting user mode
try to determine this by various rather hacky mechanisms (parsing of
boot messages before they are gone, trying to make use of known subtle
differences in behavior of some instructions), add a sysfs node
/sys/hypervisor/guest_type to explicitly deliver this information as
it is known to the kernel.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
Documentation/ABI/testing/sysfs-hypervisor | 13 +++++++++++++
arch/arm/xen/enlighten.c | 3 +++
arch/x86/xen/enlighten.c | 3 +++
arch/x86/xen/enlighten_hvm.c | 6 ++++--
arch/x86/xen/enlighten_pv.c | 1 +
drivers/xen/sys-hypervisor.c | 17 +++++++++++++++++
include/xen/xen.h | 2 ++
7 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-hypervisor b/Documentation/ABI/testing/sysfs-hypervisor
index 443196f0aa1c..06850f74ebd4 100644
--- a/Documentation/ABI/testing/sysfs-hypervisor
+++ b/Documentation/ABI/testing/sysfs-hypervisor
@@ -19,6 +19,19 @@ Contact: xen-devel@xxxxxxxxxxxxxxxxxxxx
Description:
Compiler which was used to build the Xen hypervisor

+What: /sys/hypervisor/guest_type
+Date: May 2017
+KernelVersion: 4.12
+Contact: xen-devel@xxxxxxxxxxxxxxxxxxxx
+Description:
+ Type of guest:
+ "native": standard guest type on arm
+ "HVM": fully virtualized guest (x86)
+ "PV": paravirtualized guest (x86)
+ "PVH": fully virtualized guest without legacy emulation (x86)
+ "PVHVM": fully virtualized guest using paravirtualized
+ interfaces (e.g. interrupts, timers) (x86)
+
What: /sys/hypervisor/pmu/pmu_mode
Date: August 2015
KernelVersion: 4.3
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index ba7f4c8f5c3e..d2100f79e458 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -43,6 +43,9 @@ EXPORT_SYMBOL(xen_start_info);
enum xen_domain_type xen_domain_type = XEN_NATIVE;
EXPORT_SYMBOL(xen_domain_type);

+char *xen_guest_type = "native";
+EXPORT_SYMBOL_GPL(xen_guest_type);
+
struct shared_info xen_dummy_shared_info;
struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a5ffcbb20cc0..53bd23dfecac 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -47,6 +47,9 @@ EXPORT_PER_CPU_SYMBOL(xen_vcpu_id);
enum xen_domain_type xen_domain_type = XEN_NATIVE;
EXPORT_SYMBOL_GPL(xen_domain_type);

+char *xen_guest_type = "HVM";
+EXPORT_SYMBOL_GPL(xen_guest_type);
+
unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
EXPORT_SYMBOL(machine_to_phys_mapping);
unsigned long machine_to_phys_nr;
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index a6d014f47e52..ba6dbff8675d 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -68,13 +68,15 @@ static void __init init_hvm_pv_info(void)
xen_domain_type = XEN_HVM_DOMAIN;

/* PVH set up hypercall page in xen_prepare_pvh(). */
- if (xen_pvh_domain())
+ if (xen_pvh_domain()) {
pv_info.name = "Xen PVH";
- else {
+ xen_guest_type = "PVH";
+ } else {
u64 pfn;
uint32_t msr;

pv_info.name = "Xen HVM";
+ xen_guest_type = "PVHVM";
msr = cpuid_ebx(base + 2);
pfn = __pa(hypercall_page);
wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index f33eef4ebd12..7ac5e93d96f3 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1255,6 +1255,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
return;

xen_domain_type = XEN_PV_DOMAIN;
+ xen_guest_type = "PV";

xen_setup_features();

diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index 84106f9c456c..d641e9970d5d 100644
--- a/drivers/xen/sys-hypervisor.c
+++ b/drivers/xen/sys-hypervisor.c
@@ -50,6 +50,18 @@ static int __init xen_sysfs_type_init(void)
return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
}

+static ssize_t guest_type_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+ return sprintf(buffer, "%s\n", xen_guest_type);
+}
+
+HYPERVISOR_ATTR_RO(guest_type);
+
+static int __init xen_sysfs_guest_type_init(void)
+{
+ return sysfs_create_file(hypervisor_kobj, &guest_type_attr.attr);
+}
+
/* xen version attributes */
static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
{
@@ -471,6 +483,9 @@ static int __init hyper_sysfs_init(void)
ret = xen_sysfs_type_init();
if (ret)
goto out;
+ ret = xen_sysfs_guest_type_init();
+ if (ret)
+ goto guest_type_out;
ret = xen_sysfs_version_init();
if (ret)
goto version_out;
@@ -502,6 +517,8 @@ static int __init hyper_sysfs_init(void)
comp_out:
sysfs_remove_group(hypervisor_kobj, &version_group);
version_out:
+ sysfs_remove_file(hypervisor_kobj, &guest_type_attr.attr);
+guest_type_out:
sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
out:
return ret;
diff --git a/include/xen/xen.h b/include/xen/xen.h
index 6e8b7fc79801..3defb2e03c8b 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -9,8 +9,10 @@ enum xen_domain_type {

#ifdef CONFIG_XEN
extern enum xen_domain_type xen_domain_type;
+extern char *xen_guest_type;
#else
#define xen_domain_type XEN_NATIVE
+#define xen_guest_type "native"
#endif

#define xen_domain() (xen_domain_type != XEN_NATIVE)
--
2.12.0