ia64/xen-unstable

changeset 19322:cc9b41a476dc

x86 shadow: fix vram tracking

Check for writable mappings in ptes before assuming that the type
count in the page has changed.

Signed-off-by: Gianluca Guida <gianluca.guida@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Mar 12 10:55:43 2009 +0000 (2009-03-12)
parents 8ce14a3bcf05
children a762162e2fc9
files xen/arch/x86/mm/shadow/multi.c
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/multi.c	Thu Mar 12 08:35:12 2009 +0000
     1.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Mar 12 10:55:43 2009 +0000
     1.3 @@ -1039,18 +1039,19 @@ static inline void shadow_vram_get_l1e(s
     1.4                                         mfn_t sl1mfn,
     1.5                                         struct domain *d)
     1.6  { 
     1.7 -    mfn_t mfn;
     1.8 +    mfn_t mfn = shadow_l1e_get_mfn(new_sl1e);
     1.9 +    int flags = shadow_l1e_get_flags(new_sl1e);
    1.10      unsigned long gfn;
    1.11  
    1.12 -    if ( !d->dirty_vram ) return;
    1.13 -
    1.14 -    mfn = shadow_l1e_get_mfn(new_sl1e);
    1.15 -
    1.16 -    if ( !mfn_valid(mfn) ) return; /* m2p for mmio_direct may not exist */
    1.17 +    if ( !d->dirty_vram         /* tracking disabled? */
    1.18 +         || !(flags & _PAGE_RW) /* read-only mapping? */
    1.19 +         || !mfn_valid(mfn) )   /* mfn can be invalid in mmio_direct */
    1.20 +        return;
    1.21  
    1.22      gfn = mfn_to_gfn(d, mfn);
    1.23  
    1.24 -    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) {
    1.25 +    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) )
    1.26 +    {
    1.27          unsigned long i = gfn - d->dirty_vram->begin_pfn;
    1.28          struct page_info *page = mfn_to_page(mfn);
    1.29          
    1.30 @@ -1066,48 +1067,58 @@ static inline void shadow_vram_put_l1e(s
    1.31                                         mfn_t sl1mfn,
    1.32                                         struct domain *d)
    1.33  {
    1.34 -    mfn_t mfn;
    1.35 +    mfn_t mfn = shadow_l1e_get_mfn(old_sl1e);
    1.36 +    int flags = shadow_l1e_get_flags(old_sl1e);
    1.37      unsigned long gfn;
    1.38  
    1.39 -    if ( !d->dirty_vram ) return;
    1.40 -
    1.41 -    mfn = shadow_l1e_get_mfn(old_sl1e);
    1.42 -
    1.43 -    if ( !mfn_valid(mfn) ) return;
    1.44 +    if ( !d->dirty_vram         /* tracking disabled? */
    1.45 +         || !(flags & _PAGE_RW) /* read-only mapping? */
    1.46 +         || !mfn_valid(mfn) )   /* mfn can be invalid in mmio_direct */
    1.47 +        return;
    1.48  
    1.49      gfn = mfn_to_gfn(d, mfn);
    1.50  
    1.51 -    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) {
    1.52 +    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) )
    1.53 +    {
    1.54          unsigned long i = gfn - d->dirty_vram->begin_pfn;
    1.55          struct page_info *page = mfn_to_page(mfn);
    1.56          int dirty = 0;
    1.57          paddr_t sl1ma = pfn_to_paddr(mfn_x(sl1mfn))
    1.58              | ((unsigned long)sl1e & ~PAGE_MASK);
    1.59  
    1.60 -        if ( (page->u.inuse.type_info & PGT_count_mask) == 1 ) {
    1.61 +        if ( (page->u.inuse.type_info & PGT_count_mask) == 1 )
    1.62 +        {
    1.63              /* Last reference */
    1.64              if ( d->dirty_vram->sl1ma[i] == INVALID_PADDR ) {
    1.65                  /* We didn't know it was that one, let's say it is dirty */
    1.66                  dirty = 1;
    1.67 -            } else {
    1.68 +            }
    1.69 +            else
    1.70 +            {
    1.71                  ASSERT(d->dirty_vram->sl1ma[i] == sl1ma);
    1.72                  d->dirty_vram->sl1ma[i] = INVALID_PADDR;
    1.73 -                if ( shadow_l1e_get_flags(old_sl1e) & _PAGE_DIRTY )
    1.74 +                if ( flags & _PAGE_DIRTY )
    1.75                      dirty = 1;
    1.76              }
    1.77 -        } else {
    1.78 +        }
    1.79 +        else
    1.80 +        {
    1.81              /* We had more than one reference, just consider the page dirty. */
    1.82              dirty = 1;
    1.83              /* Check that it's not the one we recorded. */
    1.84 -            if ( d->dirty_vram->sl1ma[i] == sl1ma ) {
    1.85 +            if ( d->dirty_vram->sl1ma[i] == sl1ma )
    1.86 +            {
    1.87                  /* Too bad, we remembered the wrong one... */
    1.88                  d->dirty_vram->sl1ma[i] = INVALID_PADDR;
    1.89 -            } else {
    1.90 +            }
    1.91 +            else
    1.92 +            {
    1.93                  /* Ok, our recorded sl1e is still pointing to this page, let's
    1.94                   * just hope it will remain. */
    1.95              }
    1.96          }
    1.97 -        if ( dirty ) {
    1.98 +        if ( dirty )
    1.99 +        {
   1.100              d->dirty_vram->dirty_bitmap[i / 8] |= 1 << (i % 8);
   1.101              d->dirty_vram->last_dirty = NOW();
   1.102          }