xen: reinstate previously unused XENMEM_remove_from_physmap hypercall
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>
Sat, 28 Jan 2012 13:47:24 +0000 (13:47 +0000)
committerDaniel De Graaf <dgdegra@tycho.nsa.gov>
Sat, 28 Jan 2012 13:47:24 +0000 (13:47 +0000)
This patch reinstates the XENMEM_remove_from_physmap hypercall
which was removed in 19041:ee62aaafff46 because it was not used.

However, is now needed in order to support xenstored stub domains.
The xenstored stub domain is not priviliged like dom0 and so cannot
unilaterally map the xenbus page of other guests into it's address
space.  Therefore, before creating a domU the domain builder needs to
seed its grant table with a grant ref allowing the xenstored stub
domain to access the new domU's xenbus page.

At present domU's do not start with their grant table mapped.
Instead it gets mapped when the guest requests a grant table from
the hypervisor.

In order to seed the grant table, the domain builder first needs to
map it into dom0 address space.  But the hypercall to do this
requires a gpfn (guest pfn), which is an mfn for PV guest, but a pfn
for HVM guests.  Therfore, in order to seed the grant table of an
HVM guest, dom0 needs to *temporarily* map it into the guest's
"physical" address space.

Hence the need to reinstate the XENMEM_remove_from_physmap hypercall.

Signed-off-by: Alex Zeffertt <alex.zeffertt@eu.citrix.com>
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Keir Fraser <keir@xen.org>
xen/common/compat/memory.c
xen/common/memory.c
xen/include/asm-ia64/mm.h
xen/include/public/memory.h
xen/include/xlat.lst
xen/include/xsm/xsm.h
xen/xsm/dummy.c
xen/xsm/flask/hooks.c

index 2402984f1efcb6608ed10b209e9595e7c02a59f4..e7257cc53e573752ce155507babd61104f11d975 100644 (file)
@@ -25,6 +25,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
             XEN_GUEST_HANDLE(void) hnd;
             struct xen_memory_reservation *rsrv;
             struct xen_memory_exchange *xchg;
+            struct xen_remove_from_physmap *xrfp;
         } nat;
         union {
             struct compat_memory_reservation rsrv;
@@ -179,6 +180,18 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
             nat.hnd = compat;
             break;
 
+        case XENMEM_remove_from_physmap:
+        {
+            struct compat_remove_from_physmap cmp;
+
+            if ( copy_from_guest(&cmp, compat, 1) )
+                return -EFAULT;
+
+            XLAT_remove_from_physmap(nat.xrfp, &cmp);
+
+            break;
+        }
+
         default:
             return compat_arch_memory_op(cmd, compat);
         }
@@ -284,6 +297,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
         case XENMEM_current_reservation:
         case XENMEM_maximum_reservation:
         case XENMEM_maximum_gpfn:
+        case XENMEM_remove_from_physmap:
             break;
 
         default:
index 8d45439745d1253b01d0f51f5fc3bca2802e97e2..53886cea3bdeb6256fb1040a16cada827b5528b0 100644 (file)
@@ -659,6 +659,43 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
 
         break;
 
+    case XENMEM_remove_from_physmap:
+    {
+        struct xen_remove_from_physmap xrfp;
+        unsigned long mfn;
+        struct domain *d;
+
+        if ( copy_from_guest(&xrfp, arg, 1) )
+            return -EFAULT;
+
+        rc = rcu_lock_target_domain_by_id(xrfp.domid, &d);
+        if ( rc != 0 )
+            return rc;
+
+        if ( xsm_remove_from_physmap(current->domain, d) )
+        {
+            rcu_unlock_domain(d);
+            return -EPERM;
+        }
+
+        domain_lock(d);
+
+        mfn = get_gfn_untyped(d, xrfp.gpfn);
+
+        if ( mfn_valid(mfn) )
+            guest_physmap_remove_page(d, xrfp.gpfn, mfn, PAGE_ORDER_4K);
+        else
+            rc = -ENOENT;
+
+        put_gfn(d, xrfp.gpfn);
+
+        domain_unlock(d);
+
+        rcu_unlock_domain(d);
+
+        break;
+    }
+
     default:
         rc = arch_memory_op(op, arg);
         break;
