ia64/xen-unstable

changeset 18547:7a32c2325fdc

x86: Fix guest_physmap_add_entry checks

guest_physmap_add_entry() checks to see if the given mfn and gpfn
range in the p2m and m2p tables is already mapped before overwriting
the maps, and attempts to do something reasonable so that we don't
have any "dangling" pointers.

Unfortunately, these checks got broken when the page_order argument
was added. Each individual p2m and m2p entry needs to be checked, not
just the first page in a page order.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Sep 25 10:26:08 2008 +0100 (2008-09-25)
parents 7592da5118ec
children eececb5de4fa
files xen/arch/x86/mm/p2m.c
line diff
     1.1 --- a/xen/arch/x86/mm/p2m.c	Thu Sep 25 10:21:40 2008 +0100
     1.2 +++ b/xen/arch/x86/mm/p2m.c	Thu Sep 25 10:26:08 2008 +0100
     1.3 @@ -953,38 +953,47 @@ guest_physmap_add_entry(struct domain *d
     1.4  
     1.5      P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
     1.6  
     1.7 -    omfn = gfn_to_mfn(d, gfn, &ot);
     1.8 -    if ( p2m_is_ram(ot) )
     1.9 +    /* First, remove m->p mappings for existing p->m mappings */
    1.10 +    for ( i = 0; i < (1UL << page_order); i++ )
    1.11      {
    1.12 -        ASSERT(mfn_valid(omfn));
    1.13 -        for ( i = 0; i < (1UL << page_order); i++ )
    1.14 -            set_gpfn_from_mfn(mfn_x(omfn)+i, INVALID_M2P_ENTRY);
    1.15 -    }
    1.16 -
    1.17 -    ogfn = mfn_to_gfn(d, _mfn(mfn));
    1.18 -    if (
    1.19 -#ifdef __x86_64__
    1.20 -        (ogfn != 0x5555555555555555L)
    1.21 -#else
    1.22 -        (ogfn != 0x55555555L)
    1.23 -#endif
    1.24 -        && (ogfn != INVALID_M2P_ENTRY)
    1.25 -        && (ogfn != gfn) )
    1.26 -    {
    1.27 -        /* This machine frame is already mapped at another physical address */
    1.28 -        P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
    1.29 -                  mfn, ogfn, gfn);
    1.30 -        omfn = gfn_to_mfn(d, ogfn, &ot);
    1.31 +        omfn = gfn_to_mfn(d, gfn, &ot);
    1.32          if ( p2m_is_ram(ot) )
    1.33          {
    1.34              ASSERT(mfn_valid(omfn));
    1.35 -            P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
    1.36 -                      ogfn , mfn_x(omfn));
    1.37 -            if ( mfn_x(omfn) == mfn )
    1.38 -                p2m_remove_page(d, ogfn, mfn, page_order);
    1.39 +            set_gpfn_from_mfn(mfn_x(omfn)+i, INVALID_M2P_ENTRY);
    1.40          }
    1.41      }
    1.42  
    1.43 +    /* Then, look for m->p mappings for this range and deal with them */
    1.44 +    for ( i = 0; i < (1UL << page_order); i++ )
    1.45 +    {
    1.46 +        ogfn = mfn_to_gfn(d, _mfn(mfn));
    1.47 +        if (
    1.48 +#ifdef __x86_64__
    1.49 +            (ogfn != 0x5555555555555555L)
    1.50 +#else
    1.51 +            (ogfn != 0x55555555L)
    1.52 +#endif
    1.53 +            && (ogfn != INVALID_M2P_ENTRY)
    1.54 +            && (ogfn != gfn) )
    1.55 +        {
    1.56 +            /* This machine frame is already mapped at another physical
    1.57 +             * address */
    1.58 +            P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
    1.59 +                      mfn, ogfn, gfn);
    1.60 +            omfn = gfn_to_mfn(d, ogfn, &ot);
    1.61 +            if ( p2m_is_ram(ot) )
    1.62 +            {
    1.63 +                ASSERT(mfn_valid(omfn));
    1.64 +                P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
    1.65 +                          ogfn , mfn_x(omfn));
    1.66 +                if ( mfn_x(omfn) == mfn )
    1.67 +                    p2m_remove_page(d, ogfn, mfn, 0);
    1.68 +            }
    1.69 +        }
    1.70 +    }
    1.71 +
    1.72 +    /* Now, actually do the two-way mapping */
    1.73      if ( mfn_valid(_mfn(mfn)) ) 
    1.74      {
    1.75          if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) )