[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH 14/16]: PVH xen: add xenmem_add_foreign_to_pmap()



In this patch, I add a new function, xenmem_add_foreign_to_pmap(), to
map pages from foreign gue st into current dom0 for domU creation.
Also, some minor grant changes for PVH.

Signed-off-by: Mukesh Rathor <mukesh.rathor@xxxxxxxxxx>

diff -r 2c894340b16f -r 47d2e652bd4d xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Jan 11 16:43:02 2013 -0800
+++ b/xen/arch/x86/mm.c Fri Jan 11 16:45:36 2013 -0800
@@ -2608,7 +2608,7 @@ static struct domain *get_pg_owner(domid
         goto out;
     }
 
-    if ( unlikely(paging_mode_translate(curr)) )
+    if ( !is_pvh_domain(curr) && unlikely(paging_mode_translate(curr)) )
     {
         MEM_LOG("Cannot mix foreign mappings with translated domains");
         goto out;
@@ -3734,16 +3734,34 @@ static int replace_grant_p2m_mapping(
     old_mfn = get_gfn(d, gfn, &type);
     if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame )
     {
-        put_gfn(d, gfn);
         gdprintk(XENLOG_WARNING,
-                 "replace_grant_p2m_mapping: old mapping invalid (type %d, mfn 
%lx, frame %lx)\n",
+                 "replace_grant_p2m_mapping: old mapping invalid "
+                 "(type %d, mfn %lx, frame %lx)\n",
                  type, mfn_x(old_mfn), frame);
-        return GNTST_general_error;
+        goto out_err;
     }
     guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K);
 
+    /* PVH: Because we free the existing mfn in XENMEM_add_to_physmap during
+     * grant map, we undo that here so the guest P2M (EPT/NPT) is consistent */
+    if ( is_pvh_domain(d) ) {
+        struct page_info *page = alloc_domheap_page(d, 0);
+
+       if ( page == NULL ) {
+           gdprintk(XENLOG_ERR, "Unable to alloc domheap page\n");
+            goto out_err;
+       }
+       if ( guest_physmap_add_page(d, gfn, page_to_mfn(page), 0) != 0 ) {
+           gdprintk(XENLOG_ERR, "Unable to add mfn to replace grant\n");
+            goto out_err;
+        }
+    }
     put_gfn(d, gfn);
     return GNTST_okay;
