[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC 3/9] x86/nested: add nested_xen_version hypercall



Provides proxying to the host hypervisor for XENVER_version and
XENVER_get_features ops.

The nested PV interface is only enabled when Xen is not running as
either the PV shim or booted as PVH, since the initialization performed
within the hypervisor in those cases - ie. as a Xen guest - claims resources
that are normally operated by the control domain.

This nested hypercall only permits access from the control domain.
The XSM policy hook implementation is deferred to a subsequent commit.

Signed-off-by: Christopher Clark <christopher.clark@xxxxxxxxxx>
---
 xen/arch/x86/Kconfig                  | 22 +++++++
 xen/arch/x86/guest/Makefile           |  5 +-
 xen/arch/x86/guest/hypercall_page.S   |  1 +
 xen/arch/x86/guest/xen-nested.c       | 82 +++++++++++++++++++++++++++
 xen/arch/x86/guest/xen.c              |  5 +-
 xen/arch/x86/hypercall.c              |  3 +
 xen/arch/x86/pv/hypercall.c           |  3 +
 xen/include/asm-x86/guest/hypercall.h |  7 ++-
 xen/include/asm-x86/guest/xen.h       | 10 ++++
 xen/include/public/xen.h              |  1 +
 xen/include/xen/hypercall.h           |  6 ++
 11 files changed, 142 insertions(+), 3 deletions(-)
 create mode 100644 xen/arch/x86/guest/xen-nested.c

diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 31e5ffd2f2..e31e8d3434 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -207,6 +207,28 @@ config PV_SHIM_EXCLUSIVE
          option is only intended for use when building a dedicated PV Shim
          firmware, and will not function correctly in other scenarios.
 
+         If unsure, say N.
+
+config XEN_NESTED
+       bool "Xen PV driver interface for nested Xen" if EXPERT = "y"
+       depends on XEN_DETECT
+       ---help---
+         Enables a second PV driver interface in the hypervisor to support 
running
+         two sets of PV drivers within a single privileged guest (eg. guest 
dom0)
+         of a system running Xen under Xen:
+
+         1) host set: frontends to access devices provided by lower hypervisor
+         2) guest set: backends to support existing PV drivers in nested guest 
VMs
+
+         This interface supports the host set of drivers and performs proxying 
of a
+         limited set of hypercall operations from the guest to the host 
hypervisor.
+
+         This feature is for the guest hypervisor and is transparent to the
+         host hypervisor. Guest VMs of the guest hypervisor use the standard
+         PV driver interfaces and unmodified drivers.
+
+         Feature is also known as "The Xen-Blanket", presented at Eurosys 2012.
+
          If unsure, say N.
 endmenu
 
diff --git a/xen/arch/x86/guest/Makefile b/xen/arch/x86/guest/Makefile
index d3a7844e61..6d8b0186d4 100644
--- a/xen/arch/x86/guest/Makefile
+++ b/xen/arch/x86/guest/Makefile
@@ -1,5 +1,8 @@
-obj-$(CONFIG_XEN_GUEST) += hypercall_page.o
+ifneq ($(filter y,$(CONFIG_XEN_GUEST) $(CONFIG_XEN_NESTED) 
$(CONFIG_PVH_GUEST)),)
+obj-y += hypercall_page.o
+endif
 obj-y += xen.o
 obj-$(CONFIG_XEN_GUEST) += xen-guest.o
+obj-$(CONFIG_XEN_NESTED) += xen-nested.o
 
 obj-bin-$(CONFIG_PVH_GUEST) += pvh-boot.init.o
diff --git a/xen/arch/x86/guest/hypercall_page.S 
b/xen/arch/x86/guest/hypercall_page.S
index 6485e9150e..2b1e35803a 100644
--- a/xen/arch/x86/guest/hypercall_page.S
+++ b/xen/arch/x86/guest/hypercall_page.S
@@ -60,6 +60,7 @@ DECLARE_HYPERCALL(domctl)
 DECLARE_HYPERCALL(kexec_op)
 DECLARE_HYPERCALL(argo_op)
 DECLARE_HYPERCALL(xenpmu_op)
+DECLARE_HYPERCALL(nested_xen_version)
 
 DECLARE_HYPERCALL(arch_0)
 DECLARE_HYPERCALL(arch_1)
