xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Dan Magenheimer <dan.magenheimer@oracle.com>
To: xen-devel@lists.xensource.com, Keir Fraser <keir.fraser@eu.citrix.com>
Subject: [PATCH] enable tmem functionality for PV on HVM guests
Date: Mon, 21 Jun 2010 10:14:41 -0700 (PDT)	[thread overview]
Message-ID: <a7f1ebf4-698e-42f0-9d03-70d77efdde2d@default> (raw)

[-- Attachment #1: Type: text/plain, Size: 5309 bytes --]

(Keir, please also apply for 4.0.1 if it's not too late.)

Enable tmem functionality for PV on HVM guests.  Guest kernel
must still be tmem-enabled to use this functionality (e.g.
won't work for Windows), but upstream Linux tmem (aka
cleancache and frontswap) patches apply cleanly on top
of PV on HVM patches.

Also, fix up some ASSERTS and code used only when bad guest
mfns are passed to tmem.  Previous code could crash Xen
if a buggy/malicious guest passes bad gmfns.

Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>

diff -r ba2c0eecaf7f xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/arch/x86/hvm/hvm.c	Mon Jun 21 10:37:05 2010 -0600
@@ -2265,7 +2265,8 @@ static hvm_hypercall_t *hvm_hypercall32_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 #else /* defined(__x86_64__) */
@@ -2313,7 +2314,8 @@ static hvm_hypercall_t *hvm_hypercall64_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 static hvm_hypercall_t *hvm_hypercall32_table[NR_hypercalls] = {
@@ -2323,7 +2325,8 @@ static hvm_hypercall_t *hvm_hypercall32_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 #endif /* defined(__x86_64__) */
diff -r ba2c0eecaf7f xen/common/tmem.c
--- a/xen/common/tmem.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/common/tmem.c	Mon Jun 21 10:37:05 2010 -0600
@@ -1483,6 +1483,7 @@ copy_uncompressed:
         pgp_free_data(pgp, pool);
     if ( ( pgp->pfp = tmem_page_alloc(pool) ) == NULL )
         goto failed_dup;
+    pgp->size = 0;
     /* tmh_copy_from_client properly handles len==0 and offsets != 0 */
     ret = tmh_copy_from_client(pgp->pfp,cmfn,tmem_offset,pfn_offset,len,0);
     if ( ret == -EFAULT )
@@ -1492,7 +1493,6 @@ copy_uncompressed:
         if ( pcd_associate(pgp,NULL,0) == -ENOMEM )
             goto failed_dup;
     }
-    pgp->size = 0;
 
 done:
     /* successfully replaced data, clean up and return success */
@@ -1509,12 +1509,14 @@ bad_copy:
 bad_copy:
     /* this should only happen if the client passed a bad mfn */
     failed_copies++;
-ASSERT(0);
-    return -EFAULT;
+    ret = -EFAULT;
+    goto cleanup;
 
 failed_dup:
    /* couldn't change out the data, flush the old data and return
     * -ENOSPC instead of -ENOMEM to differentiate failed _dup_ put */
+    ret = -ENOSPC;
+cleanup:
     pgpfound = pgp_delete_from_obj(obj, pgp->index);
     ASSERT(pgpfound == pgp);
     pgp_delete(pgpfound,0);
@@ -1528,7 +1530,7 @@ failed_dup:
         tmem_spin_unlock(&obj->obj_spinlock);
     }
     pool->dup_puts_flushed++;
-    return -ENOSPC;
+    return ret;
 }
 
 
@@ -1579,6 +1581,7 @@ static NOINLINE int do_tmem_put(pool_t *
         goto free;
     ASSERT(ret != -EEXIST);
     pgp->index = index;
+    pgp->size = 0;
 
     if ( len != 0 && client->compress )
     {
@@ -1615,7 +1618,6 @@ copy_uncompressed:
         if ( pcd_associate(pgp,NULL,0) == -ENOMEM )
             goto delete_and_free;
     }
-    pgp->size = 0;
 
 insert_page:
     if ( is_ephemeral(pool) )
@@ -1648,6 +1650,11 @@ insert_page:
         tot_good_eph_puts++;
     return 1;
 
+bad_copy:
+    /* this should only happen if the client passed a bad mfn */
+    ret = -EFAULT;
+    failed_copies++;
+
 delete_and_free:
     ASSERT((obj != NULL) && (pgp != NULL) && (pgp->index != -1));
     pgpdel = pgp_delete_from_obj(obj, pgp->index);
@@ -1669,12 +1676,6 @@ free:
     }
     pool->no_mem_puts++;
     return ret;
