ia64/xen-unstable

changeset 5275:834f2ae69b7d

bitkeeper revision 1.1640 (429f380cmOBrQfCPrfaJptORVNmNSQ)

Fix page-table initialisation (MPT, linear mappings, and mapcache).
In particular, we were mapping garbage pages into the idle page
directory which caused bogus unflushable mappings to get speculatively
loaded into the TLB (nasty crashes).
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jun 02 16:47:08 2005 +0000 (2005-06-02)
parents 7d4fe5930112
children c1a4141f0cdc
files xen/arch/x86/x86_32/domain_page.c xen/arch/x86/x86_32/mm.c xen/include/asm-x86/x86_32/domain_page.h
line diff
     1.1 --- a/xen/arch/x86/x86_32/domain_page.c	Thu Jun 02 13:56:35 2005 +0000
     1.2 +++ b/xen/arch/x86/x86_32/domain_page.c	Thu Jun 02 16:47:08 2005 +0000
     1.3 @@ -29,13 +29,11 @@ static spinlock_t map_lock = SPIN_LOCK_U
     1.4  static void flush_all_ready_maps(void)
     1.5  {
     1.6      l1_pgentry_t *cache = mapcache;
     1.7 +    unsigned int i;
     1.8  
     1.9 -    /* A bit skanky -- depends on having an aligned PAGE_SIZE set of PTEs. */
    1.10 -    do {
    1.11 -        if ( (l1e_get_flags(*cache) & READY_FOR_TLB_FLUSH) )
    1.12 -            *cache = l1e_empty();
    1.13 -    }
    1.14 -    while ( ((unsigned long)(++cache) & ~PAGE_MASK) != 0 );
    1.15 +    for ( i = 0; i < MAPCACHE_ENTRIES; i++ )
    1.16 +        if ( (l1e_get_flags(cache[i]) & READY_FOR_TLB_FLUSH) )
    1.17 +            cache[i] = l1e_empty();
    1.18  }
    1.19  
    1.20  
     2.1 --- a/xen/arch/x86/x86_32/mm.c	Thu Jun 02 13:56:35 2005 +0000
     2.2 +++ b/xen/arch/x86/x86_32/mm.c	Thu Jun 02 16:47:08 2005 +0000
     2.3 @@ -59,8 +59,9 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned l
     2.4  void __init paging_init(void)
     2.5  {
     2.6      void *ioremap_pt;
     2.7 -    unsigned long v,v2,i;
     2.8 +    unsigned long v;
     2.9      struct pfn_info *pg;
    2.10 +    int i, mapcache_order;
    2.11  
    2.12  #ifdef CONFIG_X86_PAE
    2.13      printk("PAE enabled, limit: %d GB\n", MACHPHYS_MBYTES);
    2.14 @@ -70,64 +71,56 @@ void __init paging_init(void)
    2.15  
    2.16      idle0_exec_domain.arch.monitor_table = mk_pagetable(__pa(idle_pg_table));
    2.17  
    2.18 -    /* Allocate and map the machine-to-phys table and create read-only
    2.19 -     * mapping of MPT for guest-OS use.  Without PAE we'll end up with
    2.20 -     * one 4MB page, with PAE we'll allocate 2MB pages depending on
    2.21 -     * the amout of memory installed, but at least 4MB to cover 4GB
    2.22 -     * address space.  This is needed to make PCI I/O memory address
    2.23 -     * lookups work in guests. -- kraxel */
    2.24 -    mpt_size = max_page * 4;
    2.25 -    if (mpt_size < 4*1024*1024)
    2.26 +    /*
    2.27 +     * Allocate and map the machine-to-phys table and create read-only mapping 
    2.28 +     * of MPT for guest-OS use.  Without PAE we'll end up with one 4MB page, 
    2.29 +     * with PAE we'll allocate 2MB pages depending on the amount of memory 
    2.30 +     * installed, but at least 4MB to cover 4GB address space.  This is needed 
    2.31 +     * to make PCI I/O memory address lookups work in guests.
    2.32 +     */
    2.33 +    if ( (mpt_size = max_page * 4) < (4*1024*1024) )
    2.34          mpt_size = 4*1024*1024;
    2.35 -    for (v  = RDWR_MPT_VIRT_START, v2 = RO_MPT_VIRT_START;
    2.36 -         v != RDWR_MPT_VIRT_END && mpt_size > (v - RDWR_MPT_VIRT_START);
    2.37 -         v += (1 << L2_PAGETABLE_SHIFT), v2 += (1 << L2_PAGETABLE_SHIFT)) {
    2.38 +    for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
    2.39 +    {
    2.40          if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER)) == NULL )
    2.41              panic("Not enough memory to bootstrap Xen.\n");
    2.42 -        idle_pg_table_l2[l2_linear_offset(v)] =
    2.43 +        idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i] =
    2.44              l2e_from_page(pg, __PAGE_HYPERVISOR | _PAGE_PSE);
    2.45 -        idle_pg_table_l2[l2_linear_offset(v2)] =
    2.46 +        idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i] =
    2.47              l2e_from_page(pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW);
    2.48      }
    2.49      memset((void *)RDWR_MPT_VIRT_START, 0x55, mpt_size);
    2.50  
    2.51 -    /* Xen 2/4MB mappings can all be GLOBAL. */
    2.52 +    /* Xen PSE mappings can all be GLOBAL. */
    2.53      if ( cpu_has_pge )
    2.54      {
    2.55 -        for ( v = HYPERVISOR_VIRT_START; v; v += (1 << L2_PAGETABLE_SHIFT) ) {
    2.56 -            if (!l2e_get_flags(idle_pg_table_l2[l2_linear_offset(v)]) & _PAGE_PSE)
    2.57 +        for ( v = HYPERVISOR_VIRT_START; v; v += (1 << L2_PAGETABLE_SHIFT) )
    2.58 +        {
    2.59 +            if ( (l2e_get_flags(idle_pg_table_l2[l2_linear_offset(v)]) &
    2.60 +                  (_PAGE_PSE|_PAGE_PRESENT)) != (_PAGE_PSE|_PAGE_PRESENT) )
    2.61                  continue;
    2.62 -            if (v >= RO_MPT_VIRT_START && v < RO_MPT_VIRT_END)
    2.63 +            if ( (v >= RO_MPT_VIRT_START) && (v < RO_MPT_VIRT_END) )
    2.64                  continue;
    2.65 -            l2e_add_flags(idle_pg_table_l2[l2_linear_offset(v)],
    2.66 -                          _PAGE_GLOBAL);
    2.67 +            l2e_add_flags(idle_pg_table_l2[l2_linear_offset(v)], _PAGE_GLOBAL);
    2.68          }
    2.69      }
    2.70  
    2.71 -    /* Create page table(s) for ioremap(). */
    2.72 -    for (v = IOREMAP_VIRT_START; v != IOREMAP_VIRT_END; v += (1 << L2_PAGETABLE_SHIFT)) {
    2.73 +    /* Create page tables for ioremap(). */
    2.74 +    for ( i = 0; i < (IOREMAP_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
    2.75 +    {
    2.76          ioremap_pt = (void *)alloc_xenheap_page();
    2.77          clear_page(ioremap_pt);
    2.78 -        idle_pg_table_l2[l2_linear_offset(v)] =
    2.79 +        idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i] =
    2.80              l2e_from_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR);
    2.81      }
    2.82  
    2.83      /* Set up mapping cache for domain pages. */
    2.84 -    mapcache = (l1_pgentry_t*)alloc_xenheap_pages(10-PAGETABLE_ORDER);
    2.85 -    for (v = MAPCACHE_VIRT_START, i = 0;
    2.86 -         v != MAPCACHE_VIRT_END;
    2.87 -         v += (1 << L2_PAGETABLE_SHIFT), i++) {
    2.88 -        clear_page(mapcache + i*L1_PAGETABLE_ENTRIES);
    2.89 -        idle_pg_table_l2[l2_linear_offset(v)] =
    2.90 -            l2e_from_page(virt_to_page(mapcache + i*L1_PAGETABLE_ENTRIES),
    2.91 -                            __PAGE_HYPERVISOR);
    2.92 -    }
    2.93 -
    2.94 -    for (v = LINEAR_PT_VIRT_START; v != LINEAR_PT_VIRT_END; v += (1 << L2_PAGETABLE_SHIFT)) {
    2.95 -        idle_pg_table_l2[l2_linear_offset(v)] =
    2.96 -            l2e_from_page(virt_to_page(idle_pg_table_l2 + ((v-RDWR_MPT_VIRT_START) >> PAGETABLE_ORDER)),
    2.97 -                            __PAGE_HYPERVISOR);
    2.98 -    }
    2.99 +    mapcache_order = get_order(MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER));
   2.100 +    mapcache = (l1_pgentry_t *)alloc_xenheap_pages(mapcache_order);
   2.101 +    memset(mapcache, 0, PAGE_SIZE << mapcache_order);
   2.102 +    for ( i = 0; i < (MAPCACHE_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
   2.103 +        idle_pg_table_l2[l2_linear_offset(MAPCACHE_VIRT_START) + i] =
   2.104 +            l2e_from_page(virt_to_page(mapcache) + i, __PAGE_HYPERVISOR);
   2.105  }
   2.106  
   2.107  void __init zap_low_mappings(l2_pgentry_t *base)
   2.108 @@ -148,7 +141,8 @@ void __init zap_low_mappings(l2_pgentry_
   2.109  
   2.110  void subarch_init_memory(struct domain *dom_xen)
   2.111  {
   2.112 -    unsigned long i, v, m2p_start_mfn;
   2.113 +    unsigned long m2p_start_mfn;
   2.114 +    int i;
   2.115  
   2.116      /*
   2.117       * We are rather picky about the layout of 'struct pfn_info'. The
   2.118 @@ -164,21 +158,18 @@ void subarch_init_memory(struct domain *
   2.119                 offsetof(struct pfn_info, count_info),
   2.120                 offsetof(struct pfn_info, u.inuse._domain),
   2.121                 sizeof(struct pfn_info));
   2.122 -        for ( ; ; )
   2.123 -            __asm__ __volatile__ ( "hlt" );
   2.124 +        BUG();
   2.125      }
   2.126  
   2.127      /* M2P table is mappable read-only by privileged domains. */
   2.128 -    for (v  = RDWR_MPT_VIRT_START;
   2.129 -         v != RDWR_MPT_VIRT_END && mpt_size > (v - RDWR_MPT_VIRT_START);
   2.130 -         v += (1 << L2_PAGETABLE_SHIFT)) {
   2.131 +    for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
   2.132 +    {
   2.133          m2p_start_mfn = l2e_get_pfn(
   2.134 -            idle_pg_table_l2[l2_linear_offset(v)]);
   2.135 +            idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i]);
   2.136          for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   2.137          {
   2.138              frame_table[m2p_start_mfn+i].count_info = PGC_allocated | 1;
   2.139 -            /* gdt to make sure it's only mapped read-only by non-privileged
   2.140 -               domains. */
   2.141 +            /* Ensure it's only mapped read-only by domains. */
   2.142              frame_table[m2p_start_mfn+i].u.inuse.type_info = PGT_gdt_page | 1;
   2.143              page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
   2.144          }
     3.1 --- a/xen/include/asm-x86/x86_32/domain_page.h	Thu Jun 02 13:56:35 2005 +0000
     3.2 +++ b/xen/include/asm-x86/x86_32/domain_page.h	Thu Jun 02 16:47:08 2005 +0000
     3.3 @@ -11,7 +11,8 @@
     3.4  #include <xen/sched.h>
     3.5  
     3.6  extern l1_pgentry_t *mapcache;
     3.7 -#define MAPCACHE_ENTRIES        1024
     3.8 +#define MAPCACHE_ORDER    10
     3.9 +#define MAPCACHE_ENTRIES  (1 << MAPCACHE_ORDER)
    3.10  
    3.11  /*
    3.12   * Maps a given physical address, returning corresponding virtual address.