debuggers.hg

changeset 19946:01ae7dc043ba

x86: extend mmu_update hypercall to allow update of foreign pagetables.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 07 14:38:59 2009 +0100 (2009-07-07)
parents a29bb4efff00
children 797006dadc38
files xen/arch/x86/mm.c xen/include/public/xen.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Tue Jul 07 14:21:16 2009 +0100
     1.2 +++ b/xen/arch/x86/mm.c	Tue Jul 07 14:38:59 2009 +0100
     1.3 @@ -110,6 +110,7 @@
     1.4  #include <asm/hypercall.h>
     1.5  #include <asm/shared.h>
     1.6  #include <public/memory.h>
     1.7 +#include <public/sched.h>
     1.8  #include <xsm/xsm.h>
     1.9  #include <xen/trace.h>
    1.10  
    1.11 @@ -2999,8 +3000,9 @@ int do_mmu_update(
    1.12      unsigned long gpfn, gmfn, mfn;
    1.13      struct page_info *page;
    1.14      int rc = 0, okay = 1, i = 0;
    1.15 -    unsigned int cmd, done = 0;
    1.16 -    struct domain *d = current->domain;
    1.17 +    unsigned int cmd, done = 0, pt_dom;
    1.18 +    struct domain *d = current->domain, *pt_owner = d;
    1.19 +    struct vcpu *v = current;
    1.20      struct domain_mmap_cache mapcache;
    1.21  
    1.22      if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
    1.23 @@ -3018,7 +3020,29 @@ int do_mmu_update(
    1.24          goto out;
    1.25      }
    1.26  
    1.27 -    if ( !set_foreigndom(foreigndom) )
    1.28 +    if ( (pt_dom = foreigndom >> 16) != 0 )
    1.29 +    {
    1.30 +        /* Pagetables belong to a foreign domain (PFD). */
    1.31 +        if ( (pt_owner = rcu_lock_domain_by_id(pt_dom - 1)) == NULL )
    1.32 +        {
    1.33 +            rc = -EINVAL;
    1.34 +            goto out;
    1.35 +        }
    1.36 +        if ( pt_owner == d )
    1.37 +            rcu_unlock_domain(pt_owner);
    1.38 +        if ( (v = pt_owner->vcpu ? pt_owner->vcpu[0] : NULL) == NULL )
    1.39 +        {
    1.40 +            rc = -EINVAL;
    1.41 +            goto out;
    1.42 +        }
    1.43 +        if ( !IS_PRIV_FOR(d, pt_owner) )
    1.44 +        {
    1.45 +            rc = -ESRCH;
    1.46 +            goto out;
    1.47 +        }
    1.48 +    }
    1.49 +
    1.50 +    if ( !set_foreigndom((uint16_t)foreigndom) )
    1.51      {
    1.52          rc = -ESRCH;
    1.53          goto out;
    1.54 @@ -3059,9 +3083,9 @@ int do_mmu_update(
    1.55  
    1.56              req.ptr -= cmd;
    1.57              gmfn = req.ptr >> PAGE_SHIFT;
    1.58 -            mfn = gmfn_to_mfn(d, gmfn);
    1.59 -
    1.60 -            if ( unlikely(!get_page_from_pagenr(mfn, d)) )
    1.61 +            mfn = gmfn_to_mfn(pt_owner, gmfn);
    1.62 +
    1.63 +            if ( unlikely(!get_page_from_pagenr(mfn, pt_owner)) )
    1.64              {
    1.65                  MEM_LOG("Could not get page for normal update");
    1.66                  break;
    1.67 @@ -3080,24 +3104,21 @@ int do_mmu_update(
    1.68                  {
    1.69                      l1_pgentry_t l1e = l1e_from_intpte(req.val);
    1.70                      okay = mod_l1_entry(va, l1e, mfn,
    1.71 -                                        cmd == MMU_PT_UPDATE_PRESERVE_AD,
    1.72 -                                        current);
    1.73 +                                        cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
    1.74                  }
    1.75                  break;
    1.76                  case PGT_l2_page_table:
    1.77                  {
    1.78                      l2_pgentry_t l2e = l2e_from_intpte(req.val);
    1.79                      okay = mod_l2_entry(va, l2e, mfn,
    1.80 -                                        cmd == MMU_PT_UPDATE_PRESERVE_AD,
    1.81 -                                        current);
    1.82 +                                        cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
    1.83                  }
    1.84                  break;
    1.85                  case PGT_l3_page_table:
    1.86                  {
    1.87                      l3_pgentry_t l3e = l3e_from_intpte(req.val);
    1.88                      rc = mod_l3_entry(va, l3e, mfn,
    1.89 -                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1,
    1.90 -                                      current);
    1.91 +                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
    1.92                      okay = !rc;
    1.93                  }
    1.94                  break;
    1.95 @@ -3106,8 +3127,7 @@ int do_mmu_update(
    1.96                  {
    1.97                      l4_pgentry_t l4e = l4e_from_intpte(req.val);
    1.98                      rc = mod_l4_entry(va, l4e, mfn,
    1.99 -                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1,
   1.100 -                                      current);
   1.101 +                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
   1.102                      okay = !rc;
   1.103                  }
   1.104                  break;
   1.105 @@ -3115,7 +3135,7 @@ int do_mmu_update(
   1.106                  case PGT_writable_page:
   1.107                      perfc_incr(writable_mmu_updates);
   1.108                      okay = paging_write_guest_entry(
   1.109 -                        current, va, req.val, _mfn(mfn));
   1.110 +                        v, va, req.val, _mfn(mfn));
   1.111                      break;
   1.112                  }
   1.113                  page_unlock(page);
   1.114 @@ -3126,7 +3146,7 @@ int do_mmu_update(
   1.115              {
   1.116                  perfc_incr(writable_mmu_updates);
   1.117                  okay = paging_write_guest_entry(
   1.118 -                    current, va, req.val, _mfn(mfn));
   1.119 +                    v, va, req.val, _mfn(mfn));
   1.120                  put_page_type(page);
   1.121              }
   1.122  
   1.123 @@ -3191,6 +3211,9 @@ int do_mmu_update(
   1.124      perfc_add(num_page_updates, i);
   1.125  
   1.126   out:
   1.127 +    if ( pt_owner && (pt_owner != d) )
   1.128 +        rcu_unlock_domain(pt_owner);
   1.129 +
   1.130      /* Add incremental work we have done to the @done output parameter. */
   1.131      if ( unlikely(!guest_handle_is_null(pdone)) )
   1.132      {
     2.1 --- a/xen/include/public/xen.h	Tue Jul 07 14:21:16 2009 +0100
     2.2 +++ b/xen/include/public/xen.h	Tue Jul 07 14:38:59 2009 +0100
     2.3 @@ -158,18 +158,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
     2.4  #define NR_VIRQS       24
     2.5  
     2.6  /*
     2.7 - * MMU-UPDATE REQUESTS
     2.8 + * HYPERVISOR_mmu_update(reqs, count, pdone, foreigndom)
     2.9   * 
    2.10 - * HYPERVISOR_mmu_update() accepts a list of (ptr, val) pairs.
    2.11 - * A foreigndom (FD) can be specified (or DOMID_SELF for none).
    2.12 - * Where the FD has some effect, it is described below.
    2.13 - * ptr[1:0] specifies the appropriate MMU_* command.
    2.14 + * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
    2.15 + * @count is the length of the above array.
    2.16 + * @pdone is an output parameter indicating number of completed operations
    2.17 + * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
    2.18 + *                    hypercall invocation. Can be DOMID_SELF.
    2.19 + * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
    2.20 + *                     in this hypercall invocation. The value of this field
    2.21 + *                     (x) encodes the PFD as follows:
    2.22 + *                     x == 0 => PFD == DOMID_SELF
    2.23 + *                     x != 0 => PFD == x - 1
    2.24   * 
    2.25 + * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
    2.26 + * -------------
    2.27   * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
    2.28 - * Updates an entry in a page table. If updating an L1 table, and the new
    2.29 - * table entry is valid/present, the mapped frame must belong to the FD, if
    2.30 - * an FD has been specified. If attempting to map an I/O page then the
    2.31 - * caller assumes the privilege of the FD.
    2.32 + * Updates an entry in a page table belonging to PFD. If updating an L1 table,
    2.33 + * and the new table entry is valid/present, the mapped frame must belong to
    2.34 + * FD. If attempting to map an I/O page then the caller assumes the privilege
    2.35 + * of the FD.
    2.36   * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
    2.37   * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
    2.38   * ptr[:2]  -- Machine address of the page-table entry to modify.