Patchwork [v4,02/28] VIOMMU: Add vIOMMU framework and vIOMMU domctl

login
register
mail settings
Submitter Chao Gao
Date Nov. 17, 2017, 6:22 a.m.
Message ID <1510899755-40237-3-git-send-email-chao.gao@intel.com>
Download mbox | patch
Permalink /patch/385489/
State New
Headers show

Comments

Chao Gao - Nov. 17, 2017, 6:22 a.m.
From: Lan Tianyu <tianyu.lan@intel.com>

This patch is to introduce an abstract layer for arch vIOMMU implementation
and vIOMMU domctl to deal with requests from tool stack. Arch vIOMMU code needs to
provide callback. vIOMMU domctl supports to create vIOMMU instance in hypervisor
and it will be destroyed during destroying domain.

Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Chao Gao <chao.gao@intel.com>
---
v4:
 - introduce REGISTER_VIOMMU() to register viommu types and ops.
 - remove unneeded domctl interface to destroy viommu.
---
 docs/misc/xen-command-line.markdown |   7 ++
 xen/arch/x86/Kconfig                |   1 +
 xen/arch/x86/hvm/hvm.c              |   3 +
 xen/arch/x86/xen.lds.S              |   3 +
 xen/common/Kconfig                  |   3 +
 xen/common/Makefile                 |   1 +
 xen/common/domctl.c                 |   7 ++
 xen/common/viommu.c                 | 125 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/hvm/domain.h    |   3 +
 xen/include/public/domctl.h         |  31 +++++++++
 xen/include/xen/viommu.h            |  69 ++++++++++++++++++++
 11 files changed, 253 insertions(+)
 create mode 100644 xen/common/viommu.c
 create mode 100644 xen/include/xen/viommu.h

Patch

diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
index eb4995e..d097382 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1836,3 +1836,10 @@  mode.
 > Default: `true`
 
 Permit use of the `xsave/xrstor` instructions.
+
+### viommu
+> `= <boolean>`
+
+> Default: `false`
+
+Permit use of viommu interface to create and destroy viommu device model.
diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 64955dc..df254e4 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -25,6 +25,7 @@  config X86
 	select HAS_UBSAN
 	select NUMA
 	select VGA
+	select VIOMMU
 
 config ARCH_DEFCONFIG
 	string
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 205b4cb..964418a 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -36,6 +36,7 @@ 
 #include <xen/rangeset.h>
 #include <xen/monitor.h>
 #include <xen/warning.h>
+#include <xen/viommu.h>
 #include <asm/shadow.h>
 #include <asm/hap.h>
 #include <asm/current.h>
@@ -693,6 +694,8 @@  void hvm_domain_relinquish_resources(struct domain *d)
         pmtimer_deinit(d);
         hpet_deinit(d);
     }
+
+    viommu_destroy_domain(d);
 }
 
 void hvm_domain_destroy(struct domain *d)
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index d5e8821..7f8d2b8 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -231,6 +231,9 @@  SECTIONS
        __start_schedulers_array = .;
        *(.data.schedulers)
        __end_schedulers_array = .;
+       __start_viommus_array = .;
+       *(.data.viommus)
+       __end_viommus_array = .;
   } :text
 
   .data : {                    /* Data */
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 103ef44..62aaa76 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -52,6 +52,9 @@  config HAS_CHECKPOLICY
 	string
 	option env="XEN_HAS_CHECKPOLICY"
 
+config VIOMMU
+	bool
+
 config KEXEC
 	bool "kexec support"
 	default y
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 66cc2c8..182b3ac 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -56,6 +56,7 @@  obj-y += time.o
 obj-y += timer.o
 obj-y += trace.o
 obj-y += version.o
+obj-$(CONFIG_VIOMMU) += viommu.o
 obj-y += virtual_region.o
 obj-y += vm_event.o
 obj-y += vmap.o
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 3c6fa4e..9c5651d 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -25,6 +25,7 @@ 
 #include <xen/paging.h>
 #include <xen/hypercall.h>
 #include <xen/vm_event.h>
+#include <xen/viommu.h>
 #include <xen/monitor.h>
 #include <asm/current.h>
 #include <asm/irq.h>
@@ -1155,6 +1156,12 @@  long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
                                      op->u.set_gnttab_limits.maptrack_frames);
         break;
 
