All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mukesh Rathor <mukesh.rathor@oracle.com>
To: Xen-devel@lists.xensource.com
Cc: george.dunlap@eu.citrix.com, keir.xen@gmail.com, tim@xen.org,
	JBeulich@suse.com
Subject: [V6 PATCH 6/7] pvh dom0: Add and remove foreign pages
Date: Thu,  5 Dec 2013 18:38:43 -0800	[thread overview]
Message-ID: <1386297524-15483-7-git-send-email-mukesh.rathor@oracle.com> (raw)
In-Reply-To: <1386297524-15483-1-git-send-email-mukesh.rathor@oracle.com>

In this patch, a new function, xenmem_add_foreign_to_p2m(), is added
to map pages from foreign guest into current dom0 for domU creation.
Such pages are typed p2m_map_foreign. Also, support is added here to
XENMEM_remove_from_physmap to remove such pages. Note, in the remove
path, we must release the refcount that was taken during the map phase.

Signed-off-by: Mukesh Rathor <mukesh.rathor@oracle.com>
---
 xen/arch/x86/mm.c         |   88 +++++++++++++++++++++++++++++++++++++++++----
 xen/common/memory.c       |   37 ++++++++++++++++++-
 xen/include/asm-arm/p2m.h |    2 +
 3 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index e3da479..1a4d564 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2810,7 +2810,7 @@ static struct domain *get_pg_owner(domid_t 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;
@@ -4520,9 +4520,75 @@ static int handle_iomem_range(unsigned long s, unsigned long e, void *p)
     return 0;
 }
 
+/*
+ * Add frames from foreign domain to target 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.
+ * Side Effect: the mfn for fgfn will be refcounted so it is not lost
+ *              while mapped here. The refcnt is released in do_memory_op()
+ *              via XENMEM_remove_from_physmap.
+ * Returns: 0 ==> success
+ */
+static int xenmem_add_foreign_to_p2m(struct domain *tdom, unsigned long fgfn,
+                                     unsigned long gpfn, struct domain *fdom)
+{
+    p2m_type_t p2mt, p2mt_prev;
+    int rc = 0;
+    unsigned long prev_mfn, mfn = 0;
+    struct page_info *page = NULL;
+
+    if ( tdom == fdom || !tdom || !fdom || !is_pvh_domain(tdom) )
+        return -EINVAL;
+
+    /* following will take a refcnt on the mfn */
+    page = get_page_from_gfn(fdom, fgfn, &p2mt, P2M_ALLOC);
+    if ( !page || !p2m_is_valid(p2mt) )
+    {
+        if ( page )
+            put_page(page);
+        return -EINVAL;
+    }
+    mfn = page_to_mfn(page);
+
+    /* Remove previously mapped page if it is present. */
+    prev_mfn = mfn_x(get_gfn(tdom, 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(tdom, gpfn, prev_mfn, 0);
+        else
+            /* Normal domain memory is freed, to avoid leaking memory. */
+            guest_remove_page(tdom, gpfn);
+    }
+    /*
+     * Create the new mapping. Can't use guest_physmap_add_page() because it
+     * will update the m2p table which will result in  mfn -> gpfn of dom0
+     * and not fgfn of domU.
+     */
+    if ( set_foreign_p2m_entry(tdom, gpfn, _mfn(mfn)) == 0 )
+    {
+        gdprintk(XENLOG_WARNING, "set_foreign_p2m_entry failed. "
+                 "gpfn:%lx mfn:%lx fgfn:%lx td:%d fd:%d\n",
+                 gpfn, mfn, fgfn, tdom->domain_id, fdom->domain_id);
+        put_page(page);
+        rc = -EINVAL;
+    }
+
+    /*
+     * We must do this put_gfn after set_foreign_p2m_entry so another cpu
+     * doesn't populate the gpfn before us.
+     */
+    put_gfn(tdom, gpfn);
+
+    return rc;
+}
+
 static int xenmem_add_to_physmap_once(
     struct domain *d,
-    const struct xen_add_to_physmap *xatp)
+    const struct xen_add_to_physmap *xatp,
+    struct domain *fdom)
 {
     struct page_info *page = NULL;
     unsigned long gfn = 0; /* gcc ... */
@@ -4581,6 +4647,13 @@ static int xenmem_add_to_physmap_once(
             page = mfn_to_page(mfn);
             break;
         }
+
+        case XENMAPSPACE_gmfn_foreign:
+        {
+            rc = xenmem_add_foreign_to_p2m(d, xatp->idx, xatp->gpfn, fdom);
+            return rc;
+        }
+
         default:
             break;
     }
