diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index ec71574e99..5c0fcf320e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -399,6 +399,7 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
     physinfo->cap_pv = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_pv);
     physinfo->cap_hvm_directio =
         !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_directio);
+    physinfo->cap_hap = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hap);
 
     GC_FREE;
     return 0;
diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index d624159e53..3f59e790b7 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -65,8 +65,8 @@ _hidden
 int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq);
 
 _hidden
-void libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
-                                               libxl_domain_create_info *c_info);
+int libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
+                                              libxl_domain_create_info *c_info);
 
 _hidden
 void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 141e159043..b067869154 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -1114,8 +1114,8 @@ int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq)
     return xc_domain_bind_pt_spi_irq(CTX->xch, domid, irq, irq);
 }
 
-void libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
-                                               libxl_domain_create_info *c_info)
+int libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
+                                              libxl_domain_create_info *c_info)
 {
     /*
      * Arm guest are now considered as PVH by the toolstack. To allow
@@ -1130,6 +1130,9 @@ void libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
         c_info->type = LIBXL_DOMAIN_TYPE_PVH;
         /* All other fields can remain untouched */
     }
+    libxl_defbool_setdefault(&c_info->hap, true);
+
+    return 0;
 }
 
 void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 03ce166f4f..431ead2067 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -30,17 +30,19 @@
 int libxl__domain_create_info_setdefault(libxl__gc *gc,
                                          libxl_domain_create_info *c_info)
 {
+    int rc;
+
     if (!c_info->type) {
         LOG(ERROR, "domain type unspecified");
         return ERROR_INVAL;
     }
 
-    libxl__arch_domain_create_info_setdefault(gc, c_info);
+    rc = libxl__arch_domain_create_info_setdefault(gc, c_info);
+    if (rc)
+        return rc;
 
-    if (c_info->type != LIBXL_DOMAIN_TYPE_PV) {
-        libxl_defbool_setdefault(&c_info->hap, true);
+    if (c_info->type != LIBXL_DOMAIN_TYPE_PV)
         libxl_defbool_setdefault(&c_info->oos, true);
-    }
 
     libxl_defbool_setdefault(&c_info->run_hotplug_scripts, true);
     libxl_defbool_setdefault(&c_info->driver_domain, false);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index b61399ce36..9e1f8515d3 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -1025,6 +1025,7 @@ libxl_physinfo = Struct("physinfo", [
     ("cap_hvm", bool),
     ("cap_pv", bool),
     ("cap_hvm_directio", bool), # No longer HVM specific
+    ("cap_hap", bool),
     ], dir=DIR_OUT)
 
 libxl_connectorinfo = Struct("connectorinfo", [
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index c0f88a7eaa..bdc9d9adfe 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -620,9 +620,20 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
     return rc;
 }
 
-void libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
-                                               libxl_domain_create_info *c_info)
+int libxl__arch_domain_create_info_setdefault(libxl__gc *gc,
+                                              libxl_domain_create_info *c_info)
 {
+    libxl_physinfo pi;
+    int rc = libxl_get_physinfo(CTX, &pi);
+
+    if (rc) {
+        LOG(ERROR, "unable to get physinfo");
+        return rc;
+    }
+
+    libxl_defbool_setdefault(&c_info->hap, pi.cap_hap);
+
+    return 0;
 }
 
 void libxl__arch_domain_build_info_setdefault(libxl__gc *gc,
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index c50d910a1c..74ea184087 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -165,6 +165,8 @@ void arch_do_physinfo(struct xen_sysctl_physinfo *pi)
         pi->capabilities |= XEN_SYSCTL_PHYSCAP_pv;
     if ( iommu_enabled )
         pi->capabilities |= XEN_SYSCTL_PHYSCAP_directio;
+    if ( hvm_hap_supported() )
+        pi->capabilities |= XEN_SYSCTL_PHYSCAP_hap;
 }
 
 long arch_do_sysctl(
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 91c48dcae0..6c457625e9 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -90,6 +90,10 @@ struct xen_sysctl_tbuf_op {
  /* (x86) The platform supports direct access to I/O devices with IOMMU. */
 #define _XEN_SYSCTL_PHYSCAP_directio     2
 #define XEN_SYSCTL_PHYSCAP_directio  (1u<<_XEN_SYSCTL_PHYSCAP_directio)
+/* (x86) The platform supports Hardware Assisted Paging. */
+#define _XEN_SYSCTL_PHYSCAP_hap          3
+#define XEN_SYSCTL_PHYSCAP_hap           (1u<<_XEN_SYSCTL_PHYSCAP_hap)
+
 struct xen_sysctl_physinfo {
     uint32_t threads_per_core;
     uint32_t cores_per_socket;
