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

[Xen-changelog] [xen-unstable] x86: extend mmu_update hypercall to allow update of foreign pagetables.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1246973939 -3600
# Node ID 01ae7dc043bae5987a67e9aee4109839b1e40996
# Parent  a29bb4efff00b1323a52527b974d58651fdce9b6
x86: extend mmu_update hypercall to allow update of foreign pagetables.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>
---
 xen/arch/x86/mm.c        |   55 +++++++++++++++++++++++++++++++++--------------
 xen/include/public/xen.h |   30 ++++++++++++++++---------
 2 files changed, 58 insertions(+), 27 deletions(-)

diff -r a29bb4efff00 -r 01ae7dc043ba xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Tue Jul 07 14:21:16 2009 +0100
+++ b/xen/arch/x86/mm.c Tue Jul 07 14:38:59 2009 +0100
@@ -110,6 +110,7 @@
 #include <asm/hypercall.h>
 #include <asm/shared.h>
 #include <public/memory.h>
+#include <public/sched.h>
 #include <xsm/xsm.h>
 #include <xen/trace.h>
 
@@ -2999,8 +3000,9 @@ int do_mmu_update(
     unsigned long gpfn, gmfn, mfn;
     struct page_info *page;
     int rc = 0, okay = 1, i = 0;
-    unsigned int cmd, done = 0;
-    struct domain *d = current->domain;
+    unsigned int cmd, done = 0, pt_dom;
+    struct domain *d = current->domain, *pt_owner = d;
+    struct vcpu *v = current;
     struct domain_mmap_cache mapcache;
 
     if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
@@ -3018,7 +3020,29 @@ int do_mmu_update(
         goto out;
     }
 
-    if ( !set_foreigndom(foreigndom) )
+    if ( (pt_dom = foreigndom >> 16) != 0 )
+    {
+        /* Pagetables belong to a foreign domain (PFD). */
+        if ( (pt_owner = rcu_lock_domain_by_id(pt_dom - 1)) == NULL )
+        {
+            rc = -EINVAL;
+            goto out;
+        }
+        if ( pt_owner == d )
+            rcu_unlock_domain(pt_owner);
+        if ( (v = pt_owner->vcpu ? pt_owner->vcpu[0] : NULL) == NULL )
+        {
+            rc = -EINVAL;
+            goto out;
+        }
+        if ( !IS_PRIV_FOR(d, pt_owner) )
+        {
+            rc = -ESRCH;
+            goto out;
+        }
+    }
+
+    if ( !set_foreigndom((uint16_t)foreigndom) )
     {
         rc = -ESRCH;
         goto out;
@@ -3059,9 +3083,9 @@ int do_mmu_update(
 
             req.ptr -= cmd;
             gmfn = req.ptr >> PAGE_SHIFT;
-            mfn = gmfn_to_mfn(d, gmfn);
-
-            if ( unlikely(!get_page_from_pagenr(mfn, d)) )
+            mfn = gmfn_to_mfn(pt_owner, gmfn);
+
+            if ( unlikely(!get_page_from_pagenr(mfn, pt_owner)) )
             {
                 MEM_LOG("Could not get page for normal update");
                 break;
@@ -3080,24 +3104,21 @@ int do_mmu_update(
                 {
                     l1_pgentry_t l1e = l1e_from_intpte(req.val);
                     okay = mod_l1_entry(va, l1e, mfn,
-                                        cmd == MMU_PT_UPDATE_PRESERVE_AD,
-                                        current);
+                                        cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
                 }
                 break;
                 case PGT_l2_page_table:
                 {
                     l2_pgentry_t l2e = l2e_from_intpte(req.val);
                     okay = mod_l2_entry(va, l2e, mfn,
-                                        cmd == MMU_PT_UPDATE_PRESERVE_AD,
-                                        current);
+                                        cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
                 }
                 break;
                 case PGT_l3_page_table:
                 {
                     l3_pgentry_t l3e = l3e_from_intpte(req.val);
                     rc = mod_l3_entry(va, l3e, mfn,
-                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1,
-                                      current);
+                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
                     okay = !rc;
                 }
                 break;
@@ -3106,8 +3127,7 @@ int do_mmu_update(
                 {
                     l4_pgentry_t l4e = l4e_from_intpte(req.val);
                     rc = mod_l4_entry(va, l4e, mfn,
-                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1,
-                                      current);
+                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
                     okay = !rc;
                 }
                 break;
@@ -3115,7 +3135,7 @@ int do_mmu_update(
                 case PGT_writable_page:
                     perfc_incr(writable_mmu_updates);
                     okay = paging_write_guest_entry(
-                        current, va, req.val, _mfn(mfn));
+                        v, va, req.val, _mfn(mfn));
                     break;
                 }
                 page_unlock(page);
@@ -3126,7 +3146,7 @@ int do_mmu_update(
             {
                 perfc_incr(writable_mmu_updates);
                 okay = paging_write_guest_entry(
-                    current, va, req.val, _mfn(mfn));
+                    v, va, req.val, _mfn(mfn));
                 put_page_type(page);
             }
 
@@ -3191,6 +3211,9 @@ int do_mmu_update(
     perfc_add(num_page_updates, i);
 
  out:
+    if ( pt_owner && (pt_owner != d) )
+        rcu_unlock_domain(pt_owner);
+
     /* Add incremental work we have done to the @done output parameter. */
     if ( unlikely(!guest_handle_is_null(pdone)) )
     {
diff -r a29bb4efff00 -r 01ae7dc043ba xen/include/public/xen.h
--- a/xen/include/public/xen.h  Tue Jul 07 14:21:16 2009 +0100
+++ b/xen/include/public/xen.h  Tue Jul 07 14:38:59 2009 +0100
@@ -158,18 +158,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define NR_VIRQS       24
 
 /*
- * MMU-UPDATE REQUESTS
- * 
- * HYPERVISOR_mmu_update() accepts a list of (ptr, val) pairs.
- * A foreigndom (FD) can be specified (or DOMID_SELF for none).
- * Where the FD has some effect, it is described below.
- * ptr[1:0] specifies the appropriate MMU_* command.
- * 
+ * HYPERVISOR_mmu_update(reqs, count, pdone, foreigndom)
+ * 
+ * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
+ * @count is the length of the above array.
+ * @pdone is an output parameter indicating number of completed operations
+ * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
+ *                    hypercall invocation. Can be DOMID_SELF.
+ * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
+ *                     in this hypercall invocation. The value of this field
+ *                     (x) encodes the PFD as follows:
+ *                     x == 0 => PFD == DOMID_SELF
+ *                     x != 0 => PFD == x - 1
+ * 
+ * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
+ * -------------
  * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
- * Updates an entry in a page table. If updating an L1 table, and the new
- * table entry is valid/present, the mapped frame must belong to the FD, if
- * an FD has been specified. If attempting to map an I/O page then the
- * caller assumes the privilege of the FD.
+ * Updates an entry in a page table belonging to PFD. If updating an L1 table,
+ * and the new table entry is valid/present, the mapped frame must belong to
+ * FD. If attempting to map an I/O page then the caller assumes the privilege
+ * of the FD.
  * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
  * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
  * ptr[:2]  -- Machine address of the page-table entry to modify.

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


 


Rackspace

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