[Xen-devel] [RFC PATCH 02/16] x86/xen: cpuid support in xenhost_t

Ankur Arora posted 16 patches 1 year, 11 months ago

[Xen-devel] [RFC PATCH 02/16] x86/xen: cpuid support in xenhost_t

Posted by Ankur Arora 1 year, 11 months ago
xen_cpuid_base() is used to probe and setup features early in a
guest's lifetime.

We want this to behave differently depending on xenhost->type: for
instance, local xenhosts cannot intercept the cpuid instruction at all.

Add op (*cpuid_base)() in xenhost_ops_t.

Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
---
 arch/x86/include/asm/xen/hypervisor.h |  2 +-
 arch/x86/pci/xen.c                    |  2 +-
 arch/x86/xen/enlighten_hvm.c          |  7 +++++--
 arch/x86/xen/enlighten_pv.c           | 16 +++++++++++++++-
 arch/x86/xen/enlighten_pvh.c          |  4 ++++
 drivers/tty/hvc/hvc_xen.c             |  2 +-
 drivers/xen/grant-table.c             |  3 ++-
 drivers/xen/xenbus/xenbus_xs.c        |  3 ++-
 include/xen/xenhost.h                 | 21 +++++++++++++++++++++
 9 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
index 39171b3646bb..6c4cdcdf997d 100644
--- a/arch/x86/include/asm/xen/hypervisor.h
+++ b/arch/x86/include/asm/xen/hypervisor.h
@@ -53,7 +53,7 @@ static inline bool xen_x2apic_para_available(void)
 #else
 static inline bool xen_x2apic_para_available(void)
 {
-	return (xen_cpuid_base() != 0);
+	return (xen_cpuid_base(NULL) != 0);
 }
 #endif
 
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 9112d1cb397b..d1a3b9f08289 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -431,7 +431,7 @@ void __init xen_msi_init(void)
 		 * event channels for MSI handling and instead use regular
 		 * APIC processing
 		 */
-		uint32_t eax = cpuid_eax(xen_cpuid_base() + 4);
+		uint32_t eax = cpuid_eax(xenhost_cpuid_base(xh_default) + 4);
 
 		if (((eax & XEN_HVM_CPUID_X2APIC_VIRT) && x2apic_mode) ||
 		    ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && boot_cpu_has(X86_FEATURE_APIC)))
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 100452f4f44c..ffc5791675b2 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -83,7 +83,10 @@ static void __init xen_hvm_init_mem_mapping(void)
 	xen_vcpu_info_reset(0);
 }
 
+extern uint32_t xen_pv_cpuid_base(xenhost_t *xh);
+
 xenhost_ops_t xh_hvm_ops = {
+	.cpuid_base = xen_pv_cpuid_base,
 };
 
 xenhost_ops_t xh_hvm_nested_ops = {
@@ -94,7 +97,7 @@ static void __init init_hvm_pv_info(void)
 	int major, minor;
 	uint32_t eax, ebx, ecx, edx, base;
 
-	base = xen_cpuid_base();
+	base = xenhost_cpuid_base(xh_default);
 	eax = cpuid_eax(base + 1);
 
 	major = eax >> 16;
@@ -250,7 +253,7 @@ static uint32_t __init xen_platform_hvm(void)
 	if (xen_pv_domain() || xen_nopv)
 		return 0;
 
-	return xen_cpuid_base();
+	return xenhost_cpuid_base(xh_default);
 }
 
 static __init void xen_hvm_guest_late_init(void)
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index bb6e811c1525..a4e04b0cc596 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1189,10 +1189,23 @@ static void __init xen_dom0_set_legacy_features(void)
 	x86_platform.legacy.rtc = 1;
 }
 
+uint32_t xen_pv_cpuid_base(xenhost_t *xh)
+{
+	return hypervisor_cpuid_base("XenVMMXenVMM", 2);
+}
+
+uint32_t xen_pv_nested_cpuid_base(xenhost_t *xh)
+{
+	return hypervisor_cpuid_base("XenVMMXenVMM",
+				2 /* nested specific leaf? */);
+}
+
 xenhost_ops_t xh_pv_ops = {
+	.cpuid_base = xen_pv_cpuid_base,
 };
 
 xenhost_ops_t xh_pv_nested_ops = {
+	.cpuid_base = xen_pv_nested_cpuid_base,
 };
 
 /* First C function to be called on Xen boot */
@@ -1469,7 +1482,8 @@ static int xen_cpu_dead_pv(unsigned int cpu)
 static uint32_t __init xen_platform_pv(void)
 {
 	if (xen_pv_domain())
-		return xen_cpuid_base();
+		/* xenhost is setup in xen_start_kernel. */
+		return xenhost_cpuid_base(xh_default);
 
 	return 0;
 }
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index 826c296d27a3..c07eba169572 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -29,6 +29,10 @@ void __init xen_pvh_init(void)
 	u32 msr;
 	u64 pfn;
 
