ia64/xen-unstable

changeset 12563:47a8bb3cd123

[XEN] Don't call domain_crash_synchronous() with shadow lock held.
Call domain_crash() and propagate an error to the caller instead.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Thu Nov 23 17:44:12 2006 +0000 (2006-11-23)
parents 7a38b70788a5
children 2fd223c64fc6
files xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/mm/shadow/private.h xen/include/asm-x86/shadow.h
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/common.c	Thu Nov 23 17:42:29 2006 +0000
     1.2 +++ b/xen/arch/x86/mm/shadow/common.c	Thu Nov 23 17:44:12 2006 +0000
     1.3 @@ -791,6 +791,7 @@ shadow_alloc_p2m_page(struct domain *d)
     1.4      struct list_head *entry;
     1.5      mfn_t mfn;
     1.6      void *p;
     1.7 +    int ok;
     1.8  
     1.9      if ( list_empty(&d->arch.shadow.p2m_freelist) &&
    1.10           !shadow_alloc_p2m_pages(d) )
    1.11 @@ -799,7 +800,8 @@ shadow_alloc_p2m_page(struct domain *d)
    1.12      list_del(entry);
    1.13      list_add_tail(entry, &d->arch.shadow.p2m_inuse);
    1.14      mfn = page_to_mfn(list_entry(entry, struct page_info, list));
    1.15 -    sh_get_ref(mfn, 0);
    1.16 +    ok = sh_get_ref(mfn, 0);
    1.17 +    ASSERT(ok); /* First sh_get_ref() can't possibly overflow */
    1.18      p = sh_map_domain_page(mfn);
    1.19      clear_page(p);
    1.20      sh_unmap_domain_page(p);
     2.1 --- a/xen/arch/x86/mm/shadow/multi.c	Thu Nov 23 17:42:29 2006 +0000
     2.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Nov 23 17:44:12 2006 +0000
     2.3 @@ -832,12 +832,6 @@ l1e_propagate_from_guest(struct vcpu *v,
     2.4  /* These functions update shadow entries (and do bookkeeping on the shadow
     2.5   * tables they are in).  It is intended that they are the only
     2.6   * functions which ever write (non-zero) data onto a shadow page.
     2.7 - *
     2.8 - * They return a set of flags: 
     2.9 - * SHADOW_SET_CHANGED -- we actually wrote a new value to the shadow.
    2.10 - * SHADOW_SET_FLUSH   -- the caller must cause a TLB flush.
    2.11 - * SHADOW_SET_ERROR   -- the input is not a valid entry (for example, if
    2.12 - *                        shadow_get_page_from_l1e() fails).
    2.13   */
    2.14  
    2.15  static inline void safe_write_entry(void *dst, void *src) 
    2.16 @@ -982,10 +976,12 @@ static int shadow_set_l4e(struct vcpu *v
    2.17               | (((unsigned long)sl4e) & ~PAGE_MASK));
    2.18  
    2.19      if ( shadow_l4e_get_flags(new_sl4e) & _PAGE_PRESENT ) 
    2.20 -    {
    2.21          /* About to install a new reference */        
    2.22 -        sh_get_ref(shadow_l4e_get_mfn(new_sl4e), paddr);
    2.23 -    } 
    2.24 +        if ( !sh_get_ref(shadow_l4e_get_mfn(new_sl4e), paddr) )
    2.25 +        {
    2.26 +            domain_crash(v->domain);
    2.27 +            return SHADOW_SET_ERROR;
    2.28 +        }
    2.29  
    2.30      /* Write the new entry */
    2.31      shadow_write_entries(sl4e, &new_sl4e, 1, sl4mfn);
    2.32 @@ -1022,11 +1018,13 @@ static int shadow_set_l3e(struct vcpu *v
    2.33      paddr = ((((paddr_t)mfn_x(sl3mfn)) << PAGE_SHIFT) 
    2.34               | (((unsigned long)sl3e) & ~PAGE_MASK));
    2.35      
    2.36 -    if ( shadow_l3e_get_flags(new_sl3e) & _PAGE_PRESENT ) 
    2.37 -    {
    2.38 +    if ( shadow_l3e_get_flags(new_sl3e) & _PAGE_PRESENT )
    2.39          /* About to install a new reference */        
    2.40 -        sh_get_ref(shadow_l3e_get_mfn(new_sl3e), paddr);
    2.41 -    } 
    2.42 +        if ( !sh_get_ref(shadow_l3e_get_mfn(new_sl3e), paddr) )
    2.43 +        {
    2.44 +            domain_crash(v->domain);
    2.45 +            return SHADOW_SET_ERROR;
    2.46 +        } 
    2.47  
    2.48      /* Write the new entry */
    2.49      shadow_write_entries(sl3e, &new_sl3e, 1, sl3mfn);
    2.50 @@ -1077,10 +1075,12 @@ static int shadow_set_l2e(struct vcpu *v
    2.51               | (((unsigned long)sl2e) & ~PAGE_MASK));
    2.52  
    2.53      if ( shadow_l2e_get_flags(new_sl2e) & _PAGE_PRESENT ) 
    2.54 -    {
    2.55          /* About to install a new reference */
    2.56 -        sh_get_ref(shadow_l2e_get_mfn(new_sl2e), paddr);
    2.57 -    } 
    2.58 +        if ( !sh_get_ref(shadow_l2e_get_mfn(new_sl2e), paddr) )
    2.59 +        {
    2.60 +            domain_crash(v->domain);
    2.61 +            return SHADOW_SET_ERROR;
    2.62 +        } 
    2.63  
    2.64      /* Write the new entry */
    2.65  #if GUEST_PAGING_LEVELS == 2 && SHADOW_PAGING_LEVELS > 2
    2.66 @@ -1727,6 +1727,8 @@ static shadow_l3e_t * shadow_get_and_cre
    2.67                                   *sl3mfn, &new_sl4e, ft);
    2.68          r = shadow_set_l4e(v, sl4e, new_sl4e, sl4mfn);
    2.69          ASSERT((r & SHADOW_SET_FLUSH) == 0);
    2.70 +        if ( r & SHADOW_SET_ERROR )
    2.71 +            return NULL;
    2.72      }
    2.73      /* Now follow it down a level.  Guaranteed to succeed. */
    2.74      return sh_linear_l3_table(v) + shadow_l3_linear_offset(gw->va);
    2.75 @@ -1745,7 +1747,7 @@ static shadow_l2e_t * shadow_get_and_cre
    2.76      if ( !valid_mfn(gw->l2mfn) ) return NULL; /* No guest page. */
    2.77      /* Get the l3e */
    2.78      sl3e = shadow_get_and_create_l3e(v, gw, &sl3mfn, ft);
    2.79 -    ASSERT(sl3e != NULL);  /* Since we know guest PT is valid this far */
    2.80 +    if ( sl3e == NULL ) return NULL; 
    2.81      if ( shadow_l3e_get_flags(*sl3e) & _PAGE_PRESENT ) 
    2.82      {
    2.83          *sl2mfn = shadow_l3e_get_mfn(*sl3e);
    2.84 @@ -1767,6 +1769,8 @@ static shadow_l2e_t * shadow_get_and_cre
    2.85                                   *sl2mfn, &new_sl3e, ft);
    2.86          r = shadow_set_l3e(v, sl3e, new_sl3e, sl3mfn);
    2.87          ASSERT((r & SHADOW_SET_FLUSH) == 0);
    2.88 +        if ( r & SHADOW_SET_ERROR )
    2.89 +            return NULL;        
    2.90      }
    2.91      /* Now follow it down a level.  Guaranteed to succeed. */
    2.92      return sh_linear_l2_table(v) + shadow_l2_linear_offset(gw->va);
    2.93 @@ -1848,6 +1852,8 @@ static shadow_l1e_t * shadow_get_and_cre
    2.94                                   *sl1mfn, &new_sl2e, ft);
    2.95          r = shadow_set_l2e(v, sl2e, new_sl2e, sl2mfn);
    2.96          ASSERT((r & SHADOW_SET_FLUSH) == 0);        
    2.97 +        if ( r & SHADOW_SET_ERROR )
    2.98 +            return NULL;
    2.99          /* This next line is important: in 32-on-PAE and 32-on-64 modes,
   2.100           * the guest l1 table has an 8k shadow, and we need to return
   2.101           * the right mfn of the pair. This call will set it for us as a
   2.102 @@ -2711,10 +2717,17 @@ static int sh_page_fault(struct vcpu *v,
   2.103  
   2.104      /* Acquire the shadow.  This must happen before we figure out the rights 
   2.105       * for the shadow entry, since we might promote a page here. */
   2.106 -    // XXX -- this code will need to change somewhat if/when the shadow code
   2.107 -    // can directly map superpages...
   2.108      ptr_sl1e = shadow_get_and_create_l1e(v, &gw, &sl1mfn, ft);
   2.109 -    ASSERT(ptr_sl1e);
   2.110 +    if ( unlikely(ptr_sl1e == NULL) ) 
   2.111 +    {
   2.112 +        /* Couldn't get the sl1e!  Since we know the guest entries
   2.113 +         * are OK, this can only have been caused by a failed
   2.114 +         * shadow_set_l*e(), which will have crashed the guest.  
   2.115 +         * Get out of the fault handler immediately. */
   2.116 +        ASSERT(test_bit(_DOMF_dying, &d->domain_flags));
   2.117 +        shadow_unlock(d);
   2.118 +        return 0;
   2.119 +    }
   2.120  
   2.121      /* Calculate the shadow entry and write it */
   2.122      l1e_propagate_from_guest(v, (gw.l1e) ? gw.l1e : &gw.eff_l1e, gw.l1mfn, 
   2.123 @@ -3265,10 +3278,9 @@ sh_set_toplevel_shadow(struct vcpu *v,
   2.124      smfn = get_shadow_status(v, gmfn, root_type);
   2.125      if ( valid_mfn(smfn) )
   2.126      {
   2.127 -        /* Pull this root shadow to the front of the list of roots. */
   2.128 -        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
   2.129 -        list_del(&sp->list);
   2.130 -        list_add(&sp->list, &d->arch.shadow.toplevel_shadows);
   2.131 +        /* Pull this root shadow out of the list of roots (we will put
   2.132 +         * it back in at the head). */
   2.133 +        list_del(&mfn_to_shadow_page(smfn)->list);
   2.134      }
   2.135      else
   2.136      {
   2.137 @@ -3276,8 +3288,6 @@ sh_set_toplevel_shadow(struct vcpu *v,
   2.138          shadow_prealloc(d, SHADOW_MAX_ORDER); 
   2.139          /* Shadow the page. */
   2.140          smfn = sh_make_shadow(v, gmfn, root_type);
   2.141 -        list_add(&mfn_to_shadow_page(smfn)->list, 
   2.142 -                 &d->arch.shadow.toplevel_shadows);
   2.143      }
   2.144      ASSERT(valid_mfn(smfn));
   2.145      
   2.146 @@ -3287,10 +3297,22 @@ sh_set_toplevel_shadow(struct vcpu *v,
   2.147      mfn_to_page(gmfn)->shadow_flags &= ~SHF_unhooked_mappings;
   2.148  #endif
   2.149  
   2.150 -    /* Take a ref to this page: it will be released in sh_detach_old_tables()
   2.151 -     * or in the next call to sh_set_toplevel_shadow(). */
   2.152 -    sh_get_ref(smfn, 0);
   2.153 -    sh_pin(smfn);
   2.154 +    /* Pin the shadow and put it (back) on the list of top-level shadows */
   2.155 +    if ( sh_pin(smfn) )
   2.156 +        list_add(&mfn_to_shadow_page(smfn)->list, 
   2.157 +                 &d->arch.shadow.toplevel_shadows);
   2.158 +    else 
   2.159 +    {
   2.160 +        SHADOW_ERROR("can't pin %#lx as toplevel shadow\n", mfn_x(smfn));
   2.161 +        domain_crash(v->domain);
   2.162 +    }        
   2.163 +
   2.164 +    /* Take a ref to this page: it will be released in sh_detach_old_tables. */
   2.165 +    if ( !sh_get_ref(smfn, 0) )
   2.166 +    {
   2.167 +        SHADOW_ERROR("can't install %#lx as toplevel shadow\n", mfn_x(smfn));
   2.168 +        domain_crash(v->domain);
   2.169 +    }
   2.170  
   2.171      /* Done.  Install it */
   2.172      SHADOW_PRINTK("%u/%u [%u] gmfn %#"SH_PRI_mfn" smfn %#"SH_PRI_mfn"\n",
   2.173 @@ -3559,7 +3581,7 @@ static int sh_guess_wrmap(struct vcpu *v
   2.174  #endif
   2.175  #endif
   2.176      mfn_t sl1mfn;
   2.177 -
   2.178 +    int r;
   2.179  
   2.180      /* Carefully look in the shadow linear map for the l1e we expect */
   2.181  #if SHADOW_PAGING_LEVELS >= 4
   2.182 @@ -3588,7 +3610,8 @@ static int sh_guess_wrmap(struct vcpu *v
   2.183      /* Found it!  Need to remove its write permissions. */
   2.184      sl1mfn = shadow_l2e_get_mfn(*sl2p);
   2.185      sl1e = shadow_l1e_remove_flags(sl1e, _PAGE_RW);
   2.186 -    shadow_set_l1e(v, sl1p, sl1e, sl1mfn);
   2.187 +    r = shadow_set_l1e(v, sl1p, sl1e, sl1mfn);
   2.188 +    ASSERT( !(r & SHADOW_SET_ERROR) );
   2.189      return 1;
   2.190  }
   2.191  #endif
   2.192 @@ -3608,7 +3631,7 @@ int sh_remove_write_access(struct vcpu *
   2.193               && (flags & _PAGE_RW) 
   2.194               && (mfn_x(shadow_l1e_get_mfn(*sl1e)) == mfn_x(readonly_mfn)) )
   2.195          {
   2.196 -            shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
   2.197 +            (void) shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
   2.198  #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC 
   2.199              /* Remember the last shadow that we shot a writeable mapping in */
   2.200              v->arch.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn);
   2.201 @@ -3636,7 +3659,7 @@ int sh_remove_all_mappings(struct vcpu *
   2.202          if ( (flags & _PAGE_PRESENT) 
   2.203               && (mfn_x(shadow_l1e_get_mfn(*sl1e)) == mfn_x(target_mfn)) )
   2.204          {
   2.205 -            shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
   2.206 +            (void) shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
   2.207              if ( (mfn_to_page(target_mfn)->count_info & PGC_count_mask) == 0 )
   2.208                  /* This breaks us cleanly out of the FOREACH macro */
   2.209                  done = 1;
   2.210 @@ -3654,17 +3677,17 @@ void sh_clear_shadow_entry(struct vcpu *
   2.211      switch ( mfn_to_shadow_page(smfn)->type )
   2.212      {
   2.213      case SH_type_l1_shadow:
   2.214 -        shadow_set_l1e(v, ep, shadow_l1e_empty(), smfn); break;
   2.215 +        (void) shadow_set_l1e(v, ep, shadow_l1e_empty(), smfn); break;
   2.216      case SH_type_l2_shadow:
   2.217  #if GUEST_PAGING_LEVELS == 3
   2.218      case SH_type_l2h_shadow:
   2.219  #endif
   2.220 -        shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn); break;
   2.221 +        (void) shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn); break;
   2.222  #if GUEST_PAGING_LEVELS >= 4
   2.223      case SH_type_l3_shadow:
   2.224 -        shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn); break;
   2.225 +        (void) shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn); break;
   2.226      case SH_type_l4_shadow:
   2.227 -        shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn); break;
   2.228 +        (void) shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn); break;
   2.229  #endif
   2.230      default: BUG(); /* Called with the wrong kind of shadow. */
   2.231      }
   2.232 @@ -3686,7 +3709,7 @@ int sh_remove_l1_shadow(struct vcpu *v, 
   2.233          if ( (flags & _PAGE_PRESENT) 
   2.234               && (mfn_x(shadow_l2e_get_mfn(*sl2e)) == mfn_x(sl1mfn)) )
   2.235          {
   2.236 -            shadow_set_l2e(v, sl2e, shadow_l2e_empty(), sl2mfn);
   2.237 +            (void) shadow_set_l2e(v, sl2e, shadow_l2e_empty(), sl2mfn);
   2.238              if ( mfn_to_shadow_page(sl1mfn)->type == 0 )
   2.239                  /* This breaks us cleanly out of the FOREACH macro */
   2.240                  done = 1;
   2.241 @@ -3709,7 +3732,7 @@ int sh_remove_l2_shadow(struct vcpu *v, 
   2.242          if ( (flags & _PAGE_PRESENT) 
   2.243               && (mfn_x(shadow_l3e_get_mfn(*sl3e)) == mfn_x(sl2mfn)) )
   2.244          {
   2.245 -            shadow_set_l3e(v, sl3e, shadow_l3e_empty(), sl3mfn);
   2.246 +            (void) shadow_set_l3e(v, sl3e, shadow_l3e_empty(), sl3mfn);
   2.247              if ( mfn_to_shadow_page(sl2mfn)->type == 0 )
   2.248                  /* This breaks us cleanly out of the FOREACH macro */
   2.249                  done = 1;
   2.250 @@ -3731,7 +3754,7 @@ int sh_remove_l3_shadow(struct vcpu *v, 
   2.251          if ( (flags & _PAGE_PRESENT) 
   2.252               && (mfn_x(shadow_l4e_get_mfn(*sl4e)) == mfn_x(sl3mfn)) )
   2.253          {
   2.254 -            shadow_set_l4e(v, sl4e, shadow_l4e_empty(), sl4mfn);
   2.255 +            (void) shadow_set_l4e(v, sl4e, shadow_l4e_empty(), sl4mfn);
   2.256              if ( mfn_to_shadow_page(sl3mfn)->type == 0 )
   2.257                  /* This breaks us cleanly out of the FOREACH macro */
   2.258                  done = 1;
     3.1 --- a/xen/arch/x86/mm/shadow/private.h	Thu Nov 23 17:42:29 2006 +0000
     3.2 +++ b/xen/arch/x86/mm/shadow/private.h	Thu Nov 23 17:44:12 2006 +0000
     3.3 @@ -260,6 +260,18 @@ void sh_install_xen_entries_in_l2(struct
     3.4  
     3.5  
     3.6  /******************************************************************************
     3.7 + * Flags used in the return value of the shadow_set_lXe() functions...
     3.8 + */
     3.9 +
    3.10 +/* We actually wrote something new to the shadow */
    3.11 +#define SHADOW_SET_CHANGED            0x1
    3.12 +/* Caller should flush TLBs to clear the old entry */
    3.13 +#define SHADOW_SET_FLUSH              0x2
    3.14 +/* Something went wrong: the shadow entry was invalid or refcount failed */
    3.15 +#define SHADOW_SET_ERROR              0x4
    3.16 +
    3.17 +
    3.18 +/******************************************************************************
    3.19   * MFN/page-info handling 
    3.20   */
    3.21  
    3.22 @@ -350,8 +362,9 @@ void sh_destroy_shadow(struct vcpu *v, m
    3.23  
    3.24  /* Increase the refcount of a shadow page.  Arguments are the mfn to refcount, 
    3.25   * and the physical address of the shadow entry that holds the ref (or zero
    3.26 - * if the ref is held by something else) */
    3.27 -static inline void sh_get_ref(mfn_t smfn, paddr_t entry_pa)
    3.28 + * if the ref is held by something else).  
    3.29 + * Returns 0 for failure, 1 for success. */
    3.30 +static inline int sh_get_ref(mfn_t smfn, paddr_t entry_pa)
    3.31  {
    3.32      u32 x, nx;
    3.33      struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
    3.34 @@ -365,7 +378,7 @@ static inline void sh_get_ref(mfn_t smfn
    3.35      {
    3.36          SHADOW_PRINTK("shadow ref overflow, gmfn=%" PRtype_info " smfn=%lx\n",
    3.37                         sp->backpointer, mfn_x(smfn));
    3.38 -        domain_crash_synchronous();
    3.39 +        return 0;
    3.40      }
    3.41      
    3.42      /* Guarded by the shadow lock, so no need for atomic update */
    3.43 @@ -374,6 +387,8 @@ static inline void sh_get_ref(mfn_t smfn
    3.44      /* We remember the first shadow entry that points to each shadow. */
    3.45      if ( entry_pa != 0 && sp->up == 0 ) 
    3.46          sp->up = entry_pa;
    3.47 +    
    3.48 +    return 1;
    3.49  }
    3.50  
    3.51  
    3.52 @@ -396,9 +411,9 @@ static inline void sh_put_ref(struct vcp
    3.53  
    3.54      if ( unlikely(x == 0) ) 
    3.55      {
    3.56 -        SHADOW_PRINTK("shadow ref underflow, smfn=%lx oc=%08x t=%#x\n",
    3.57 -                      mfn_x(smfn), sp->count, sp->type);
    3.58 -        domain_crash_synchronous();
    3.59 +        SHADOW_ERROR("shadow ref underflow, smfn=%lx oc=%08x t=%#x\n",
    3.60 +                     mfn_x(smfn), sp->count, sp->type);
    3.61 +        BUG();
    3.62      }
    3.63  
    3.64      /* Guarded by the shadow lock, so no need for atomic update */
    3.65 @@ -409,8 +424,9 @@ static inline void sh_put_ref(struct vcp
    3.66  }
    3.67  
    3.68  
    3.69 -/* Pin a shadow page: take an extra refcount and set the pin bit. */
    3.70 -static inline void sh_pin(mfn_t smfn)
    3.71 +/* Pin a shadow page: take an extra refcount and set the pin bit.
    3.72 + * Returns 0 for failure, 1 for success. */
    3.73 +static inline int sh_pin(mfn_t smfn)
    3.74  {
    3.75      struct shadow_page_info *sp;
    3.76      
    3.77 @@ -418,9 +434,11 @@ static inline void sh_pin(mfn_t smfn)
    3.78      sp = mfn_to_shadow_page(smfn);
    3.79      if ( !(sp->pinned) ) 
    3.80      {
    3.81 -        sh_get_ref(smfn, 0);
    3.82 +        if ( !sh_get_ref(smfn, 0) )
    3.83 +            return 0;
    3.84          sp->pinned = 1;
    3.85      }
    3.86 +    return 1;
    3.87  }
    3.88  
    3.89  /* Unpin a shadow page: unset the pin bit and release the extra ref. */
     4.1 --- a/xen/include/asm-x86/shadow.h	Thu Nov 23 17:42:29 2006 +0000
     4.2 +++ b/xen/include/asm-x86/shadow.h	Thu Nov 23 17:44:12 2006 +0000
     4.3 @@ -68,11 +68,6 @@
     4.4   */
     4.5  #define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; })
     4.6  
     4.7 -// flags used in the return value of the shadow_set_lXe() functions...
     4.8 -#define SHADOW_SET_CHANGED            0x1
     4.9 -#define SHADOW_SET_FLUSH              0x2
    4.10 -#define SHADOW_SET_ERROR              0x4
    4.11 -
    4.12  // How do we tell that we have a 32-bit PV guest in a 64-bit Xen?
    4.13  #ifdef __x86_64__
    4.14  #define pv_32bit_guest(_v) 0 // not yet supported