# 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
|