diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
index 9ed7ccb57b..1f564ff83b 100644
--- a/tools/flask/policy/modules/dom0.te
+++ b/tools/flask/policy/modules/dom0.te
@@ -45,6 +45,7 @@ allow dom0_t dom0_t:resource { add remove };
 
 # Allow dom0 to communicate with a nested Xen hypervisor
 allow dom0_t nestedxen_t:version { xen_version xen_get_features };
+allow dom0_t nestedxen_t:mmu physmap;
 
 # These permissions allow using the FLASK security server to compute access
 # checks locally, which could be used by a domain or service (such as xenstore)
diff --git a/xen/arch/x86/guest/hypercall_page.S b/xen/arch/x86/guest/hypercall_page.S
index 2b1e35803a..1a8dd0ea4f 100644
--- a/xen/arch/x86/guest/hypercall_page.S
+++ b/xen/arch/x86/guest/hypercall_page.S
@@ -61,6 +61,7 @@ DECLARE_HYPERCALL(kexec_op)
 DECLARE_HYPERCALL(argo_op)
 DECLARE_HYPERCALL(xenpmu_op)
 DECLARE_HYPERCALL(nested_xen_version)
+DECLARE_HYPERCALL(nested_memory_op)
 
 DECLARE_HYPERCALL(arch_0)
 DECLARE_HYPERCALL(arch_1)
diff --git a/xen/arch/x86/guest/xen-nested.c b/xen/arch/x86/guest/xen-nested.c
index fcfa5e1087..a76983cc2d 100644
--- a/xen/arch/x86/guest/xen-nested.c
+++ b/xen/arch/x86/guest/xen-nested.c
@@ -22,11 +22,17 @@
 #include <xen/lib.h>
 #include <xen/sched.h>
 
+#include <public/memory.h>
 #include <public/version.h>
+#include <public/xen.h>
 
 #include <asm/guest/hypercall.h>
 #include <asm/guest/xen.h>
 
+#ifdef CONFIG_COMPAT
+#include <compat/memory.h>
+#endif
+
 extern char hypercall_page[];
 
 /* xen_nested: support for nested PV interface enabled */
@@ -80,3 +86,77 @@ long do_nested_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         return -EOPNOTSUPP;
     }
 }
+
+static long nested_add_to_physmap(struct xen_add_to_physmap xatp)
+{
+    struct domain *d;
+    long ret;
+
+    if ( !xen_nested )
+        return -ENOSYS;
+
+    if ( (xatp.space != XENMAPSPACE_shared_info) &&
+         (xatp.space != XENMAPSPACE_grant_table) )
+    {
+        gprintk(XENLOG_ERR, "Nested memory op: unknown xatp.space: %u\n",
+                xatp.space);
+        return -EINVAL;
+    }
+
+    if ( xatp.domid != DOMID_SELF )
+        return -EPERM;
+
+    ret = xsm_nested_add_to_physmap(XSM_PRIV, current->domain);
+    if ( ret )
+        return ret;
+
+    gprintk(XENLOG_DEBUG, "Nested XENMEM_add_to_physmap: %d\n", xatp.space);
+
+    d = rcu_lock_current_domain();
+
+    ret = xen_hypercall_memory_op(XENMEM_add_to_physmap, &xatp);
+
+    rcu_unlock_domain(d);
+
+    if ( ret )
+        gprintk(XENLOG_ERR, "Nested memory op failed add_to_physmap"
+                            " for %d with %ld\n", xatp.space, ret);
+    return ret;
+}
+
+long do_nested_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    struct xen_add_to_physmap xatp;
+
+    if ( cmd != XENMEM_add_to_physmap )
+    {
+        gprintk(XENLOG_ERR, "Nested memory op %u not implemented.\n", cmd);
+        return -EOPNOTSUPP;
+    }
+
+    if ( copy_from_guest(&xatp, arg, 1) )
+        return -EFAULT;
+
+    return nested_add_to_physmap(xatp);
+}
+
+#ifdef CONFIG_COMPAT
+int compat_nested_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    struct compat_add_to_physmap cmp;
+    struct xen_add_to_physmap *nat = COMPAT_ARG_XLAT_VIRT_BASE;
+
+    if ( cmd != XENMEM_add_to_physmap )
+    {
+        gprintk(XENLOG_ERR, "Nested memory op %u not implemented.\n", cmd);
+        return -EOPNOTSUPP;
+    }
+
+    if ( copy_from_guest(&cmp, arg, 1) )
+        return -EFAULT;
+
+    XLAT_add_to_physmap(nat, &cmp);
+
+    return nested_add_to_physmap(*nat);
+}
+#endif
diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c
index b22f0ca65a..2aa8dc5ac6 100644
--- a/xen/arch/x86/hypercall.c
+++ b/xen/arch/x86/hypercall.c
@@ -75,6 +75,7 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] =
 #endif
 #ifdef CONFIG_XEN_NESTED
     ARGS(nested_xen_version, 2),
