ia64/xen-unstable

changeset 4154:6b80eefad546

bitkeeper revision 1.1236.32.5 (4236f0a1yd2hrR_KV0kikHZDllUBHw)

Bug fix for when an attempt to grab a ref to a guest page fails.
In general, the code is much more paranoid now about checking
the return status of shadow_get_page_from_l1e() and get_shadow_ref().

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author mafetter@fleming.research
date Tue Mar 15 14:26:41 2005 +0000 (2005-03-15)
parents 4ff298f651de
children 44b147d903bc
files xen/arch/x86/shadow.c xen/include/asm-x86/shadow.h
line diff
     1.1 --- a/xen/arch/x86/shadow.c	Tue Mar 15 12:31:32 2005 +0000
     1.2 +++ b/xen/arch/x86/shadow.c	Tue Mar 15 14:26:41 2005 +0000
     1.3 @@ -1178,7 +1178,8 @@ void shadow_map_l1_into_current_l2(unsig
     1.4      ASSERT( !(old_sl2e & _PAGE_PRESENT) );
     1.5  #endif
     1.6  
     1.7 -    get_shadow_ref(sl1mfn);
     1.8 +    if (!get_shadow_ref(sl1mfn))
     1.9 +        BUG();
    1.10      l2pde_general(d, &gl2e, &sl2e, sl1mfn);
    1.11      __guest_set_l2e(ed, va, gl2e);
    1.12      __shadow_set_l2e(ed, va, sl2e);
    1.13 @@ -1195,9 +1196,13 @@ void shadow_map_l1_into_current_l2(unsig
    1.14  
    1.15          for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    1.16          {
    1.17 -            l1pte_propagate_from_guest(d, gpl1e[i], &spl1e[i]);
    1.18 -            if ( spl1e[i] & _PAGE_PRESENT )
    1.19 -                shadow_get_page_from_l1e(mk_l1_pgentry(spl1e[i]), d);
    1.20 +            unsigned long sl1e;
    1.21 +
    1.22 +            l1pte_propagate_from_guest(d, gpl1e[i], &sl1e);
    1.23 +            if ( (sl1e & _PAGE_PRESENT) &&
    1.24 +                 !shadow_get_page_from_l1e(mk_l1_pgentry(sl1e), d) )
    1.25 +                sl1e = 0;
    1.26 +            spl1e[i] = sl1e;
    1.27          }
    1.28      }
    1.29  }
    1.30 @@ -1502,8 +1507,9 @@ static u32 remove_all_write_access_in_pt
    1.31              unsigned long old = pt[i];
    1.32              unsigned long new = old & ~_PAGE_RW;
    1.33  
    1.34 -            if ( is_l1_shadow )
    1.35 -                shadow_get_page_from_l1e(mk_l1_pgentry(new), d);
    1.36 +            if ( is_l1_shadow &&
    1.37 +                 !shadow_get_page_from_l1e(mk_l1_pgentry(new), d) )
    1.38 +                BUG();
    1.39  
    1.40              count++;
    1.41              pt[i] = new;
    1.42 @@ -1724,8 +1730,9 @@ void __shadow_sync_all(struct domain *d)
    1.43          unsigned long opte = *ppte;
    1.44          unsigned long npte = opte & ~_PAGE_RW;
    1.45  
    1.46 -        if ( npte & _PAGE_PRESENT)
    1.47 -            shadow_get_page_from_l1e(mk_l1_pgentry(npte), d);
    1.48 +        if ( (npte & _PAGE_PRESENT) &&
    1.49 +             !shadow_get_page_from_l1e(mk_l1_pgentry(npte), d) )
    1.50 +            BUG();
    1.51          *ppte = npte;
    1.52          put_page_from_l1e(mk_l1_pgentry(opte), d);
    1.53  
     2.1 --- a/xen/include/asm-x86/shadow.h	Tue Mar 15 12:31:32 2005 +0000
     2.2 +++ b/xen/include/asm-x86/shadow.h	Tue Mar 15 14:26:41 2005 +0000
     2.3 @@ -259,13 +259,16 @@ shadow_get_page_from_l1e(l1_pgentry_t l1
     2.4           (d != owner) )
     2.5      {
     2.6          res = get_page_from_l1e(l1e, owner);
     2.7 -        printk("tried to map page from domain %d into shadow page tables "
     2.8 +        printk("tried to map mfn %p from domain %d into shadow page tables "
     2.9                 "of domain %d; %s\n",
    2.10 -               owner->id, d->id, res ? "success" : "failed");
    2.11 +               mfn, owner->id, d->id, res ? "success" : "failed");
    2.12      }
    2.13  
    2.14      if ( unlikely(!res) )
    2.15 +    {
    2.16          perfc_incrc(shadow_get_page_fail);
    2.17 +        FSH_LOG("%s failed to get ref l1e=%p\n", l1_pgentry_val(l1e));
    2.18 +    }
    2.19  
    2.20      return res;
    2.21  }
    2.22 @@ -313,8 +316,9 @@ static inline void
    2.23          //
    2.24          if ( (old_hl2e ^ new_hl2e) & (PAGE_MASK | _PAGE_PRESENT) )
    2.25          {
    2.26 -            if ( new_hl2e & _PAGE_PRESENT )
    2.27 -                shadow_get_page_from_l1e(mk_l1_pgentry(new_hl2e), ed->domain);
    2.28 +            if ( (new_hl2e & _PAGE_PRESENT) &&
    2.29 +                 !shadow_get_page_from_l1e(mk_l1_pgentry(new_hl2e), ed->domain) )
    2.30 +                new_hl2e = 0;
    2.31              if ( old_hl2e & _PAGE_PRESENT )
    2.32                  put_page_from_l1e(mk_l1_pgentry(old_hl2e), ed->domain);
    2.33          }
    2.34 @@ -531,26 +535,20 @@ static inline void l1pte_read_fault(
    2.35  static inline void l1pte_propagate_from_guest(
    2.36      struct domain *d, unsigned long gpte, unsigned long *spte_p)
    2.37  { 
    2.38 -    unsigned long spte = *spte_p;
    2.39      unsigned long pfn = gpte >> PAGE_SHIFT;
    2.40      unsigned long mfn = __gpfn_to_mfn(d, pfn);
    2.41 +    unsigned long spte;
    2.42  
    2.43  #if SHADOW_VERBOSE_DEBUG
    2.44 -    unsigned long old_spte = spte;
    2.45 +    unsigned long old_spte = *spte_p;
    2.46  #endif
    2.47  
    2.48 -    if ( unlikely(!mfn) )
    2.49 -    {
    2.50 -        // likely an MMIO address space mapping...
    2.51 -        //
    2.52 -        *spte_p = 0;
    2.53 -        return;
    2.54 -    }
    2.55 +    spte = 0;
    2.56  
    2.57 -    spte = 0;
    2.58 -    if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == 
    2.59 -         (_PAGE_PRESENT|_PAGE_ACCESSED) ) {
    2.60 -        
    2.61 +    if ( mfn &&
    2.62 +         ((gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
    2.63 +          (_PAGE_PRESENT|_PAGE_ACCESSED)) ) {
    2.64 +
    2.65          spte = (mfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
    2.66          
    2.67          if ( shadow_mode_log_dirty(d) ||
    2.68 @@ -563,7 +561,7 @@ static inline void l1pte_propagate_from_
    2.69  
    2.70  #if SHADOW_VERBOSE_DEBUG
    2.71      if ( old_spte || spte || gpte )
    2.72 -        debugtrace_printk("l1pte_propagate_from_guest: gpte=0x%p, old spte=0x%p, new spte=0x%p\n", gpte, old_spte, spte);
    2.73 +        SH_VLOG("l1pte_propagate_from_guest: gpte=0x%p, old spte=0x%p, new spte=0x%p", gpte, old_spte, spte);
    2.74  #endif
    2.75  
    2.76      *spte_p = spte;
    2.77 @@ -624,8 +622,7 @@ validate_pte_change(
    2.78  #endif
    2.79  
    2.80      old_spte = *shadow_pte_p;
    2.81 -    l1pte_propagate_from_guest(d, new_pte, shadow_pte_p);
    2.82 -    new_spte = *shadow_pte_p;
    2.83 +    l1pte_propagate_from_guest(d, new_pte, &new_spte);
    2.84  
    2.85      // only do the ref counting if something important changed.
    2.86      //
    2.87 @@ -634,12 +631,15 @@ validate_pte_change(
    2.88      {
    2.89          perfc_incrc(validate_pte_changes);
    2.90  
    2.91 -        if ( new_spte & _PAGE_PRESENT )
    2.92 -            shadow_get_page_from_l1e(mk_l1_pgentry(new_spte), d);
    2.93 +        if ( (new_spte & _PAGE_PRESENT) &&
    2.94 +             !shadow_get_page_from_l1e(mk_l1_pgentry(new_spte), d) )
    2.95 +            new_spte = 0;
    2.96          if ( old_spte & _PAGE_PRESENT )
    2.97              put_page_from_l1e(mk_l1_pgentry(old_spte), d);
    2.98      }
    2.99  
   2.100 +    *shadow_pte_p = new_spte;
   2.101 +
   2.102      // paranoia rules!
   2.103      return 1;
   2.104  }
   2.105 @@ -652,13 +652,14 @@ validate_pde_change(
   2.106      unsigned long new_pde,
   2.107      unsigned long *shadow_pde_p)
   2.108  {
   2.109 -    unsigned long old_spde = *shadow_pde_p;
   2.110 -    unsigned long new_spde;
   2.111 +    unsigned long old_spde, new_spde;
   2.112  
   2.113      perfc_incrc(validate_pde_calls);
   2.114  
   2.115 -    l2pde_propagate_from_guest(d, &new_pde, shadow_pde_p);
   2.116 -    new_spde = *shadow_pde_p;
   2.117 +    old_spde = *shadow_pde_p;
   2.118 +    l2pde_propagate_from_guest(d, &new_pde, &new_spde);
   2.119 +
   2.120 +    // XXX Shouldn't we supposed to propagate the new_pde to the guest?
   2.121  
   2.122      // only do the ref counting if something important changed.
   2.123      //
   2.124 @@ -667,12 +668,15 @@ validate_pde_change(
   2.125      {
   2.126          perfc_incrc(validate_pde_changes);
   2.127  
   2.128 -        if ( new_spde & _PAGE_PRESENT )
   2.129 -            get_shadow_ref(new_spde >> PAGE_SHIFT);
   2.130 +        if ( (new_spde & _PAGE_PRESENT) &&
   2.131 +             !get_shadow_ref(new_spde >> PAGE_SHIFT) )
   2.132 +            BUG();
   2.133          if ( old_spde & _PAGE_PRESENT )
   2.134              put_shadow_ref(old_spde >> PAGE_SHIFT);
   2.135      }
   2.136  
   2.137 +    *shadow_pde_p = new_spde;
   2.138 +
   2.139      // paranoia rules!
   2.140      return 1;
   2.141  }
   2.142 @@ -1140,7 +1144,8 @@ shadow_set_l1e(unsigned long va, unsigne
   2.143              if ( sl1mfn )
   2.144              {
   2.145                  perfc_incrc(shadow_set_l1e_unlinked);
   2.146 -                get_shadow_ref(sl1mfn);
   2.147 +                if (!get_shadow_ref(sl1mfn))
   2.148 +                    BUG();
   2.149                  l2pde_general(d, &gpde, &sl2e, sl1mfn);
   2.150                  __guest_set_l2e(ed, va, gpde);
   2.151                  __shadow_set_l2e(ed, va, sl2e);
   2.152 @@ -1155,17 +1160,19 @@ shadow_set_l1e(unsigned long va, unsigne
   2.153      }
   2.154  
   2.155      old_spte = l1_pgentry_val(shadow_linear_pg_table[l1_linear_offset(va)]);
   2.156 -    shadow_linear_pg_table[l1_linear_offset(va)] = mk_l1_pgentry(new_spte);
   2.157  
   2.158      // only do the ref counting if something important changed.
   2.159      //
   2.160      if ( (old_spte ^ new_spte) & (PAGE_MASK | _PAGE_RW | _PAGE_PRESENT) )
   2.161      {
   2.162 -        if ( new_spte & _PAGE_PRESENT )
   2.163 -            shadow_get_page_from_l1e(mk_l1_pgentry(new_spte), d);
   2.164 +        if ( (new_spte & _PAGE_PRESENT) &&
   2.165 +             !shadow_get_page_from_l1e(mk_l1_pgentry(new_spte), d) )
   2.166 +            new_spte = 0;
   2.167          if ( old_spte & _PAGE_PRESENT )
   2.168              put_page_from_l1e(mk_l1_pgentry(old_spte), d);
   2.169      }
   2.170 +
   2.171 +    shadow_linear_pg_table[l1_linear_offset(va)] = mk_l1_pgentry(new_spte);
   2.172  }
   2.173  
   2.174  /************************************************************************/