diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 57073c06d5..a0d84281d0 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -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;
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 466df2cdf5..8169d44bda 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -401,6 +401,13 @@
  */
 #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
  *
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 6f431baec2..7253d6e0fb 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -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", [
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index 35dddbbd9c..de4bae6012 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -110,6 +110,7 @@ type physinfo_cap_flag =
 	| CAP_DirectIO
 	| CAP_HAP
 	| CAP_Shadow
+	| CAP_IOMMU_HAP_PT_SHARE
 
 type physinfo =
 {
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index 0dd55e9d8b..c885e75895 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -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;
diff --git a/tools/xl/xl_info.c b/tools/xl/xl_info.c
index 148c4740ae..bfbca93997 100644
--- a/tools/xl/xl_info.c
+++ b/tools/xl/xl_info.c
@@ -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);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 3831c6d4c1..ed8272cf93 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -142,6 +142,22 @@ 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;
+    }
+    else 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 +174,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) )
+        iommu_hap_pt_share = false;
     else
     {
         printk("HVM: Hardware Assisted Paging (HAP) detected\n");
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 92b4ea0d21..ef840fcb76 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -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;
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index bb5a3e57c9..2e011d4e43 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -1401,12 +1401,15 @@ int __init amd_iommu_init(bool xt)
     if ( rc )
         goto error_out;
 
+#ifndef iommu_hap_pt_share
     /*
      * Disable sharing HAP page tables with AMD IOMMU,
      * since it only supports p2m_ram_rw, and this would
      * prevent doing IO to/from mapped grant frames.
      */
-    iommu_hap_pt_share = 0;
+    iommu_hap_pt_share = false;
+#endif
+
     printk(XENLOG_DEBUG "AMD-Vi: Disabled HAP memory map sharing with IOMMU\n");
 
     /* per iommu initialization  */
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 09ce9d9294..bdf12f85e6 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -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;
 
@@ -103,7 +107,14 @@ static int __init parse_iommu_param(const char *s)
         else if ( (val = parse_boolean("dom0-strict", s, ss)) >= 0 )
             iommu_hwdom_strict = val;
         else if ( (val = parse_boolean("sharept", s, ss)) >= 0 )
+        {
+#ifndef iommu_hap_pt_share
             iommu_hap_pt_share = val;
+#else
+            if (val != iommu_hap_pt_share)
+                rc = -EINVAL;
+#endif
+        }
         else
             rc = -EINVAL;
 
@@ -511,7 +522,12 @@ int __init iommu_setup(void)
         iommu_enabled = (rc == 0);
     }
     if ( !iommu_enabled )
+    {
         iommu_intremap = 0;
+#ifndef iommu_hap_pt_share
+        iommu_hap_pt_share = false;
+#endif
+    }
 
     if ( (force_iommu && !iommu_enabled) ||
          (force_intremap && !iommu_intremap) )
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 7ffafdc065..a7381a7449 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1898,6 +1898,7 @@ int iommu_pte_flush(struct domain *d, uint64_t dfn, uint64_t *pte,
     return rc;
 }
 
+#ifndef iommu_hap_pt_share
 static int __init vtd_ept_page_compatible(struct vtd_iommu *iommu)
 {
     u64 ept_cap, vtd_cap = iommu->cap;
@@ -1910,6 +1911,7 @@ static int __init vtd_ept_page_compatible(struct vtd_iommu *iommu)
     return (ept_has_2mb(ept_cap) && opt_hap_2mb) == cap_sps_2mb(vtd_cap) &&
            (ept_has_1gb(ept_cap) && opt_hap_1gb) == cap_sps_1gb(vtd_cap);
 }
+#endif
 
 /*
  * set VT-d page table directory to EPT table if allowed
@@ -2309,8 +2311,10 @@ static int __init vtd_setup(void)
         if ( !cap_intr_post(iommu->cap) || !iommu_intremap || !cpu_has_cx16 )
             iommu_intpost = 0;
 
+#ifndef iommu_hap_pt_share
         if ( !vtd_ept_page_compatible(iommu) )
-            iommu_hap_pt_share = 0;
+            iommu_hap_pt_share = false;
+#endif
 
         ret = iommu_set_interrupt(drhd);
         if ( ret )
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index e324442f92..2be013de5b 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -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_hap_pt_share
 
 struct xen_sysctl_physinfo {
     uint32_t threads_per_core;
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index ab258b848b..a519f4d87b 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -55,7 +55,13 @@ 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
+
 extern bool_t iommu_debug;
 extern bool_t amd_iommu_perdev_intremap;
 