+    case XEN_DOMCTL_viommu_op:
+        ret = viommu_domctl(d, &op->u.viommu_op);
+        if ( !ret )
+            copyback = 1;
+        break;
+
     default:
         ret = arch_do_domctl(op, d, u_domctl);
         break;
diff --git a/xen/common/viommu.c b/xen/common/viommu.c
new file mode 100644
index 0000000..fd8b7fd
--- /dev/null
+++ b/xen/common/viommu.c
@@ -0,0 +1,125 @@ 
+/*
+ * common/viommu.c
+ *
+ * Copyright (c) 2017 Intel Corporation
+ * Author: Lan Tianyu <tianyu.lan@intel.com>
+ *
+ * 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 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/>.
+ */
+
+#include <xen/sched.h>
+#include <xen/spinlock.h>
+#include <xen/types.h>
+#include <xen/viommu.h>
+
+extern const struct viommu_ops *__start_viommus_array[], *__end_viommus_array[];
+#define NUM_VIOMMU_TYPE (__end_viommus_array - __start_viommus_array)
+#define viommu_type_array __start_viommus_array
+
+int viommu_destroy_domain(struct domain *d)
+{
+    struct viommu *viommu = d->arch.hvm_domain.viommu;
+    int ret;
+
+    if ( !viommu )
+        return -ENODEV;
+
+    ret = viommu->ops->destroy(viommu);
+    if ( ret < 0 )
+        return ret;
+
+    xfree(viommu);
+    d->arch.hvm_domain.viommu = NULL;
+
+    return 0;
+}
+
+static const struct viommu_ops *viommu_get_ops(uint8_t type)
+{
+    int i;
+
+    for ( i = 0; i < NUM_VIOMMU_TYPE; i++)
+    {
+        if ( viommu_type_array[i]->type == type )
+            return viommu_type_array[i];
+    }
+
+    return NULL;
+}
+
+static int viommu_create(struct domain *d, uint8_t type,
+                         uint64_t base_address, uint64_t caps,
+                         uint32_t *viommu_id)
+{
+    struct viommu *viommu;
+    const struct viommu_ops *viommu_ops = NULL;
+    int rc;
+
+    /* Only support one vIOMMU per domain. */
+    if ( d->arch.hvm_domain.viommu )
+        return -E2BIG;
+
+    viommu_ops = viommu_get_ops(type);
+    if ( !viommu_ops )
+        return -EINVAL;
+
+    ASSERT(viommu_ops->create);
+
+    viommu = xzalloc(struct viommu);
+    if ( !viommu )
+        return -ENOMEM;
+
+    viommu->base_address = base_address;
+    viommu->caps = caps;
+    viommu->ops = viommu_ops;
+
+    rc = viommu_ops->create(d, viommu);
+    if ( rc < 0 )
+    {
+        xfree(viommu);
+        return rc;
+    }
+
+    d->arch.hvm_domain.viommu = viommu;
+
+    /* Only support one vIOMMU per domain. */
+    *viommu_id = 0;
+    return 0;
+}
+
+int viommu_domctl(struct domain *d, struct xen_domctl_viommu_op *op)
+{
+    int rc;
+
+    switch ( op->cmd )
+    {
+    case XEN_DOMCTL_viommu_create:
+        rc = viommu_create(d, op->u.create.type, op->u.create.base_address,
+                           op->u.create.capabilities, &op->u.create.id);
+        break;
+    default:
+        return -ENOSYS;
+    }
+
+    return rc;
+}
+
+/*
+ * 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/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index 7f128c0..fcd3482 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -21,6 +21,7 @@ 
 #define __ASM_X86_HVM_DOMAIN_H__
 
 #include <xen/iommu.h>
+#include <xen/viommu.h>
 #include <asm/hvm/irq.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/vlapic.h>
@@ -196,6 +197,8 @@  struct hvm_domain {
         struct vmx_domain vmx;
         struct svm_domain svm;
     };
+
+    struct viommu *viommu;
 };
 
 #define hap_enabled(d)  ((d)->arch.hvm_domain.hap_enabled)
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 70027ab..9f6f0aa 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1105,6 +1105,35 @@  struct xen_domctl_vuart_op {
                                  */
 };
 