diff --git a/xen/arch/x86/guest/xen-nested.c b/xen/arch/x86/guest/xen-nested.c
new file mode 100644
index 0000000000..744592aa0c
--- /dev/null
+++ b/xen/arch/x86/guest/xen-nested.c
@@ -0,0 +1,82 @@
+/*
+ * arch/x86/guest/xen-nested.c
+ *
+ * Hypercall implementations for nested PV drivers interface.
+ *
+ * Copyright (c) 2019 Star Lab Corp
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <xen/config.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/hypercall.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+
+#include <public/version.h>
+
+#include <asm/guest/hypercall.h>
+#include <asm/guest/xen.h>
+
+extern char hypercall_page[];
+
+/* xen_nested: support for nested PV interface enabled */
+static bool __read_mostly xen_nested;
+
+void xen_nested_enable(void)
+{
+    /* Fill the hypercall page. */
+    wrmsrl(cpuid_ebx(hypervisor_cpuid_base() + 2), __pa(hypercall_page));
+
+    xen_nested = true;
+}
+
+long do_nested_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    long ret;
+
+    if ( !xen_nested )
+        return -ENOSYS;
+
+    /* FIXME: apply XSM check here */
+    if ( !is_control_domain(current->domain) )
+        return -EPERM;
+
+    gprintk(XENLOG_DEBUG, "Nested xen_version: %d.\n", cmd);
+
+    switch ( cmd )
+    {
+    case XENVER_version:
+        return xen_hypercall_xen_version(XENVER_version, 0);
+
+    case XENVER_get_features:
+    {
+        xen_feature_info_t fi;
+
+        if ( copy_from_guest(&fi, arg, 1) )
+            return -EFAULT;
+
+        ret = xen_hypercall_xen_version(XENVER_get_features, &fi);
+        if ( ret )
+            return ret;
+
+        if ( __copy_to_guest(arg, &fi, 1) )
+            return -EFAULT;
+
+        return 0;
+    }
+
+    default:
+        gprintk(XENLOG_ERR, "Nested xen_version op %d not implemented.\n", 
cmd);
+        return -EOPNOTSUPP;
+    }
+}
diff --git a/xen/arch/x86/guest/xen.c b/xen/arch/x86/guest/xen.c
index b0b603a11a..78a5f40b22 100644
--- a/xen/arch/x86/guest/xen.c
+++ b/xen/arch/x86/guest/xen.c
@@ -74,7 +74,10 @@ void __init probe_hypervisor(void)
 
     xen_detected = true;
 
-    xen_guest_enable();
+    if ( pv_shim || pvh_boot )
+        xen_guest_enable();
+    else
+        xen_nested_enable();
 }
 
 void __init hypervisor_print_info(void)
diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c
index d483dbaa6b..b22f0ca65a 100644
--- a/xen/arch/x86/hypercall.c
+++ b/xen/arch/x86/hypercall.c
@@ -72,6 +72,9 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] =
 #ifdef CONFIG_HVM
     ARGS(hvm_op, 2),
     ARGS(dm_op, 3),
+#endif
+#ifdef CONFIG_XEN_NESTED
+    ARGS(nested_xen_version, 2),
 #endif
     ARGS(mca, 1),
     ARGS(arch_1, 1),
diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c
index 0c84c0b3a0..1e00d07273 100644
--- a/xen/arch/x86/pv/hypercall.c
+++ b/xen/arch/x86/pv/hypercall.c
@@ -83,6 +83,9 @@ const hypercall_table_t pv_hypercall_table[] = {
 #ifdef CONFIG_HVM
     HYPERCALL(hvm_op),
     COMPAT_CALL(dm_op),
+#endif
+#ifdef CONFIG_XEN_NESTED
+    HYPERCALL(nested_xen_version),
 #endif
     HYPERCALL(mca),
     HYPERCALL(arch_1),
diff --git a/xen/include/asm-x86/guest/hypercall.h 
b/xen/include/asm-x86/guest/hypercall.h
index d548816b30..86e11dd1d1 100644
--- a/xen/include/asm-x86/guest/hypercall.h
+++ b/xen/include/asm-x86/guest/hypercall.h
@@ -19,7 +19,7 @@
 #ifndef __X86_XEN_HYPERCALL_H__
 #define __X86_XEN_HYPERCALL_H__
 
-#ifdef CONFIG_XEN_GUEST
+#if defined(CONFIG_XEN_GUEST) || defined (CONFIG_XEN_NESTED)
 
 #include <xen/types.h>
 
@@ -123,6 +123,11 @@ static inline long xen_hypercall_hvm_op(unsigned int op, 
void *arg)
     return _hypercall64_2(long, __HYPERVISOR_hvm_op, op, arg);
 }
 
+static inline long xen_hypercall_xen_version(unsigned int op, void *arg)
+{
+    return _hypercall64_2(long, __HYPERVISOR_xen_version, op, arg);
+}
+
 /*
  * Higher level hypercall helpers
  */
diff --git a/xen/include/asm-x86/guest/xen.h b/xen/include/asm-x86/guest/xen.h
index 27c854ab8a..802aee5edb 100644
--- a/xen/include/asm-x86/guest/xen.h
+++ b/xen/include/asm-x86/guest/xen.h
@@ -43,6 +43,16 @@ static inline void hypervisor_print_info(void) {
 
 #endif /* CONFIG_XEN_DETECT */
 
+#ifdef CONFIG_XEN_NESTED
+
+void xen_nested_enable(void);
+
+#else
+
+static inline void xen_nested_enable(void) {}
+
+#endif /* CONFIG_XEN_NESTED */
+
 #ifdef CONFIG_XEN_GUEST
 #define XEN_shared_info ((struct shared_info 
*)fix_to_virt(FIX_XEN_SHARED_INFO))
 
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index cb2917e74b..2f5ac5eedc 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -121,6 +121,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
 #define __HYPERVISOR_argo_op              39
 #define __HYPERVISOR_xenpmu_op            40
 #define __HYPERVISOR_dm_op                41
+#define __HYPERVISOR_nested_xen_version   42
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h
index fc00a67448..15194002d6 100644
--- a/xen/include/xen/hypercall.h
+++ b/xen/include/xen/hypercall.h
@@ -150,6 +150,12 @@ do_dm_op(
     unsigned int nr_bufs,
     XEN_GUEST_HANDLE_PARAM(xen_dm_op_buf_t) bufs);
 
+#ifdef CONFIG_XEN_NESTED
+extern long do_nested_xen_version(
+    int cmd,
+    XEN_GUEST_HANDLE_PARAM(void) arg);
+#endif
+
 #ifdef CONFIG_COMPAT
 
 extern int
-- 
2.17.1


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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.