@@ -4646,7 +4719,7 @@ static int xenmem_add_to_physmap(struct domain *d,
         start_xatp = *xatp;
         while ( xatp->size > 0 )
         {
-            rc = xenmem_add_to_physmap_once(d, xatp);
+            rc = xenmem_add_to_physmap_once(d, xatp, NULL);
             if ( rc < 0 )
                 return rc;
 
@@ -4672,11 +4745,12 @@ static int xenmem_add_to_physmap(struct domain *d,
         return rc;
     }
 
-    return xenmem_add_to_physmap_once(d, xatp);
+    return xenmem_add_to_physmap_once(d, xatp, NULL);
 }
 
 static int xenmem_add_to_physmap_range(struct domain *d,
-                                       struct xen_add_to_physmap_range *xatpr)
+                                       struct xen_add_to_physmap_range *xatpr,
+                                       struct domain *fdom)
 {
     /* Process entries in reverse order to allow continuations */
     while ( xatpr->size > 0 )
@@ -4693,7 +4767,7 @@ static int xenmem_add_to_physmap_range(struct domain *d,
         xatp.space = xatpr->space;
         xatp.idx = idx;
         xatp.gpfn = gpfn;
-        rc = xenmem_add_to_physmap_once(d, &xatp);
+        rc = xenmem_add_to_physmap_once(d, &xatp, fdom);
 
         if ( copy_to_guest_offset(xatpr->errs, xatpr->size-1, &rc, 1) )
             return -EFAULT;
@@ -4780,7 +4854,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
         }
         rc = xsm_add_to_physmap(XSM_TARGET, current->domain, d, fd);
         if ( rc == 0 )
-            rc = xenmem_add_to_physmap_range(d, &xatpr);
+            rc = xenmem_add_to_physmap_range(d, &xatpr, fd);
 
         rcu_unlock_domain(d);
         if ( fd )
diff --git a/xen/common/memory.c b/xen/common/memory.c
index eb7b72b..7103c8b 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -675,9 +675,11 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 
     case XENMEM_remove_from_physmap:
     {
+        unsigned long mfn;
         struct xen_remove_from_physmap xrfp;
         struct page_info *page;
         struct domain *d;
+        p2m_type_t p2mt = -1;
 
         if ( copy_from_guest(&xrfp, arg, 1) )
             return -EFAULT;
@@ -693,11 +695,42 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
             return rc;
         }
 
+        /*
+         * If autotranslate guest, (eg pvh), the gfn could be mapped to a mfn
+         * from foreign domain by the user space tool during domain creation.
+         * We need to check for that, free it up from the p2m, and release
+         * refcnt on it. In such a case, page would be NULL and the following
+         * call would not have refcnt'd the page.
+         * See also xenmem_add_foreign_to_p2m().
+         */
         page = get_page_from_gfn(d, xrfp.gpfn, NULL, P2M_ALLOC);
         if ( page )
+            mfn = page_to_mfn(page);
+#ifdef CONFIG_X86
+        else
         {
-            guest_physmap_remove_page(d, xrfp.gpfn, page_to_mfn(page), 0);
-            put_page(page);
+            mfn = mfn_x(get_gfn_query(d, xrfp.gpfn, &p2mt));
+            if ( p2m_is_foreign(p2mt) )
+            {
+                struct domain *foreign_dom;
+
+                foreign_dom = page_get_owner(mfn_to_page(mfn));
+                ASSERT(is_pvh_domain(d));
+                ASSERT(d != foreign_dom);
+            }
+        }
+#endif
+        if ( page || p2m_is_foreign(p2mt) )
+        {
+            guest_physmap_remove_page(d, xrfp.gpfn, mfn, 0);
+            if ( page )
+                put_page(page);
+
+            if ( p2m_is_foreign(p2mt) )
+            {
+                put_page(mfn_to_page(mfn));
+                put_gfn(d, xrfp.gpfn);
+            }
         }
         else
             rc = -ENOENT;
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index c660820..f079f00 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -110,6 +110,8 @@ static inline int get_page_and_type(struct page_info *page,
     return rc;
 }
 
+#define p2m_is_foreign(_t) (0)
+
 #endif /* _XEN_P2M_H */
 
 /*
-- 
1.7.2.3

  parent reply	other threads:[~2013-12-06  2:38 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-06  2:38 [V6 PATCH 0/7]: PVH dom0 Mukesh Rathor
2013-12-06  2:38 ` [V6 PATCH 1/7] pvh dom0: move some pv specific code to static functions Mukesh Rathor
2013-12-06  2:38 ` [V6 PATCH 2/7] pvh dom0: construct_dom0 changes Mukesh Rathor
2013-12-06  2:38 ` [V6 PATCH 3/7] pvh dom0: implement XENMEM_add_to_physmap_range for x86 Mukesh Rathor
2013-12-06  2:38 ` [V6 PATCH 4/7] pvh dom0: Introduce p2m_map_foreign Mukesh Rathor
2013-12-09 12:02   ` Tim Deegan
2013-12-06  2:38 ` [V6 PATCH 5/7] pvh: change xsm_add_to_physmap Mukesh Rathor
2013-12-06  2:38 ` Mukesh Rathor [this message]
2013-12-06  2:54   ` [V6 PATCH 6/7] pvh dom0: Add and remove foreign pages Mukesh Rathor
2013-12-06 11:46     ` Jan Beulich
2013-12-07  2:09       ` Mukesh Rathor
2013-12-07  2:34   ` [V6 PATCH 6.1/7] " Mukesh Rathor
2013-12-07 16:06     ` Julien Grall
2013-12-09  9:50     ` Jan Beulich
2013-12-10  1:30       ` Mukesh Rathor
2013-12-09 10:31     ` Ian Campbell
2013-12-09 13:46       ` Julien Grall
2013-12-09 12:11     ` Tim Deegan
2013-12-10  2:16       ` Mukesh Rathor
2013-12-09  2:45   ` [V6 PATCH 6/7] " Julien Grall
2013-12-09  2:57     ` Julien Grall
2013-12-10  2:17     ` Mukesh Rathor
2013-12-11  0:27   ` [V6 PATCH 6.2/7] " Mukesh Rathor
2013-12-11  0:44     ` Mukesh Rathor
2013-12-11  1:35       ` Julien Grall
2013-12-11  1:47         ` Mukesh Rathor
2013-12-11  9:23           ` Jan Beulich
2013-12-11 14:29           ` Tim Deegan
2013-12-12  2:46             ` Mukesh Rathor
2013-12-13  2:44               ` Mukesh Rathor
2013-12-13 11:25                 ` Tim Deegan
2013-12-13 11:39                   ` Jan Beulich
2013-12-13 19:02                     ` George Dunlap
2013-12-16  7:47                       ` Jan Beulich
2013-12-14  2:48                   ` Mukesh Rathor
2013-12-16  8:40                     ` Jan Beulich
2013-12-16 23:27                       ` Mukesh Rathor
2013-12-16 23:44                         ` Julien Grall
2013-12-17  1:51                           ` Mukesh Rathor
2013-12-17  2:33                         ` Mukesh Rathor
2013-12-17 10:10                         ` Tim Deegan
2013-12-17 23:24                           ` Mukesh Rathor
2013-12-18  2:34                           ` Mukesh Rathor
2013-12-18  9:51                             ` Jan Beulich
2013-12-18  9:53                             ` Tim Deegan
2013-12-06  2:38 ` [V6 PATCH 7/7] pvh dom0: add opt_dom0pvh to setup.c Mukesh Rathor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1386297524-15483-7-git-send-email-mukesh.rathor@oracle.com \
    --to=mukesh.rathor@oracle.com \
    --cc=JBeulich@suse.com \
    --cc=Xen-devel@lists.xensource.com \
    --cc=george.dunlap@eu.citrix.com \
    --cc=keir.xen@gmail.com \
    --cc=tim@xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.