ia64/xen-unstable

changeset 17702:2195290728d4

shadow: check for gfn_to_mfn returning INVALID_MFN

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 22 15:08:14 2008 +0100 (2008-05-22)
parents b259eebb0223
children f472d708b9af
files xen/arch/x86/mm/shadow/common.c
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/common.c	Thu May 22 11:04:02 2008 +0100
     1.2 +++ b/xen/arch/x86/mm/shadow/common.c	Thu May 22 15:08:14 2008 +0100
     1.3 @@ -2799,8 +2799,11 @@ int shadow_track_dirty_vram(struct domai
     1.4      if ( !d->dirty_vram )
     1.5      {
     1.6          /* Just recount from start. */
     1.7 -        for ( i = begin_pfn; i < end_pfn; i++ )
     1.8 -            flush_tlb |= sh_remove_all_mappings(d->vcpu[0], gfn_to_mfn(d, i, &t));
     1.9 +        for ( i = begin_pfn; i < end_pfn; i++ ) {
    1.10 +            mfn_t mfn = gfn_to_mfn(d, i, &t);
    1.11 +            if (mfn_x(mfn) != INVALID_MFN)
    1.12 +                flush_tlb |= sh_remove_all_mappings(d->vcpu[0], mfn);
    1.13 +        }
    1.14  
    1.15          gdprintk(XENLOG_INFO, "tracking VRAM %lx - %lx\n", begin_pfn, end_pfn);
    1.16  
    1.17 @@ -2840,61 +2843,70 @@ int shadow_track_dirty_vram(struct domai
    1.18          /* Iterate over VRAM to track dirty bits. */
    1.19          for ( i = 0; i < nr; i++ ) {
    1.20              mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
    1.21 -            struct page_info *page = mfn_to_page(mfn);
    1.22 -            u32 count_info = page->u.inuse.type_info & PGT_count_mask;
    1.23 +            struct page_info *page;
    1.24 +            u32 count_info;
    1.25              int dirty = 0;
    1.26              paddr_t sl1ma = d->dirty_vram->sl1ma[i];
    1.27  
    1.28 -            switch (count_info)
    1.29 +            if (mfn_x(mfn) == INVALID_MFN)
    1.30              {
    1.31 -            case 0:
    1.32 -                /* No guest reference, nothing to track. */
    1.33 -                break;
    1.34 -            case 1:
    1.35 -                /* One guest reference. */
    1.36 -                if ( sl1ma == INVALID_PADDR )
    1.37 +                dirty = 1;
    1.38 +            }
    1.39 +            else
    1.40 +            {
    1.41 +                page = mfn_to_page(mfn);
    1.42 +                count_info = page->u.inuse.type_info & PGT_count_mask;
    1.43 +                switch (count_info)
    1.44                  {
    1.45 -                    /* We don't know which sl1e points to this, too bad. */
    1.46 -                    dirty = 1;
    1.47 -                    /* TODO: Heuristics for finding the single mapping of
    1.48 -                     * this gmfn */
    1.49 -                    flush_tlb |= sh_remove_all_mappings(d->vcpu[0], gfn_to_mfn(d, begin_pfn + i, &t));
    1.50 -                }
    1.51 -                else
    1.52 -                {
    1.53 -                    /* Hopefully the most common case: only one mapping,
    1.54 -                     * whose dirty bit we can use. */
    1.55 -                    l1_pgentry_t *sl1e;
    1.56 +                case 0:
    1.57 +                    /* No guest reference, nothing to track. */
    1.58 +                    break;
    1.59 +                case 1:
    1.60 +                    /* One guest reference. */
    1.61 +                    if ( sl1ma == INVALID_PADDR )
    1.62 +                    {
    1.63 +                        /* We don't know which sl1e points to this, too bad. */
    1.64 +                        dirty = 1;
    1.65 +                        /* TODO: Heuristics for finding the single mapping of
    1.66 +                         * this gmfn */
    1.67 +                        flush_tlb |= sh_remove_all_mappings(d->vcpu[0], mfn);
    1.68 +                    }
    1.69 +                    else
    1.70 +                    {
    1.71 +                        /* Hopefully the most common case: only one mapping,
    1.72 +                         * whose dirty bit we can use. */
    1.73 +                        l1_pgentry_t *sl1e;
    1.74  #ifdef __i386__
    1.75 -                    void *sl1p = map_sl1p;
    1.76 -                    unsigned long sl1mfn = paddr_to_pfn(sl1ma);
    1.77 -
    1.78 -                    if ( sl1mfn != map_mfn ) {
    1.79 -                        if ( map_sl1p )
    1.80 -                            sh_unmap_domain_page(map_sl1p);
    1.81 -                        map_sl1p = sl1p = sh_map_domain_page(_mfn(sl1mfn));
    1.82 -                        map_mfn = sl1mfn;
    1.83 -                    }
    1.84 -                    sl1e = sl1p + (sl1ma & ~PAGE_MASK);
    1.85 +                        void *sl1p = map_sl1p;
    1.86 +                        unsigned long sl1mfn = paddr_to_pfn(sl1ma);
    1.87 +
    1.88 +                        if ( sl1mfn != map_mfn ) {
    1.89 +                            if ( map_sl1p )
    1.90 +                                sh_unmap_domain_page(map_sl1p);
    1.91 +                            map_sl1p = sl1p = sh_map_domain_page(_mfn(sl1mfn));
    1.92 +                            map_mfn = sl1mfn;
    1.93 +                        }
    1.94 +                        sl1e = sl1p + (sl1ma & ~PAGE_MASK);
    1.95  #else
    1.96 -                    sl1e = maddr_to_virt(sl1ma);
    1.97 +                        sl1e = maddr_to_virt(sl1ma);
    1.98  #endif
    1.99  
   1.100 -                    if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY )
   1.101 -                    {
   1.102 -                        dirty = 1;
   1.103 -                        /* Note: this is atomic, so we may clear a
   1.104 -                         * _PAGE_ACCESSED set by another processor. */
   1.105 -                        l1e_remove_flags(*sl1e, _PAGE_DIRTY);
   1.106 -                        flush_tlb = 1;
   1.107 +                        if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY )
   1.108 +                        {
   1.109 +                            dirty = 1;
   1.110 +                            /* Note: this is atomic, so we may clear a
   1.111 +                             * _PAGE_ACCESSED set by another processor. */
   1.112 +                            l1e_remove_flags(*sl1e, _PAGE_DIRTY);
   1.113 +                            flush_tlb = 1;
   1.114 +                        }
   1.115                      }
   1.116 +                    break;
   1.117 +                default:
   1.118 +                    /* More than one guest reference,
   1.119 +                     * we don't afford tracking that. */
   1.120 +                    dirty = 1;
   1.121 +                    break;
   1.122                  }
   1.123 -                break;
   1.124 -            default:
   1.125 -                /* More than one guest reference,
   1.126 -                 * we don't afford tracking that. */
   1.127 -                dirty = 1;
   1.128 -                break;
   1.129              }
   1.130  
   1.131              if ( dirty )
   1.132 @@ -2916,8 +2928,11 @@ int shadow_track_dirty_vram(struct domai
   1.133              {
   1.134                  /* was clean for more than two seconds, try to disable guest
   1.135                   * write access */
   1.136 -                for ( i = begin_pfn; i < end_pfn; i++ )
   1.137 -                    flush_tlb |= sh_remove_write_access(d->vcpu[0], gfn_to_mfn(d, i, &t), 1, 0);
   1.138 +                for ( i = begin_pfn; i < end_pfn; i++ ) {
   1.139 +                    mfn_t mfn = gfn_to_mfn(d, i, &t);
   1.140 +                    if (mfn_x(mfn) != INVALID_MFN)
   1.141 +                        flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn, 1, 0);
   1.142 +                }
   1.143                  d->dirty_vram->last_dirty = -1;
   1.144              }
   1.145              rc = 0;