+    COMP(nested_memory_op, 2, 2),
 #endif
     ARGS(mca, 1),
     ARGS(arch_1, 1),
diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c
index 1e00d07273..96198d3313 100644
--- a/xen/arch/x86/pv/hypercall.c
+++ b/xen/arch/x86/pv/hypercall.c
@@ -86,6 +86,7 @@ const hypercall_table_t pv_hypercall_table[] = {
 #endif
 #ifdef CONFIG_XEN_NESTED
     HYPERCALL(nested_xen_version),
+    COMPAT_CALL(nested_memory_op),
 #endif
     HYPERCALL(mca),
     HYPERCALL(arch_1),
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index 2f5ac5eedc..e081f52fc4 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -122,6 +122,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
 #define __HYPERVISOR_xenpmu_op            40
 #define __HYPERVISOR_dm_op                41
 #define __HYPERVISOR_nested_xen_version   42
+#define __HYPERVISOR_nested_memory_op     43
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h
index 15194002d6..d373bd1763 100644
--- a/xen/include/xen/hypercall.h
+++ b/xen/include/xen/hypercall.h
@@ -154,6 +154,10 @@ do_dm_op(
 extern long do_nested_xen_version(
     int cmd,
     XEN_GUEST_HANDLE_PARAM(void) arg);
+
+extern long do_nested_memory_op(
+    int cmd,
+    XEN_GUEST_HANDLE_PARAM(void) arg);
 #endif
 
 #ifdef CONFIG_COMPAT
@@ -222,6 +226,12 @@ compat_dm_op(
     unsigned int nr_bufs,
     XEN_GUEST_HANDLE_PARAM(void) bufs);
 
+#ifdef CONFIG_XEN_NESTED
+extern int compat_nested_memory_op(
+    int cmd,
+    XEN_GUEST_HANDLE_PARAM(void) arg);
+#endif
+
 #endif
 
 void arch_get_xen_caps(xen_capabilities_info_t *info);
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 8011bf2cb4..17375f6b9f 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -747,6 +747,13 @@ static XSM_INLINE int xsm_nested_xen_version(XSM_DEFAULT_ARG
     XSM_ASSERT_ACTION(XSM_PRIV);
     return xsm_default_action(action, d, NULL);
 }
+
+static XSM_INLINE int xsm_nested_add_to_physmap(XSM_DEFAULT_ARG
+                                                const struct domain *d)
+{
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, d, NULL);
+}
 #endif
 
 #include <public/version.h>
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 96044cb55a..920d2d9088 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -189,6 +189,7 @@ struct xsm_operations {
 #endif
 #ifdef CONFIG_XEN_NESTED
     int (*nested_xen_version) (const struct domain *d, unsigned int cmd);
+    int (*nested_add_to_physmap) (const struct domain *d);
 #endif
 };
 
@@ -734,6 +735,12 @@ static inline int xsm_nested_xen_version(xsm_default_t def,
     return xsm_ops->nested_xen_version(d, cmd);
 }
 
+static inline int xsm_nested_add_to_physmap(xsm_default_t def,
+                                            const struct domain *d)
+{
+    return xsm_ops->nested_add_to_physmap(d);
+}
+
 #endif /* CONFIG_XEN_NESTED */
 
 #endif /* XSM_NO_WRAPPERS */
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index ed0a4b0691..5ce29bcfe5 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -159,5 +159,6 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
 #endif
 #ifdef CONFIG_XEN_NESTED
     set_to_dummy_if_null(ops, nested_xen_version);
+    set_to_dummy_if_null(ops, nested_add_to_physmap);
 #endif
 }
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 2835279fe7..17a81b85f9 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1749,6 +1749,20 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
 #endif
 
 #ifdef CONFIG_XEN_NESTED
+static int domain_has_nested_perm(const struct domain *d, u16 class, u32 perm)
+{
+    struct avc_audit_data ad;
+
+    AVC_AUDIT_DATA_INIT(&ad, NONE);
+
+    return avc_has_perm(domain_sid(d), SECINITSID_NESTEDXEN, class, perm, &ad);
+}
+
+static int flask_nested_add_to_physmap(const struct domain *d)
+{
+    return domain_has_nested_perm(d, SECCLASS_MMU, MMU__PHYSMAP);
+}
+
 static int flask_nested_xen_version(const struct domain *d, unsigned int op)
 {
     return domain_has_xen_version(d, SECINITSID_NESTEDXEN, op);
@@ -1897,6 +1911,7 @@ static struct xsm_operations flask_ops = {
 #endif
 #ifdef CONFIG_XEN_NESTED
     .nested_xen_version = flask_nested_xen_version,
+    .nested_add_to_physmap = flask_nested_add_to_physmap,
 #endif
 };
 