-
-bad_copy:
-    /* this should only happen if the client passed a bad mfn */
-    failed_copies++;
-ASSERT(0);
-    goto free;
 }
 
 static NOINLINE int do_tmem_get(pool_t *pool, uint64_t oid, uint32_t index,
@@ -1758,7 +1759,6 @@ bad_copy:
 bad_copy:
     /* this should only happen if the client passed a bad mfn */
     failed_copies++;
-ASSERT(0);
     return -EFAULT;
 
 }
diff -r ba2c0eecaf7f xen/common/tmem_xen.c
--- a/xen/common/tmem_xen.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/common/tmem_xen.c	Mon Jun 21 10:37:05 2010 -0600
@@ -100,7 +100,7 @@ static inline void *cli_mfn_to_va(tmem_c
     p2m_type_t t;
 
     cli_mfn = mfn_x(gfn_to_mfn(current->domain, cmfn, &t));
-    if (t != p2m_ram_rw)
+    if (t != p2m_ram_rw || cli_mfn == INVALID_MFN)
         return NULL;
     if (pcli_mfn != NULL)
         *pcli_mfn = cli_mfn;
diff -r ba2c0eecaf7f xen/include/xen/tmem_xen.h
--- a/xen/include/xen/tmem_xen.h	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/include/xen/tmem_xen.h	Mon Jun 21 10:37:05 2010 -0600
@@ -456,7 +456,9 @@ static inline int tmh_get_tmemop_from_cl
 static inline int tmh_get_tmemop_from_client(tmem_op_t *op, tmem_cli_op_t uops)
 {
 #ifdef CONFIG_COMPAT
-    if ( is_pv_32on64_vcpu(current) )
+    if ( is_hvm_vcpu(current) ?
+         hvm_guest_x86_mode(current) != 8 :
+         is_pv_32on64_vcpu(current) )
     {
         int rc;
         enum XLAT_tmem_op_u u;

[-- Attachment #2: tmem-hvm.patch --]
[-- Type: application/octet-stream, Size: 4607 bytes --]

diff -r ba2c0eecaf7f xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/arch/x86/hvm/hvm.c	Mon Jun 21 10:37:05 2010 -0600
@@ -2265,7 +2265,8 @@ static hvm_hypercall_t *hvm_hypercall32_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 #else /* defined(__x86_64__) */
@@ -2313,7 +2314,8 @@ static hvm_hypercall_t *hvm_hypercall64_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 static hvm_hypercall_t *hvm_hypercall32_table[NR_hypercalls] = {
@@ -2323,7 +2325,8 @@ static hvm_hypercall_t *hvm_hypercall32_
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
-    HYPERCALL(hvm_op)
+    HYPERCALL(hvm_op),
+    HYPERCALL(tmem_op)
 };
 
 #endif /* defined(__x86_64__) */
diff -r ba2c0eecaf7f xen/common/tmem.c
--- a/xen/common/tmem.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/common/tmem.c	Mon Jun 21 10:37:05 2010 -0600
@@ -1483,6 +1483,7 @@ copy_uncompressed:
         pgp_free_data(pgp, pool);
     if ( ( pgp->pfp = tmem_page_alloc(pool) ) == NULL )
         goto failed_dup;
+    pgp->size = 0;
     /* tmh_copy_from_client properly handles len==0 and offsets != 0 */
     ret = tmh_copy_from_client(pgp->pfp,cmfn,tmem_offset,pfn_offset,len,0);
     if ( ret == -EFAULT )
@@ -1492,7 +1493,6 @@ copy_uncompressed:
         if ( pcd_associate(pgp,NULL,0) == -ENOMEM )
             goto failed_dup;
     }
-    pgp->size = 0;
 
 done:
     /* successfully replaced data, clean up and return success */
@@ -1509,12 +1509,14 @@ bad_copy:
 bad_copy:
     /* this should only happen if the client passed a bad mfn */
     failed_copies++;
-ASSERT(0);
-    return -EFAULT;
+    ret = -EFAULT;
+    goto cleanup;
 
 failed_dup:
    /* couldn't change out the data, flush the old data and return
     * -ENOSPC instead of -ENOMEM to differentiate failed _dup_ put */
+    ret = -ENOSPC;
+cleanup:
     pgpfound = pgp_delete_from_obj(obj, pgp->index);
     ASSERT(pgpfound == pgp);
     pgp_delete(pgpfound,0);
@@ -1528,7 +1530,7 @@ failed_dup:
         tmem_spin_unlock(&obj->obj_spinlock);
     }
     pool->dup_puts_flushed++;
-    return -ENOSPC;
+    return ret;
 }
 
 
@@ -1579,6 +1581,7 @@ static NOINLINE int do_tmem_put(pool_t *
         goto free;
     ASSERT(ret != -EEXIST);
     pgp->index = index;
+    pgp->size = 0;
 
     if ( len != 0 && client->compress )
     {
@@ -1615,7 +1618,6 @@ copy_uncompressed:
         if ( pcd_associate(pgp,NULL,0) == -ENOMEM )
             goto delete_and_free;
     }
-    pgp->size = 0;
 
 insert_page:
     if ( is_ephemeral(pool) )
@@ -1648,6 +1650,11 @@ insert_page:
         tot_good_eph_puts++;
     return 1;
 
+bad_copy:
+    /* this should only happen if the client passed a bad mfn */
+    ret = -EFAULT;
+    failed_copies++;
+
 delete_and_free:
     ASSERT((obj != NULL) && (pgp != NULL) && (pgp->index != -1));
     pgpdel = pgp_delete_from_obj(obj, pgp->index);
@@ -1669,12 +1676,6 @@ free:
     }
     pool->no_mem_puts++;
     return ret;
-
-bad_copy:
-    /* this should only happen if the client passed a bad mfn */
-    failed_copies++;
-ASSERT(0);
-    goto free;
 }
 
 static NOINLINE int do_tmem_get(pool_t *pool, uint64_t oid, uint32_t index,
@@ -1758,7 +1759,6 @@ bad_copy:
 bad_copy:
     /* this should only happen if the client passed a bad mfn */
     failed_copies++;
-ASSERT(0);
     return -EFAULT;
 
 }