+	/*
+	 * Note: we have already called xen_cpuid_base() in
+	 * hypervisor_specific_init()
+	 */
 	xenhost_register(xenhost_r1, &xh_hvm_ops);
 
 	/*
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index dc43fa96c3de..5e5ca35d7187 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -595,7 +595,7 @@ console_initcall(xen_cons_init);
 #ifdef CONFIG_X86
 static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len)
 {
-	if (xen_cpuid_base())
+	if (xen_cpuid_base(xh_default))
 		outsb(0xe9, str, len);
 }
 #else
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 7ea6fb6a2e5d..98af259d0d4f 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -50,6 +50,7 @@
 #endif
 
 #include <xen/xen.h>
+#include <xen/xenhost.h>
 #include <xen/interface/xen.h>
 #include <xen/page.h>
 #include <xen/grant_table.h>
@@ -1318,7 +1319,7 @@ static bool gnttab_need_v2(void)
 	uint32_t base, width;
 
 	if (xen_pv_domain()) {
-		base = xen_cpuid_base();
+		base = xenhost_cpuid_base(xh_default);
 		if (cpuid_eax(base) < 5)
 			return false;	/* Information not available, use V1. */
 		width = cpuid_ebx(base + 5) &
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index 49a3874ae6bb..3236d1b1fa01 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -49,6 +49,7 @@
 #include <asm/xen/hypervisor.h>
 #include <xen/xenbus.h>
 #include <xen/xen.h>
+#include <xen/xenhost.h>
 #include "xenbus.h"
 
 /*
@@ -722,7 +723,7 @@ static bool xen_strict_xenbus_quirk(void)
 #ifdef CONFIG_X86
 	uint32_t eax, ebx, ecx, edx, base;
 
-	base = xen_cpuid_base();
+	base = xenhost_cpuid_base(xh_default);
 	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
 
 	if ((eax >> 16) < 4)
diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h
index a58e883f144e..13a70bdadfd2 100644
--- a/include/xen/xenhost.h
+++ b/include/xen/xenhost.h
@@ -1,6 +1,9 @@
 #ifndef __XENHOST_H
 #define __XENHOST_H
 
+#include <xen/interface/features.h>
+#include <xen/interface/xen.h>
+#include <asm/xen/hypervisor.h>
 /*
  * Xenhost abstracts out the Xen interface. It co-exists with the PV/HVM/PVH
  * abstractions (x86_init, hypervisor_x86, pv_ops etc) and is meant to
@@ -70,6 +73,16 @@ typedef struct {
 } xenhost_t;
 
 typedef struct xenhost_ops {
+	/*
+	 * xen_cpuid is used to probe features early.
+	 * xenhost_r0:
+	 *   Implementation could not use cpuid at all: it's difficult to
+	 *   intercept cpuid instruction locally.
+	 * xenhost_r1:
+	 * xenhost_r2:
+	 *   Separate cpuid-leafs?
+	 */
+	uint32_t (*cpuid_base)(xenhost_t *xenhost);
 } xenhost_ops_t;
 
 extern xenhost_t *xh_default, *xh_remote;
@@ -92,4 +105,12 @@ void __xenhost_unregister(enum xenhost_type type);
 	for ((xh) = (xenhost_t **) &xenhosts[0];	\
 		(((xh) - (xenhost_t **)&xenhosts) < 2) && (*xh)->type != xenhost_invalid; (xh)++)
 
+static inline uint32_t xenhost_cpuid_base(xenhost_t *xh)
+{
+	if (xh)
+		return (xh->ops->cpuid_base)(xh);
+	else
+		return xen_cpuid_base();
+}
+
 #endif /* __XENHOST_H */
-- 
2.20.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Re: [Xen-devel] [RFC PATCH 02/16] x86/xen: cpuid support in xenhost_t

Posted by Andrew Cooper 1 year, 10 months ago
On 09/05/2019 18:25, Ankur Arora wrote:
> xen_cpuid_base() is used to probe and setup features early in a
> guest's lifetime.
>
> We want this to behave differently depending on xenhost->type: for
> instance, local xenhosts cannot intercept the cpuid instruction at all.
>
> Add op (*cpuid_base)() in xenhost_ops_t.
>
> Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>

What is the real layout of hypervisor nesting here?

When Xen is at L0, all HVM guests get working CPUID faulting to combat
this problem, because CPUID faulting can be fully emulated even on older
Intel hardware, and AMD hardware.

It is a far cleaner way of fixing the problem.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel