]> xenbits.xensource.com Git - people/hx242/xen.git/commitdiff
sysctl / libxl: report whether IOMMU/HAP page table sharing is supported
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 17 Sep 2019 14:12:47 +0000 (16:12 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 17 Sep 2019 14:12:47 +0000 (16:12 +0200)
This patch defines a new bit reported in the hw_cap field of struct
xen_sysctl_physinfo to indicate whether the platform supports sharing of
HAP page tables (i.e. the P2M) with the IOMMU. This informs the toolstack
whether the domain needs extra memory to store discrete IOMMU page tables
or not.

NOTE: This patch makes sure iommu_hap_pt_shared is clear if HAP is not
      supported or the IOMMU is disabled, and defines it to false if
      !CONFIG_HVM.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
Acked-by: Wei Liu <wl@xen.org>
Acked-by: Julien Grall <julien.grall@arm.com>
13 files changed:
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/libxl_types.idl
tools/ocaml/libs/xc/xenctrl.ml
tools/ocaml/libs/xc/xenctrl.mli
tools/xl/xl_info.c
xen/arch/x86/hvm/hvm.c
xen/common/sysctl.c
xen/drivers/passthrough/amd/iommu_init.c
xen/drivers/passthrough/iommu.c
xen/drivers/passthrough/vtd/iommu.c
xen/include/public/sysctl.h
xen/include/xen/iommu.h

index 57073c06d5da4b1ba75a65233ed87a85e20eb2d3..a0d84281d05e6f0b478f2df6c7b6fafab872bd39 100644 (file)
@@ -402,6 +402,8 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
     physinfo->cap_hap = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hap);
     physinfo->cap_shadow =
         !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_shadow);
+    physinfo->cap_iommu_hap_pt_share =
+        !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share);
 
     GC_FREE;
     return 0;
index 466df2cdf55bd9c6f2c988268e6b5b20c2a6b44d..8169d44bdaa67b3cbe54db1e724794918ab3e6c5 100644 (file)
  */
 #define LIBXL_HAVE_PHYSINFO_CAP_HAP_SHADOW 1
 
+/*
+ * LIBXL_HAVE_PHYSINFO_CAP_IOMMU_HAP_PT_SHARE indicates that libxl_physinfo
+ * has a cap_iommu_hap_pt_share field that indicates whether the hardware
+ * supports sharing the IOMMU and HAP page tables.
+ */
+#define LIBXL_HAVE_PHYSINFO_CAP_IOMMU_HAP_PT_SHARE 1
+
 /*
  * libxl ABI compatibility
  *
index 6f431baec24bdfe6ccd30053430e1d5b43210b05..7253d6e0fb83a846aac1d30723651da49ee0dbc4 100644 (file)
@@ -1027,6 +1027,7 @@ libxl_physinfo = Struct("physinfo", [
     ("cap_hvm_directio", bool), # No longer HVM specific
     ("cap_hap", bool),
     ("cap_shadow", bool),
+    ("cap_iommu_hap_pt_share", bool),
     ], dir=DIR_OUT)
 
 libxl_connectorinfo = Struct("connectorinfo", [
index 35dddbbd9c56b51cee479a900f3bc46d74ee1756..de4bae60123c0220bba17f037547cdb4c61311d3 100644 (file)
@@ -110,6 +110,7 @@ type physinfo_cap_flag =
        | CAP_DirectIO
        | CAP_HAP
        | CAP_Shadow
+       | CAP_IOMMU_HAP_PT_SHARE
 
 type physinfo =
 {
index 0dd55e9d8b35a5b00417118f2e4df9f0e789eb84..c885e758951bdd0cc4e5fcf339cf2d68fca6e876 100644 (file)
@@ -57,7 +57,6 @@ type domain_create_flag =
   | CDF_OOS_OFF
   | CDF_XS_DOMAIN
   | CDF_IOMMU
-
 type domctl_create_config = {
   ssidref: int32;
   handle: string;
@@ -95,6 +94,8 @@ type physinfo_cap_flag =
   | CAP_DirectIO
   | CAP_HAP
   | CAP_Shadow
+  | CAP_IOMMU_HAP_PT_SHARE
+
 type physinfo = {
   threads_per_core : int;
   cores_per_socket : int;
index 148c4740ae61fb73fe42a0940e6d7a9633fe8cf7..bfbca93997dd4fec21be7dd59a6fb8a448f160c0 100644 (file)
@@ -210,13 +210,14 @@ static void output_physinfo(void)
          info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
         );
 
-    maybe_printf("virt_caps              :%s%s%s%s%s%s\n",
+    maybe_printf("virt_caps              :%s%s%s%s%s%s%s\n",
          info.cap_pv ? " pv" : "",
          info.cap_hvm ? " hvm" : "",
          info.cap_hvm && info.cap_hvm_directio ? " hvm_directio" : "",
          info.cap_pv && info.cap_hvm_directio ? " pv_directio" : "",
          info.cap_hap ? " hap" : "",
-         info.cap_shadow ? " shadow" : ""
+         info.cap_shadow ? " shadow" : "",
+         info.cap_iommu_hap_pt_share ? " iommu_hap_pt_share" : ""
         );
 
     vinfo = libxl_get_version_info(ctx);
index 3831c6d4c1a5eda9e23e5ec897e875ecda44cb4e..977934a56cad73dd81869b2fb3779c2a46165ee3 100644 (file)
@@ -142,6 +142,23 @@ static struct notifier_block cpu_nfb = {
     .notifier_call = cpu_callback
 };
 
+static bool __init hap_supported(const struct hvm_function_table *fns)
+{
+    if ( !fns->hap_supported )
+    {
+        printk("HVM: Hardware Assisted Paging (HAP) not detected\n");
+        return false;
+    }
+
+    if ( !opt_hap_enabled )
+    {
+        printk("HVM: Hardware Assisted Paging (HAP) detected but disabled\n");
+        return false;
+    }
+
+    return true;
+}
+
 static int __init hvm_enable(void)
 {
     const struct hvm_function_table *fns = NULL;
@@ -158,13 +175,8 @@ static int __init hvm_enable(void)
     hvm_enabled = 1;
 
     printk("HVM: %s enabled\n", fns->name);
-    if ( !fns->hap_supported )
-        printk("HVM: Hardware Assisted Paging (HAP) not detected\n");
-    else if ( !opt_hap_enabled )
-    {
-        hvm_funcs.hap_supported = 0;
-        printk("HVM: Hardware Assisted Paging (HAP) detected but disabled\n");
-    }
+    if ( !hap_supported(fns) )
+        clear_iommu_hap_pt_share();
     else
     {
         printk("HVM: Hardware Assisted Paging (HAP) detected\n");
index c8f86424d54befe8e2447f7ff1892847261316cd..e8763c7fdf34acf4ad30c9e819012de13638978c 100644 (file)
@@ -269,6 +269,8 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
         arch_do_physinfo(pi);
         if ( iommu_enabled )
             pi->capabilities |= XEN_SYSCTL_PHYSCAP_directio;
+        if ( iommu_hap_pt_share )
+            pi->capabilities |= XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share;
 
         if ( copy_to_guest(u_sysctl, op, 1) )
             ret = -EFAULT;
index d6a5cf2e4ab8354a84c3ac0e1b43af65f98a462c..100d0bba3baf106b8dbf2e7008f6c3dccb4de1e4 100644 (file)
@@ -1412,7 +1412,8 @@ int __init amd_iommu_init(bool xt)
      * since it only supports p2m_ram_rw, and this would
      * prevent doing IO to/from mapped grant frames.
      */
-    iommu_hap_pt_share = 0;
+    clear_iommu_hap_pt_share();
+
     printk(XENLOG_DEBUG "AMD-Vi: Disabled HAP memory map sharing with IOMMU\n");
 
     /* per iommu initialization  */
index 09ce9d929445291ae2aa73858241f1e1bc23e596..11ece4d1f3dd7f2aa0b88dda7ad34301d50a5cf4 100644 (file)
@@ -49,7 +49,11 @@ int8_t __hwdom_initdata iommu_hwdom_reserved = -1;
  * default until we find a good solution to resolve it.
  */
 bool_t __read_mostly iommu_intpost;
-bool_t __read_mostly iommu_hap_pt_share = 1;
+
+#ifndef iommu_hap_pt_share
+bool __read_mostly iommu_hap_pt_share = true;
+#endif
+
 bool_t __read_mostly iommu_debug;
 bool_t __read_mostly amd_iommu_perdev_intremap = 1;
 
@@ -102,8 +106,10 @@ static int __init parse_iommu_param(const char *s)
             iommu_hwdom_passthrough = val;
         else if ( (val = parse_boolean("dom0-strict", s, ss)) >= 0 )
             iommu_hwdom_strict = val;
+#ifndef iommu_hap_pt_share
         else if ( (val = parse_boolean("sharept", s, ss)) >= 0 )
             iommu_hap_pt_share = val;
+#endif
         else
             rc = -EINVAL;
 
@@ -511,7 +517,10 @@ int __init iommu_setup(void)
         iommu_enabled = (rc == 0);
     }
     if ( !iommu_enabled )
+    {
         iommu_intremap = 0;
+        clear_iommu_hap_pt_share();
+    }
 
     if ( (force_iommu && !iommu_enabled) ||
          (force_intremap && !iommu_intremap) )
index 7ffafdc065fa1b4745760eafcffda96b5f06e396..f123760ee28ea541ef01610aa2d6730d9a27cb6d 100644 (file)
@@ -2310,7 +2310,7 @@ static int __init vtd_setup(void)
             iommu_intpost = 0;
 
         if ( !vtd_ept_page_compatible(iommu) )
-            iommu_hap_pt_share = 0;
+            clear_iommu_hap_pt_share();
 
         ret = iommu_set_interrupt(drhd);
         if ( ret )
index e324442f925195ba9fb86df7c397f600f47470f8..19457a4e306edf133c0191487f0526056ffd2caf 100644 (file)
@@ -96,9 +96,13 @@ struct xen_sysctl_tbuf_op {
 /* The platform supports software paging. */
 #define _XEN_SYSCTL_PHYSCAP_shadow       4
 #define XEN_SYSCTL_PHYSCAP_shadow        (1u<<_XEN_SYSCTL_PHYSCAP_shadow)
+/* The platform supports sharing of HAP page tables with the IOMMU. */
+#define _XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share 5
+#define XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share  \
+    (1u << _XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share)
 
 /* Max XEN_SYSCTL_PHYSCAP_* constant.  Used for ABI checking. */
-#define XEN_SYSCTL_PHYSCAP_MAX XEN_SYSCTL_PHYSCAP_shadow
+#define XEN_SYSCTL_PHYSCAP_MAX XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share
 
 struct xen_sysctl_physinfo {
     uint32_t threads_per_core;
index ab258b848b4b8751f099c620df3ad43d1ea32598..c5ed7efe983b8244280371febb6a2c340ae1b28f 100644 (file)
@@ -55,7 +55,22 @@ static inline bool_t dfn_eq(dfn_t x, dfn_t y)
 extern bool_t iommu_enable, iommu_enabled;
 extern bool_t force_iommu, iommu_verbose, iommu_igfx;
 extern bool_t iommu_snoop, iommu_qinval, iommu_intremap, iommu_intpost;
-extern bool_t iommu_hap_pt_share;
+
+#ifdef CONFIG_HVM
+extern bool iommu_hap_pt_share;
+#else
+#define iommu_hap_pt_share false
+#endif
+
+static inline void clear_iommu_hap_pt_share(void)
+{
+#ifndef iommu_hap_pt_share
+    iommu_hap_pt_share = false;
+#elif iommu_hap_pt_share
+    ASSERT_UNREACHABLE();
+#endif
+}
+
 extern bool_t iommu_debug;
 extern bool_t amd_iommu_perdev_intremap;