diff -r ba2c0eecaf7f xen/common/tmem_xen.c
--- a/xen/common/tmem_xen.c	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/common/tmem_xen.c	Mon Jun 21 10:37:05 2010 -0600
@@ -100,7 +100,7 @@ static inline void *cli_mfn_to_va(tmem_c
     p2m_type_t t;
 
     cli_mfn = mfn_x(gfn_to_mfn(current->domain, cmfn, &t));
-    if (t != p2m_ram_rw)
+    if (t != p2m_ram_rw || cli_mfn == INVALID_MFN)
         return NULL;
     if (pcli_mfn != NULL)
         *pcli_mfn = cli_mfn;
diff -r ba2c0eecaf7f xen/include/xen/tmem_xen.h
--- a/xen/include/xen/tmem_xen.h	Tue Jun 15 11:31:43 2010 +0100
+++ b/xen/include/xen/tmem_xen.h	Mon Jun 21 10:37:05 2010 -0600
@@ -456,7 +456,9 @@ static inline int tmh_get_tmemop_from_cl
 static inline int tmh_get_tmemop_from_client(tmem_op_t *op, tmem_cli_op_t uops)
 {
 #ifdef CONFIG_COMPAT
-    if ( is_pv_32on64_vcpu(current) )
+    if ( is_hvm_vcpu(current) ?
+         hvm_guest_x86_mode(current) != 8 :
+         is_pv_32on64_vcpu(current) )
     {
         int rc;
         enum XLAT_tmem_op_u u;

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

             reply	other threads:[~2010-06-21 17:14 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-21 17:14 Dan Magenheimer [this message]
2010-06-21 17:39 ` [PATCH] enable tmem functionality for PV on HVM guests Keir Fraser
2010-06-21 17:54   ` Dan Magenheimer

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=a7f1ebf4-698e-42f0-9d03-70d77efdde2d@default \
    --to=dan.magenheimer@oracle.com \
    --cc=keir.fraser@eu.citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).