+
+out_err:
+    put_gfn(d, gfn);
+    return GNTST_general_error;
 }
 
 int replace_grant_host_mapping(
@@ -4143,7 +4161,7 @@ long do_update_descriptor(u64 pa, u64 de
     page = get_page_from_gfn(dom, gmfn, NULL, P2M_ALLOC);
     if ( (((unsigned int)pa % sizeof(struct desc_struct)) != 0) ||
          !page ||
-         !check_descriptor(dom, &d) )
+         (!is_pvh_domain(dom) && !check_descriptor(dom, &d)) )
     {
         if ( page )
             put_page(page);
@@ -4217,7 +4235,81 @@ static int handle_iomem_range(unsigned l
     return 0;
 }
 
-static int xenmem_add_to_physmap_once(
+/* add frames from foreign domain to current domain's physmap. Similar to 
+ * XENMAPSPACE_gmfn but the frame is foreign being mapped into current,
+ * and is not removed from foreign domain. 
+ * Usage: libxl on pvh dom0 creating a guest and doing privcmd_ioctl_mmap
+ * Returns: 0 ==> success
+ */
+static long noinline xenmem_add_foreign_to_pmap( domid_t foreign_domid, 
+                                        unsigned long fgmfn, unsigned long 
gpfn)
+{
+    unsigned long rc=0, prev_mfn, mfn = 0;
+    struct domain *fdom, *currd = current->domain;
+    p2m_type_t p2mt, p2mt_prev;
+
+    if ( (fdom = get_pg_owner(foreign_domid)) == NULL ) {
+        return -EPERM;
+    }
+
+    mfn = mfn_x(get_gfn_query_unlocked(fdom, fgmfn, &p2mt));
+
+    /* qemu, running on PVH dom0, mapping hvm domain's io pages during domain 
+     * creation, doesn't have mfns in the HAP table */
+    if ( !mfn_valid(mfn) && p2m_is_mmio(p2mt) ) {
+
+        if (!is_hvm_domain(fdom)) {
+            printk("mmio type for non-hvm domain. fd:%d fgmfn:%lx gpfn:%lx\n",
+                   foreign_domid, fgmfn, gpfn);
+            return -EINVAL;
+        }
+        mfn = fgmfn;     /* map 1 to 1 */
+    }
+
+    if ( !p2m_is_valid(p2mt) ) {
+        put_pg_owner(fdom);
+        return -EINVAL;
+    }
+
+    if ( !p2m_is_mmio(p2mt) && !get_page_from_pagenr(mfn, fdom) ) {
+        put_pg_owner(fdom);
+        return -EINVAL;
+    }
+
+    /* Remove previously mapped page if it was present. */
+    prev_mfn = mfn_x(get_gfn_query_unlocked(currd, gpfn, &p2mt_prev));
+    if ( mfn_valid(prev_mfn) )
+    {
+        if ( is_xen_heap_mfn(prev_mfn) )
+            /* Xen heap frames are simply unhooked from this phys slot */
+            guest_physmap_remove_page(currd, gpfn, prev_mfn, 0);
+        else
+            /* Normal domain memory is freed, to avoid leaking memory. */
+            guest_remove_page(currd, gpfn);
+    }
+
+    /* Map at new location.  Can't use guest_physmap_add_page() because it 
+     * will update the m2p table which will result in  mfn --> gpfn of dom0 
+     * and not gpfn of domU.  */
+    if ( p2m_is_mmio(p2mt) ) {
+        if ( set_mmio_p2m_entry(currd, gpfn, _mfn(mfn)) == 0 ) {
+            printk("set_mmio_p2m failed. gpfn:%lx mfn:%lx fgmfn:%lx\n", 
+                   gpfn, mfn, fgmfn);
+            rc = -EINVAL;
+        }
+
+    } else if ( set_foreign_p2m_entry(currd, gpfn, _mfn(mfn)) == 0 ) {
+
+        printk("guest_physmap_add_page failed1. gpfn:%lx mfn:%lx fgmfn:%lx\n", 
+             gpfn, mfn, fgmfn);
+        put_page(mfn_to_page(mfn));
+        rc = -EINVAL;
+    }
+    put_pg_owner(fdom);
+    return rc;
+}
+
+static int noinline xenmem_add_to_physmap_once(
     struct domain *d, uint16_t xatp_space, domid_t foreign_domid,
     unsigned long xatp_idx, unsigned long xatp_gpfn)
 {
@@ -4278,6 +4370,13 @@ static int xenmem_add_to_physmap_once(
             page = mfn_to_page(mfn);
             break;
         }
+
+        case XENMAPSPACE_gmfn_foreign:
+        {
+            rc = xenmem_add_foreign_to_pmap(foreign_domid, xatp_idx, 
xatp_gpfn);
+            return rc;
+        }
+
         default:
             break;
     }
diff -r 2c894340b16f -r 47d2e652bd4d xen/common/grant_table.c
--- a/xen/common/grant_table.c  Fri Jan 11 16:43:02 2013 -0800
+++ b/xen/common/grant_table.c  Fri Jan 11 16:45:36 2013 -0800
@@ -529,7 +529,7 @@ static void mapcount(
  * addr is _either_ a host virtual address, or the address of the pte to
  * update, as indicated by the GNTMAP_contains_pte flag.
  */
-static void
+static noinline void
 __gnttab_map_grant_ref(
     struct gnttab_map_grant_ref *op)
 {
@@ -745,7 +745,7 @@ __gnttab_map_grant_ref(
 
     double_gt_lock(lgt, rgt);
 
-    if ( !is_hvm_domain(ld) && need_iommu(ld) )
+    if ( !is_hvm_or_pvh_domain(ld) && need_iommu(ld) )
     {
         unsigned int wrc, rdc;
         int err = 0;
@@ -956,7 +956,7 @@ __gnttab_unmap_common(
             act->pin -= GNTPIN_hstw_inc;
     }
 
-    if ( !is_hvm_domain(ld) && need_iommu(ld) )
+    if ( !is_hvm_or_pvh_domain(ld) && need_iommu(ld) )
     {
         unsigned int wrc, rdc;
         int err = 0;

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.