ia64/xen-unstable

changeset 15083:03a13457d993

x86: Improve zap_low_mappings.

Do it earlier on x86/64, properly free non-superpages on x86/32, and
leave a mapping of the boot trampoline (0x90000-0xA0000) in place.

Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Sat May 12 12:07:01 2007 +0100 (2007-05-12)
parents 759d924af6d8
children 5f6da38ff828
files xen/arch/x86/domain_build.c xen/arch/x86/mm.c xen/arch/x86/setup.c xen/arch/x86/smpboot.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_64/mm.c xen/include/asm-x86/page.h
line diff
     1.1 --- a/xen/arch/x86/domain_build.c	Sat May 12 10:28:53 2007 +0100
     1.2 +++ b/xen/arch/x86/domain_build.c	Sat May 12 12:07:01 2007 +0100
     1.3 @@ -902,7 +902,6 @@ int __init construct_dom0(
     1.4  #if defined(__i386__)
     1.5      /* Destroy low mappings - they were only for our convenience. */
     1.6      zap_low_mappings(l2start);
     1.7 -    zap_low_mappings(idle_pg_table_l2);
     1.8  #endif
     1.9  
    1.10      update_domain_wallclock_time(d);
     2.1 --- a/xen/arch/x86/mm.c	Sat May 12 10:28:53 2007 +0100
     2.2 +++ b/xen/arch/x86/mm.c	Sat May 12 12:07:01 2007 +0100
     2.3 @@ -3402,6 +3402,18 @@ int ptwr_do_page_fault(struct vcpu *v, u
     2.4      return 0;
     2.5  }
     2.6  
     2.7 +void free_xen_pagetable(void *v)
     2.8 +{
     2.9 +    extern int early_boot;
    2.10 +
    2.11 +    BUG_ON(early_boot);
    2.12 +    
    2.13 +    if ( is_xen_heap_frame(virt_to_page(v)) )
    2.14 +        free_xenheap_page(v);
    2.15 +    else
    2.16 +        free_domheap_page(virt_to_page(v));
    2.17 +}
    2.18 +
    2.19  int map_pages_to_xen(
    2.20      unsigned long virt,
    2.21      unsigned long mfn,
    2.22 @@ -3475,6 +3487,73 @@ int map_pages_to_xen(
    2.23      return 0;
    2.24  }
    2.25  
    2.26 +void destroy_xen_mappings(unsigned long s, unsigned long e)
    2.27 +{
    2.28 +    l2_pgentry_t *pl2e;
    2.29 +    l1_pgentry_t *pl1e;
    2.30 +    unsigned int  i;
    2.31 +    unsigned long v = s;
    2.32 +
    2.33 +    ASSERT((s & ~PAGE_MASK) == 0);
    2.34 +    ASSERT((e & ~PAGE_MASK) == 0);
    2.35 +
    2.36 +    while ( v < e )
    2.37 +    {
    2.38 +        pl2e = virt_to_xen_l2e(v);
    2.39 +
    2.40 +        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
    2.41 +        {
    2.42 +            v += PAGE_SIZE;
    2.43 +            continue;
    2.44 +        }
    2.45 +
    2.46 +        if ( l2e_get_flags(*pl2e) & _PAGE_PSE )
    2.47 +        {
    2.48 +            if ( (l1_table_offset(v) == 0) &&
    2.49 +                 ((e-v) >= (1UL << L2_PAGETABLE_SHIFT)) )
    2.50 +            {
    2.51 +                /* PSE: whole superpage is destroyed. */
    2.52 +                l2e_write_atomic(pl2e, l2e_empty());
    2.53 +                v += 1UL << L2_PAGETABLE_SHIFT;
    2.54 +            }
    2.55 +            else
    2.56 +            {
    2.57 +                /* PSE: shatter the superpage and try again. */
    2.58 +                pl1e = alloc_xen_pagetable();
    2.59 +                for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    2.60 +                    l1e_write(&pl1e[i],
    2.61 +                              l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
    2.62 +                                           l2e_get_flags(*pl2e) & ~_PAGE_PSE));
    2.63 +                l2e_write_atomic(pl2e, l2e_from_pfn(virt_to_mfn(pl1e),
    2.64 +                                                    __PAGE_HYPERVISOR));
    2.65 +            }
    2.66 +        }
    2.67 +        else
    2.68 +        {
    2.69 +            /* Ordinary 4kB mapping. */
    2.70 +            pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(v);
    2.71 +            l1e_write_atomic(pl1e, l1e_empty());
    2.72 +            v += PAGE_SIZE;
    2.73 +
    2.74 +            /* If we are done with the L2E, check if it is now empty. */
    2.75 +            if ( (v != e) && (l1_table_offset(v) != 0) )
    2.76 +                continue;
    2.77 +            pl1e = l2e_to_l1e(*pl2e);
    2.78 +            for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    2.79 +                if ( l1e_get_intpte(pl1e[i]) != 0 )
    2.80 +                    break;
    2.81 +            if ( i == L1_PAGETABLE_ENTRIES )
    2.82 +            {
    2.83 +                /* Empty: zap the L2E and free the L1 page. */
    2.84 +                l2e_write_atomic(pl2e, l2e_empty());
    2.85 +                free_xen_pagetable(pl1e);
    2.86 +            }
    2.87 +        }
    2.88 +    }
    2.89 +
    2.90 +    flush_tlb_all_pge();
    2.91 +}
    2.92 +
    2.93  void __set_fixmap(
    2.94      enum fixed_addresses idx, unsigned long mfn, unsigned long flags)
    2.95  {
     3.1 --- a/xen/arch/x86/setup.c	Sat May 12 10:28:53 2007 +0100
     3.2 +++ b/xen/arch/x86/setup.c	Sat May 12 12:07:01 2007 +0100
     3.3 @@ -779,6 +779,11 @@ void __init __start_xen(multiboot_info_t
     3.4      if ( smp_found_config )
     3.5          get_smp_config();
     3.6  
     3.7 +#ifdef CONFIG_X86_64
     3.8 +    /* Low mappings were only needed for some BIOS table parsing. */
     3.9 +    zap_low_mappings();
    3.10 +#endif
    3.11 +
    3.12      init_apic_mappings();
    3.13  
    3.14      init_IRQ();
     4.1 --- a/xen/arch/x86/smpboot.c	Sat May 12 10:28:53 2007 +0100
     4.2 +++ b/xen/arch/x86/smpboot.c	Sat May 12 12:07:01 2007 +0100
     4.3 @@ -1162,9 +1162,6 @@ void __init smp_cpus_done(unsigned int m
     4.4  #ifdef CONFIG_X86_IO_APIC
     4.5  	setup_ioapic_dest();
     4.6  #endif
     4.7 -#ifdef CONFIG_X86_64
     4.8 -	zap_low_mappings();
     4.9 -#endif
    4.10  #ifndef CONFIG_HOTPLUG_CPU
    4.11  	/*
    4.12  	 * Disable executability of the SMP trampoline:
     5.1 --- a/xen/arch/x86/x86_32/mm.c	Sat May 12 10:28:53 2007 +0100
     5.2 +++ b/xen/arch/x86/x86_32/mm.c	Sat May 12 12:07:01 2007 +0100
     5.3 @@ -61,11 +61,6 @@ void *alloc_xen_pagetable(void)
     5.4      return mfn_to_virt(mfn);
     5.5  }
     5.6  
     5.7 -void free_xen_pagetable(void *v)
     5.8 -{
     5.9 -    free_xenheap_page(v);
    5.10 -}
    5.11 -
    5.12  l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
    5.13  {
    5.14      return &idle_pg_table_l2[l2_linear_offset(v)];
    5.15 @@ -141,22 +136,24 @@ void __init setup_idle_pagetable(void)
    5.16                                  __PAGE_HYPERVISOR));
    5.17  }
    5.18  
    5.19 -void __init zap_low_mappings(l2_pgentry_t *base)
    5.20 +void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
    5.21  {
    5.22      int i;
    5.23 -    u32 addr;
    5.24  
    5.25 -    for ( i = 0; ; i++ )
    5.26 -    {
    5.27 -        addr = i << L2_PAGETABLE_SHIFT;
    5.28 -        if ( addr >= HYPERVISOR_VIRT_START )
    5.29 -            break;
    5.30 -        if ( l2e_get_paddr(base[i]) != addr )
    5.31 -            continue;
    5.32 -        l2e_write(&base[i], l2e_empty());
    5.33 -    }
    5.34 +    /* Clear temporary idle mappings from the dom0 initial l2. */
    5.35 +    for ( i = 0; i < (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT); i++ )
    5.36 +        if ( l2e_get_intpte(dom0_l2[i]) ==
    5.37 +             l2e_get_intpte(idle_pg_table_l2[i]) )
    5.38 +            l2e_write(&dom0_l2[i], l2e_empty());
    5.39 +
    5.40 +    /* Now zap mappings in the idle pagetables. */
    5.41 +    destroy_xen_mappings(0, HYPERVISOR_VIRT_START);
    5.42  
    5.43      flush_tlb_all_pge();
    5.44 +
    5.45 +    /* Replace with mapping of the boot trampoline only. */
    5.46 +    map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
    5.47 +                     0x10, __PAGE_HYPERVISOR);
    5.48  }
    5.49  
    5.50  void __init subarch_init_memory(void)
     6.1 --- a/xen/arch/x86/x86_64/mm.c	Sat May 12 10:28:53 2007 +0100
     6.2 +++ b/xen/arch/x86/x86_64/mm.c	Sat May 12 12:07:01 2007 +0100
     6.3 @@ -70,11 +70,6 @@ void *alloc_xen_pagetable(void)
     6.4      return mfn_to_virt(mfn);
     6.5  }
     6.6  
     6.7 -void free_xen_pagetable(void *v)
     6.8 -{
     6.9 -    free_domheap_page(virt_to_page(v));
    6.10 -}
    6.11 -
    6.12  l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
    6.13  {
    6.14      l4_pgentry_t *pl4e;
    6.15 @@ -209,8 +204,15 @@ void __init setup_idle_pagetable(void)
    6.16  
    6.17  void __init zap_low_mappings(void)
    6.18  {
    6.19 +    BUG_ON(num_online_cpus() != 1);
    6.20 +
    6.21 +    /* Remove aliased mapping of first 1:1 PML4 entry. */
    6.22      l4e_write(&idle_pg_table[0], l4e_empty());
    6.23 -    flush_tlb_all_pge();
    6.24 +    local_flush_tlb_pge();
    6.25 +
    6.26 +    /* Replace with mapping of the boot trampoline only. */
    6.27 +    map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
    6.28 +                     0x10, __PAGE_HYPERVISOR);
    6.29  }
    6.30  
    6.31  void __init subarch_init_memory(void)
     7.1 --- a/xen/include/asm-x86/page.h	Sat May 12 10:28:53 2007 +0100
     7.2 +++ b/xen/include/asm-x86/page.h	Sat May 12 12:07:01 2007 +0100
     7.3 @@ -1,4 +1,3 @@
     7.4 -
     7.5  #ifndef __X86_PAGE_H__
     7.6  #define __X86_PAGE_H__
     7.7  
     7.8 @@ -369,6 +368,7 @@ map_pages_to_xen(
     7.9      unsigned long mfn,
    7.10      unsigned long nr_mfns,
    7.11      unsigned long flags);
    7.12 +void destroy_xen_mappings(unsigned long v, unsigned long e);
    7.13  
    7.14  #endif /* !__ASSEMBLY__ */
    7.15