ia64/xen-unstable

changeset 19708:c4b048ce6a4b

x86: Clean up get_page_from_l1e() to correctly distinguish between
owner-of-pte and owner-of-data-page in all cases.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 03 14:40:34 2009 +0100 (2009-06-03)
parents 07cf79dfb59c
children 011948e1b5a7
files xen/arch/x86/mm.c xen/arch/x86/mm/shadow/multi.c xen/include/asm-x86/mm.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Wed Jun 03 12:59:44 2009 +0100
     1.2 +++ b/xen/arch/x86/mm.c	Wed Jun 03 14:40:34 2009 +0100
     1.3 @@ -726,66 +726,69 @@ static void update_xen_mappings(unsigned
     1.4  #endif
     1.5  }
     1.6  
     1.7 -
     1.8  int
     1.9  get_page_from_l1e(
    1.10 -    l1_pgentry_t l1e, struct domain *d)
    1.11 +    l1_pgentry_t l1e, struct domain *l1e_owner, struct domain *pg_owner)
    1.12  {
    1.13      unsigned long mfn = l1e_get_pfn(l1e);
    1.14      struct page_info *page = mfn_to_page(mfn);
    1.15      uint32_t l1f = l1e_get_flags(l1e);
    1.16      struct vcpu *curr = current;
    1.17 -    struct domain *owner;
    1.18 +    struct domain *real_pg_owner;
    1.19  
    1.20      if ( !(l1f & _PAGE_PRESENT) )
    1.21          return 1;
    1.22  
    1.23 -    if ( unlikely(l1f & l1_disallow_mask(d)) )
    1.24 +    if ( unlikely(l1f & l1_disallow_mask(l1e_owner)) )
    1.25      {
    1.26 -        MEM_LOG("Bad L1 flags %x", l1f & l1_disallow_mask(d));
    1.27 +        MEM_LOG("Bad L1 flags %x", l1f & l1_disallow_mask(l1e_owner));
    1.28          return 0;
    1.29      }
    1.30  
    1.31      if ( !mfn_valid(mfn) ||
    1.32 -         (owner = page_get_owner_and_reference(page)) == dom_io )
    1.33 +         (real_pg_owner = page_get_owner_and_reference(page)) == dom_io )
    1.34      {
    1.35          /* Only needed the reference to confirm dom_io ownership. */
    1.36          if ( mfn_valid(mfn) )
    1.37              put_page(page);
    1.38  
    1.39          /* DOMID_IO reverts to caller for privilege checks. */
    1.40 -        if ( d == dom_io )
    1.41 -            d = curr->domain;
    1.42 -
    1.43 -        if ( !iomem_access_permitted(d, mfn, mfn) )
    1.44 +        if ( pg_owner == dom_io )
    1.45 +            pg_owner = curr->domain;
    1.46 +
    1.47 +        if ( !iomem_access_permitted(pg_owner, mfn, mfn) )
    1.48          {
    1.49              if ( mfn != (PADDR_MASK >> PAGE_SHIFT) ) /* INVALID_MFN? */
    1.50                  MEM_LOG("Non-privileged (%u) attempt to map I/O space %08lx", 
    1.51 -                        d->domain_id, mfn);
    1.52 +                        pg_owner->domain_id, mfn);
    1.53              return 0;
    1.54          }
    1.55  
    1.56          return 1;
    1.57      }
    1.58  
    1.59 -    if ( owner == NULL )
    1.60 +    if ( real_pg_owner == NULL )
    1.61          goto could_not_pin;
    1.62  
    1.63 -    /*
    1.64 -     * Let privileged domains transfer the right to map their target
    1.65 -     * domain's pages. This is used to allow stub-domain pvfb export to dom0,
    1.66 -     * until pvfb supports granted mappings. At that time this minor hack
    1.67 -     * can go away.
    1.68 -     */
    1.69 -    if ( unlikely(d != owner) && (d != curr->domain) && IS_PRIV_FOR(d, owner) )
    1.70 -        d = owner;
    1.71 +    if ( unlikely(real_pg_owner != pg_owner) )
    1.72 +    {
    1.73 +        /*
    1.74 +         * Let privileged domains transfer the right to map their target
    1.75 +         * domain's pages. This is used to allow stub-domain pvfb export to
    1.76 +         * dom0, until pvfb supports granted mappings. At that time this
    1.77 +         * minor hack can go away.
    1.78 +         */
    1.79 +        if ( (pg_owner == l1e_owner) || !IS_PRIV_FOR(pg_owner, real_pg_owner) )
    1.80 +            goto could_not_pin;
    1.81 +        pg_owner = real_pg_owner;
    1.82 +    }
    1.83  
    1.84      /* Foreign mappings into guests in shadow external mode don't
    1.85       * contribute to writeable mapping refcounts.  (This allows the
    1.86       * qemu-dm helper process in dom0 to map the domain's memory without
    1.87       * messing up the count of "real" writable mappings.) */
    1.88      if ( (l1f & _PAGE_RW) &&
    1.89 -         !(paging_mode_external(d) && (d != curr->domain)) &&
    1.90 +         ((l1e_owner == pg_owner) || !paging_mode_external(pg_owner)) &&
    1.91           !get_page_type(page, PGT_writable_page) )
    1.92          goto could_not_pin;
    1.93  
    1.94 @@ -798,8 +801,7 @@ get_page_from_l1e(
    1.95          if ( is_xen_heap_page(page) )
    1.96          {
    1.97              if ( (l1f & _PAGE_RW) &&
    1.98 -                 !(unlikely(paging_mode_external(d) &&
    1.99 -                            (d != curr->domain))) )
   1.100 +                 ((l1e_owner == pg_owner) || !paging_mode_external(pg_owner)) )
   1.101                  put_page_type(page);
   1.102              put_page(page);
   1.103              MEM_LOG("Attempt to change cache attributes of Xen heap page");
   1.104 @@ -820,10 +822,10 @@ get_page_from_l1e(
   1.105  
   1.106   could_not_pin:
   1.107      MEM_LOG("Error getting mfn %lx (pfn %lx) from L1 entry %" PRIpte
   1.108 -            " for dom%d",
   1.109 +            " for l1e_owner=%d, pg_owner=%d",
   1.110              mfn, get_gpfn_from_mfn(mfn),
   1.111 -            l1e_get_intpte(l1e), d->domain_id);
   1.112 -    if ( owner != NULL )
   1.113 +            l1e_get_intpte(l1e), l1e_owner->domain_id, pg_owner->domain_id);
   1.114 +    if ( real_pg_owner != NULL )
   1.115          put_page(page);
   1.116      return 0;
   1.117  }
   1.118 @@ -996,19 +998,18 @@ get_page_from_l4e(
   1.119  #define unadjust_guest_l3e(_p, _d) ((void)(_d))
   1.120  #endif
   1.121  
   1.122 -void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
   1.123 +void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
   1.124  {
   1.125      unsigned long     pfn = l1e_get_pfn(l1e);
   1.126      struct page_info *page;
   1.127 -    struct domain    *e;
   1.128 +    struct domain    *pg_owner;
   1.129      struct vcpu      *v;
   1.130  
   1.131      if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || is_iomem_page(pfn) )
   1.132          return;
   1.133  
   1.134      page = mfn_to_page(pfn);
   1.135 -
   1.136 -    e = page_get_owner(page);
   1.137 +    pg_owner = page_get_owner(page);
   1.138  
   1.139      /*
   1.140       * Check if this is a mapping that was established via a grant reference.
   1.141 @@ -1024,17 +1025,17 @@ void put_page_from_l1e(l1_pgentry_t l1e,
   1.142       * Xen. All active grants can safely be cleaned up when the domain dies.)
   1.143       */
   1.144      if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) &&
   1.145 -         !d->is_shutting_down && !d->is_dying )
   1.146 +         !l1e_owner->is_shutting_down && !l1e_owner->is_dying )
   1.147      {
   1.148          MEM_LOG("Attempt to implicitly unmap a granted PTE %" PRIpte,
   1.149                  l1e_get_intpte(l1e));
   1.150 -        domain_crash(d);
   1.151 +        domain_crash(l1e_owner);
   1.152      }
   1.153  
   1.154      /* Remember we didn't take a type-count of foreign writable mappings
   1.155       * to paging-external domains */
   1.156      if ( (l1e_get_flags(l1e) & _PAGE_RW) && 
   1.157 -         !(unlikely((e != d) && paging_mode_external(e))) )
   1.158 +         ((l1e_owner == pg_owner) || !paging_mode_external(pg_owner)) )
   1.159      {
   1.160          put_page_and_type(page);
   1.161      }
   1.162 @@ -1044,9 +1045,9 @@ void put_page_from_l1e(l1_pgentry_t l1e,
   1.163          if ( unlikely(((page->u.inuse.type_info & PGT_type_mask) == 
   1.164                         PGT_seg_desc_page)) &&
   1.165               unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) &&
   1.166 -             (d == e) )
   1.167 +             (l1e_owner == pg_owner) )
   1.168          {
   1.169 -            for_each_vcpu ( d, v )
   1.170 +            for_each_vcpu ( pg_owner, v )
   1.171                  invalidate_shadow_ldt(v, 1);
   1.172          }
   1.173          put_page(page);
   1.174 @@ -1137,7 +1138,7 @@ static int alloc_l1_table(struct page_in
   1.175      for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
   1.176      {
   1.177          if ( is_guest_l1_slot(i) &&
   1.178 -             unlikely(!get_page_from_l1e(pl1e[i], d)) )
   1.179 +             unlikely(!get_page_from_l1e(pl1e[i], d, d)) )
   1.180              goto fail;
   1.181  
   1.182          adjust_guest_l1e(pl1e[i], d);
   1.183 @@ -1716,7 +1717,7 @@ static int mod_l1_entry(l1_pgentry_t *pl
   1.184              return rc;
   1.185          }
   1.186  
   1.187 -        if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) )
   1.188 +        if ( unlikely(!get_page_from_l1e(nl1e, d, FOREIGNDOM)) )
   1.189              return 0;
   1.190          
   1.191          adjust_guest_l1e(nl1e, d);
   1.192 @@ -4224,7 +4225,7 @@ static int ptwr_emulated_update(
   1.193  
   1.194      /* Check the new PTE. */
   1.195      nl1e = l1e_from_intpte(val);
   1.196 -    if ( unlikely(!get_page_from_l1e(nl1e, d)) )
   1.197 +    if ( unlikely(!get_page_from_l1e(nl1e, d, d)) )
   1.198      {
   1.199          if ( is_pv_32bit_domain(d) && (bytes == 4) && (unaligned_addr & 4) &&
   1.200               !do_cmpxchg && (l1e_get_flags(nl1e) & _PAGE_PRESENT) )
     2.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Jun 03 12:59:44 2009 +0100
     2.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Jun 03 14:40:34 2009 +0100
     2.3 @@ -816,7 +816,7 @@ shadow_get_page_from_l1e(shadow_l1e_t sl
     2.4      if ( !shadow_mode_refcounts(d) )
     2.5          return 1;
     2.6  
     2.7 -    res = get_page_from_l1e(sl1e, d);
     2.8 +    res = get_page_from_l1e(sl1e, d, d);
     2.9  
    2.10      // If a privileged domain is attempting to install a map of a page it does
    2.11      // not own, we let it succeed anyway.
    2.12 @@ -828,7 +828,7 @@ shadow_get_page_from_l1e(shadow_l1e_t sl
    2.13           (d != owner) &&
    2.14           IS_PRIV_FOR(d, owner))
    2.15      {
    2.16 -        res = get_page_from_l1e(sl1e, owner);
    2.17 +        res = get_page_from_l1e(sl1e, d, owner);
    2.18          SHADOW_PRINTK("privileged domain %d installs map of mfn %05lx "
    2.19                         "which is owned by domain %d: %s\n",
    2.20                         d->domain_id, mfn_x(mfn), owner->domain_id,
     3.1 --- a/xen/include/asm-x86/mm.h	Wed Jun 03 12:59:44 2009 +0100
     3.2 +++ b/xen/include/asm-x86/mm.h	Wed Jun 03 14:40:34 2009 +0100
     3.3 @@ -285,8 +285,9 @@ void put_page_type(struct page_info *pag
     3.4  int  get_page_type(struct page_info *page, unsigned long type);
     3.5  int  put_page_type_preemptible(struct page_info *page);
     3.6  int  get_page_type_preemptible(struct page_info *page, unsigned long type);
     3.7 -int  get_page_from_l1e(l1_pgentry_t l1e, struct domain *d);
     3.8 -void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d);
     3.9 +int  get_page_from_l1e(
    3.10 +    l1_pgentry_t l1e, struct domain *l1e_owner, struct domain *pg_owner);
    3.11 +void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner);
    3.12  
    3.13  static inline void put_page_and_type(struct page_info *page)
    3.14  {