+/*  vIOMMU helper
+ *
+ * vIOMMU interface can be used to create vIOMMU.
+ */
+
+struct xen_domctl_viommu_op {
+    uint32_t cmd;
+#define XEN_DOMCTL_viommu_create        0
+    union {
+        struct {
+            /* IN - vIOMMU type */
+            uint8_t type;
+#define VIOMMU_TYPE_INTEL_VTD           0
+            /* 
+             * IN - MMIO base address of vIOMMU. vIOMMU device models
+             * are in charge of to check base_address.
+             */
+            uint64_t base_address;
+            /* IN - Capabilities with which we want to create */
+            uint64_t capabilities;
+#define VIOMMU_CAP_IRQ_REMAPPING        (1u << 0)
+            /* OUT - vIOMMU identity */
+            uint32_t id;
+        } create;
+    } u;
+};
+typedef struct xen_domctl_viommu_op xen_domctl_viommu_op;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_viommu_op);
+
 struct xen_domctl {
     uint32_t cmd;
 #define XEN_DOMCTL_createdomain                   1
@@ -1184,6 +1213,7 @@  struct xen_domctl {
 #define XEN_DOMCTL_soft_reset                    79
 #define XEN_DOMCTL_set_gnttab_limits             80
 #define XEN_DOMCTL_vuart_op                      81
+#define XEN_DOMCTL_viommu_op                     82
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1248,6 +1278,7 @@  struct xen_domctl {
         struct xen_domctl_psr_cat_op        psr_cat_op;
         struct xen_domctl_set_gnttab_limits set_gnttab_limits;
         struct xen_domctl_vuart_op          vuart_op;
+        struct xen_domctl_viommu_op         viommu_op;
         uint8_t                             pad[128];
     } u;
 };
diff --git a/xen/include/xen/viommu.h b/xen/include/xen/viommu.h
new file mode 100644
index 0000000..a859d80
--- /dev/null
+++ b/xen/include/xen/viommu.h
@@ -0,0 +1,69 @@ 
+/*
+ * include/xen/viommu.h
+ *
+ * Copyright (c) 2017, Intel Corporation
+ * Author: Lan Tianyu <tianyu.lan@intel.com>
+ *
+ * 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 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 __XEN_VIOMMU_H__
+#define __XEN_VIOMMU_H__
+
+#ifdef CONFIG_VIOMMU
+
+struct viommu;
+
+struct viommu_ops {
+    uint8_t type;
+    int (*create)(struct domain *d, struct viommu *viommu);
+    int (*destroy)(struct viommu *viommu);
+};
+
+struct viommu {
+    uint64_t base_address;
+    uint64_t caps;
+    const struct viommu_ops *ops;
+    void *priv;
+};
+
+#define REGISTER_VIOMMU(x) static const struct viommu_ops *x##_entry \
+  __used_section(".data.viommus") = &x;
+
+
+int viommu_register_type(uint8_t type, struct viommu_ops *ops);
+int viommu_destroy_domain(struct domain *d);
+int viommu_domctl(struct domain *d, struct xen_domctl_viommu_op *op);
+#else
+static inline int viommu_destroy_domain(struct domain *d)
+{
+    return -EINVAL;
+}
+static inline
+int viommu_domctl(struct domain *d, struct xen_domctl_viommu_op *op)
+{
+    return false;
+}
+#endif
+
+#endif /* __XEN_VIOMMU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */