[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Improve zap_low_mappings.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1178968021 -3600
# Node ID 03a13457d9938c88a54d5eafaa290ca8a11c53c0
# Parent  759d924af6d8ca99bf04b150dc491b23d80936b0
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@xxxxxxxxxxxxx>
---
 xen/arch/x86/domain_build.c |    1 
 xen/arch/x86/mm.c           |   79 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/setup.c        |    5 ++
 xen/arch/x86/smpboot.c      |    3 -
 xen/arch/x86/x86_32/mm.c    |   31 +++++++----------
 xen/arch/x86/x86_64/mm.c    |   14 ++++---
 xen/include/asm-x86/page.h  |    2 -
 7 files changed, 107 insertions(+), 28 deletions(-)

diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/domain_build.c       Sat May 12 12:07:01 2007 +0100
@@ -902,7 +902,6 @@ int __init construct_dom0(
 #if defined(__i386__)
     /* Destroy low mappings - they were only for our convenience. */
     zap_low_mappings(l2start);
-    zap_low_mappings(idle_pg_table_l2);
 #endif
 
     update_domain_wallclock_time(d);
diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/mm.c Sat May 12 12:07:01 2007 +0100
@@ -3402,6 +3402,18 @@ int ptwr_do_page_fault(struct vcpu *v, u
     return 0;
 }
 
+void free_xen_pagetable(void *v)
+{
+    extern int early_boot;
+
+    BUG_ON(early_boot);
+    
+    if ( is_xen_heap_frame(virt_to_page(v)) )
+        free_xenheap_page(v);
+    else
+        free_domheap_page(virt_to_page(v));
+}
+
 int map_pages_to_xen(
     unsigned long virt,
     unsigned long mfn,
@@ -3475,6 +3487,73 @@ int map_pages_to_xen(
     return 0;
 }
 
+void destroy_xen_mappings(unsigned long s, unsigned long e)
+{
+    l2_pgentry_t *pl2e;
+    l1_pgentry_t *pl1e;
+    unsigned int  i;
+    unsigned long v = s;
+
+    ASSERT((s & ~PAGE_MASK) == 0);
+    ASSERT((e & ~PAGE_MASK) == 0);
+
+    while ( v < e )
+    {
+        pl2e = virt_to_xen_l2e(v);
+
+        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+        {
+            v += PAGE_SIZE;
+            continue;
+        }
+
+        if ( l2e_get_flags(*pl2e) & _PAGE_PSE )
+        {
+            if ( (l1_table_offset(v) == 0) &&
+                 ((e-v) >= (1UL << L2_PAGETABLE_SHIFT)) )
+            {
+                /* PSE: whole superpage is destroyed. */
+                l2e_write_atomic(pl2e, l2e_empty());
+                v += 1UL << L2_PAGETABLE_SHIFT;
+            }
+            else
+            {
+                /* PSE: shatter the superpage and try again. */
+                pl1e = alloc_xen_pagetable();
+                for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
+                    l1e_write(&pl1e[i],
+                              l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
+                                           l2e_get_flags(*pl2e) & ~_PAGE_PSE));
+                l2e_write_atomic(pl2e, l2e_from_pfn(virt_to_mfn(pl1e),
+                                                    __PAGE_HYPERVISOR));
+            }
+        }
+        else
+        {
+            /* Ordinary 4kB mapping. */
+            pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(v);
+            l1e_write_atomic(pl1e, l1e_empty());
+            v += PAGE_SIZE;
+
+            /* If we are done with the L2E, check if it is now empty. */
+            if ( (v != e) && (l1_table_offset(v) != 0) )
+                continue;
+            pl1e = l2e_to_l1e(*pl2e);
+            for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
+                if ( l1e_get_intpte(pl1e[i]) != 0 )
+                    break;
+            if ( i == L1_PAGETABLE_ENTRIES )
+            {
+                /* Empty: zap the L2E and free the L1 page. */
+                l2e_write_atomic(pl2e, l2e_empty());
+                free_xen_pagetable(pl1e);
+            }
+        }
+    }
+
+    flush_tlb_all_pge();
+}
+
 void __set_fixmap(
     enum fixed_addresses idx, unsigned long mfn, unsigned long flags)
 {
diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/setup.c      Sat May 12 12:07:01 2007 +0100
@@ -779,6 +779,11 @@ void __init __start_xen(multiboot_info_t
     if ( smp_found_config )
         get_smp_config();
 
+#ifdef CONFIG_X86_64
+    /* Low mappings were only needed for some BIOS table parsing. */
+    zap_low_mappings();
+#endif
+
     init_apic_mappings();
 
     init_IRQ();
diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/smpboot.c    Sat May 12 12:07:01 2007 +0100
@@ -1162,9 +1162,6 @@ void __init smp_cpus_done(unsigned int m
 #ifdef CONFIG_X86_IO_APIC
        setup_ioapic_dest();
 #endif
-#ifdef CONFIG_X86_64
-       zap_low_mappings();
-#endif
 #ifndef CONFIG_HOTPLUG_CPU
        /*
         * Disable executability of the SMP trampoline:
diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/x86_32/mm.c  Sat May 12 12:07:01 2007 +0100
@@ -61,11 +61,6 @@ void *alloc_xen_pagetable(void)
     return mfn_to_virt(mfn);
 }
 
-void free_xen_pagetable(void *v)
-{
-    free_xenheap_page(v);
-}
-
 l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
 {
     return &idle_pg_table_l2[l2_linear_offset(v)];
@@ -141,22 +136,24 @@ void __init setup_idle_pagetable(void)
                                 __PAGE_HYPERVISOR));
 }
 
-void __init zap_low_mappings(l2_pgentry_t *base)
+void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
 {
     int i;
-    u32 addr;
-
-    for ( i = 0; ; i++ )
-    {
-        addr = i << L2_PAGETABLE_SHIFT;
-        if ( addr >= HYPERVISOR_VIRT_START )
-            break;
-        if ( l2e_get_paddr(base[i]) != addr )
-            continue;
-        l2e_write(&base[i], l2e_empty());
-    }
+
+    /* Clear temporary idle mappings from the dom0 initial l2. */
+    for ( i = 0; i < (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT); i++ )
+        if ( l2e_get_intpte(dom0_l2[i]) ==
+             l2e_get_intpte(idle_pg_table_l2[i]) )
+            l2e_write(&dom0_l2[i], l2e_empty());
+
+    /* Now zap mappings in the idle pagetables. */
+    destroy_xen_mappings(0, HYPERVISOR_VIRT_START);
 
     flush_tlb_all_pge();
+
+    /* Replace with mapping of the boot trampoline only. */
+    map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
+                     0x10, __PAGE_HYPERVISOR);
 }
 
 void __init subarch_init_memory(void)
diff -r 759d924af6d8 -r 03a13457d993 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Sat May 12 10:28:53 2007 +0100
+++ b/xen/arch/x86/x86_64/mm.c  Sat May 12 12:07:01 2007 +0100
@@ -68,11 +68,6 @@ void *alloc_xen_pagetable(void)
     mfn = alloc_boot_low_pages(1, 1); /* 0x0 - 0x40000000 */
     BUG_ON(mfn == 0);
     return mfn_to_virt(mfn);
-}
-
-void free_xen_pagetable(void *v)
-{
-    free_domheap_page(virt_to_page(v));
 }
 
 l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
@@ -209,8 +204,15 @@ void __init setup_idle_pagetable(void)
 
 void __init zap_low_mappings(void)
 {
+    BUG_ON(num_online_cpus() != 1);
+
+    /* Remove aliased mapping of first 1:1 PML4 entry. */
     l4e_write(&idle_pg_table[0], l4e_empty());
-    flush_tlb_all_pge();
+    local_flush_tlb_pge();
+
+    /* Replace with mapping of the boot trampoline only. */
+    map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
+                     0x10, __PAGE_HYPERVISOR);
 }
 
 void __init subarch_init_memory(void)
diff -r 759d924af6d8 -r 03a13457d993 xen/include/asm-x86/page.h
--- a/xen/include/asm-x86/page.h        Sat May 12 10:28:53 2007 +0100
+++ b/xen/include/asm-x86/page.h        Sat May 12 12:07:01 2007 +0100
@@ -1,4 +1,3 @@
-
 #ifndef __X86_PAGE_H__
 #define __X86_PAGE_H__
 
@@ -369,6 +368,7 @@ map_pages_to_xen(
     unsigned long mfn,
     unsigned long nr_mfns,
     unsigned long flags);
+void destroy_xen_mappings(unsigned long v, unsigned long e);
 
 #endif /* !__ASSEMBLY__ */
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.