debuggers.hg

changeset 19983:faa216e744ad

i386: fix handling of Xen entries in final L2 page table

Running Xen on top of KVM exposed an issue that latently also exists
on real hardware: So far, updating any L3 entry resulted in the Xen
owned part of the L2 table referenced by the final L3 one to be re-
initialized. This was not only unnecessary, it actually resulted in
Xen relying on the TLB entry which maps the L2 page that's being
updated not going away intermediately, since as a first step the full
range of Xen owned entries in the L2 were replaced by the respective
ones from the idle page table, and only then the per-domain entries
got re- written to their intended values.

This part of the initialization really is sufficient to be done once,
when the page becomes an L2-with-Xen-entries (PGT_pae_xen_l2) one,
i.e. can be moved to alloc_l2_table(). Only the linear page table
setup has to remain where it always was.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 15 13:07:30 2009 +0100 (2009-07-15)
parents 034e015088ac
children 91407452cdb6
files xen/arch/x86/mm.c
line diff
     1.1 --- a/xen/arch/x86/mm.c	Wed Jul 15 10:31:50 2009 +0100
     1.2 +++ b/xen/arch/x86/mm.c	Wed Jul 15 13:07:30 2009 +0100
     1.3 @@ -1159,10 +1159,9 @@ static int alloc_l1_table(struct page_in
     1.4  static int create_pae_xen_mappings(struct domain *d, l3_pgentry_t *pl3e)
     1.5  {
     1.6      struct page_info *page;
     1.7 -    l2_pgentry_t    *pl2e;
     1.8      l3_pgentry_t     l3e3;
     1.9 -#ifndef CONFIG_COMPAT
    1.10 -    l2_pgentry_t     l2e;
    1.11 +#ifdef __i386__
    1.12 +    l2_pgentry_t     *pl2e, l2e;
    1.13      int              i;
    1.14  #endif
    1.15  
    1.16 @@ -1198,17 +1197,9 @@ static int create_pae_xen_mappings(struc
    1.17          return 0;
    1.18      }
    1.19  
    1.20 -    /* Xen private mappings. */
    1.21 +#ifdef __i386__
    1.22 +    /* Xen linear pagetable mappings. */
    1.23      pl2e = map_domain_page(l3e_get_pfn(l3e3));
    1.24 -#ifndef CONFIG_COMPAT
    1.25 -    memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],
    1.26 -           &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
    1.27 -           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
    1.28 -    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
    1.29 -    {
    1.30 -        l2e = l2e_from_page(perdomain_pt_page(d, i), __PAGE_HYPERVISOR);
    1.31 -        l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e);
    1.32 -    }
    1.33      for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
    1.34      {
    1.35          l2e = l2e_empty();
    1.36 @@ -1216,13 +1207,8 @@ static int create_pae_xen_mappings(struc
    1.37              l2e = l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR);
    1.38          l2e_write(&pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], l2e);
    1.39      }
    1.40 -#else
    1.41 -    memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)],
    1.42 -           &compat_idle_pg_table_l2[
    1.43 -               l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
    1.44 -           COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e));
    1.45 +    unmap_domain_page(pl2e);
    1.46  #endif
    1.47 -    unmap_domain_page(pl2e);
    1.48  
    1.49      return 1;
    1.50  }
    1.51 @@ -1315,6 +1301,27 @@ static int alloc_l2_table(struct page_in
    1.52          adjust_guest_l2e(pl2e[i], d);
    1.53      }
    1.54  
    1.55 +    if ( rc >= 0 && (type & PGT_pae_xen_l2) )
    1.56 +    {
    1.57 +        /* Xen private mappings. */
    1.58 +#if defined(__i386__)
    1.59 +        memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],
    1.60 +               &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
    1.61 +               L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
    1.62 +        for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
    1.63 +            l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i],
    1.64 +                      l2e_from_page(perdomain_pt_page(d, i),
    1.65 +                                    __PAGE_HYPERVISOR));
    1.66 +        pl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
    1.67 +            l2e_from_pfn(pfn, __PAGE_HYPERVISOR);
    1.68 +#elif defined(CONFIG_COMPAT)
    1.69 +        memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)],
    1.70 +               &compat_idle_pg_table_l2[
    1.71 +                   l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
    1.72 +               COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e));
    1.73 +#endif
    1.74 +    }
    1.75 +
    1.76      unmap_domain_page(pl2e);
    1.77      return rc > 0 ? 0 : rc;
    1.78  }