@@ -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;
@@ -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
*
@@ -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", [
@@ -110,6 +110,7 @@ type physinfo_cap_flag =
| CAP_DirectIO
| CAP_HAP
| CAP_Shadow
+ | CAP_IOMMU_HAP_PT_SHARE
type physinfo =
{
@@ -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;
@@ -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);
@@ -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");
@@ -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;
@@ -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 */
@@ -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) )
@@ -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 )
@@ -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;
@@ -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;