index d09c363df31e819d7b36865aa41a3d8fb3705e1e..a2bfc026e638052a81741e2555c2a3f434e8006a 100644 (file)
@@ -550,6 +550,7 @@ extern u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__,
 #define gmfn_to_mfn(_d, gpfn)                  \
     gmfn_to_mfn_foreign((_d), (gpfn))
 
+#define get_gfn_untyped(d, gpfn) gmfn_to_mfn(d, gpfn)
 #define put_gfn(d, g)   ((void)0)
 
 #define __gpfn_invalid(_d, gpfn)                       \
index 3bc2f25cdc6c34cb6a2c5e6d694e4e5738d27fe6..9d9aabcfdb96902f66737b90f3ff0457dc1a7c1b 100644 (file)
@@ -229,6 +229,22 @@ struct xen_add_to_physmap {
 typedef struct xen_add_to_physmap xen_add_to_physmap_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
 
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap      15
+struct xen_remove_from_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* GPFN of the current mapping of the page. */
+    xen_pfn_t     gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
+
 /*** REMOVED ***/
 /*#define XENMEM_translate_gpfn_list  8*/
 
index f6021550df3d8032a2341d4cff96056546cd7ded..3d4f1e328f1e96547fe5d4226b1c2a4ba9e53846 100644 (file)
@@ -60,6 +60,7 @@
 !      memory_map                      memory.h
 !      memory_reservation              memory.h
 !      pod_target                      memory.h
+!      remove_from_physmap             memory.h
 ?      physdev_eoi                     physdev.h
 ?      physdev_get_free_pirq           physdev.h
 ?      physdev_irq                     physdev.h
index df6cec22f3263e718a13d289bb4e5aa7f88444af..566c8080f74ae2d8ece7a32a16360b69e4463492 100644 (file)
@@ -169,6 +169,7 @@ struct xsm_operations {
     int (*update_va_mapping) (struct domain *d, struct domain *f, 
                                                             l1_pgentry_t pte);
     int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+    int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
     int (*sendtrigger) (struct domain *d);
     int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
     int (*unbind_pt_irq) (struct domain *d);
@@ -738,6 +739,11 @@ static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
     return xsm_call(add_to_physmap(d1, d2));
 }
 
+static inline int xsm_remove_from_physmap(struct domain *d1, struct domain *d2)
+{
+    return xsm_call(remove_from_physmap(d1, d2));
+}
+
 static inline int xsm_sendtrigger(struct domain *d)
 {
     return xsm_call(sendtrigger(d));
index 4bbfbffb1472c631bf114064a1f5c495e43cfe2b..65daa4e77581f2f419d0e24290eda846df6c6e86 100644 (file)
@@ -529,6 +529,11 @@ static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
     return 0;
 }
 
+static int dummy_remove_from_physmap (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
 static int dummy_sendtrigger (struct domain *d)
 {
     return 0;
@@ -690,6 +695,7 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, mmu_machphys_update);
     set_to_dummy_if_null(ops, update_va_mapping);
     set_to_dummy_if_null(ops, add_to_physmap);
+    set_to_dummy_if_null(ops, remove_from_physmap);
     set_to_dummy_if_null(ops, sendtrigger);
     set_to_dummy_if_null(ops, bind_pt_irq);
     set_to_dummy_if_null(ops, pin_mem_cacheattr);
index 0d3576782119984e75a9ed6b57862a624aac7702..a2020a9f603b36c2caf1e9aa0db07ecdad41554d 100644 (file)
@@ -1283,6 +1283,11 @@ static int flask_add_to_physmap(struct domain *d1, struct domain *d2)
     return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
 }
 
+static int flask_remove_from_physmap(struct domain *d1, struct domain *d2)
+{
+    return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
+}
+
 static int flask_sendtrigger(struct domain *d)
 {
     return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__TRIGGER);
@@ -1550,6 +1555,7 @@ static struct xsm_operations flask_ops = {
     .mmu_machphys_update = flask_mmu_machphys_update,
     .update_va_mapping = flask_update_va_mapping,
     .add_to_physmap = flask_add_to_physmap,
+    .remove_from_physmap = flask_remove_from_physmap,
     .sendtrigger = flask_sendtrigger,
     .get_device_group = flask_get_device_group,
     .test_assign_device = flask_test_assign_device,