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

[Xen-changelog] [xen-unstable] [XEN] Early page fault handler to deal with spurious page faults.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 4ce643274b67c3aaea83ecd3f2f7133c0d599b88
# Parent  27294bab3d624d570fe3dadeb9988b7759bd774b
[XEN] Early page fault handler to deal with spurious page faults.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/crash.c              |   12 ++----------
 xen/arch/x86/setup.c              |   11 ++++++-----
 xen/arch/x86/traps.c              |   31 +++++++++++++++++++++++++++++++
 xen/arch/x86/x86_32/domain_page.c |   26 --------------------------
 xen/arch/x86/x86_32/entry.S       |    8 ++++++++
 xen/arch/x86/x86_64/entry.S       |    6 ++++++
 xen/include/xen/domain_page.h     |    9 ---------
 7 files changed, 53 insertions(+), 50 deletions(-)

diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/crash.c
--- a/xen/arch/x86/crash.c      Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/crash.c      Thu Dec 07 14:03:54 2006 +0000
@@ -27,7 +27,6 @@
 #include <public/xen.h>
 #include <asm/hvm/hvm.h>
 
-#ifdef CONFIG_SMP
 static atomic_t waiting_for_crash_ipi;
 
 static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
@@ -71,9 +70,7 @@ static void nmi_shootdown_cpus(void)
     atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
     /* Would it be better to replace the trap vector here? */
     set_nmi_callback(crash_nmi_callback);
-    /* Ensure the new callback function is set before sending
-     * out the NMI
-     */
+    /* Ensure the new callback function is set before sending out the NMI. */
     wmb();
 
     smp_send_nmi_allbutself();
@@ -88,7 +85,6 @@ static void nmi_shootdown_cpus(void)
     /* Leave the nmi callback set */
     disable_local_APIC();
 }
-#endif
 
 static void crash_save_xen_notes(void)
 {
@@ -102,16 +98,12 @@ static void crash_save_xen_notes(void)
 
 void machine_crash_shutdown(void)
 {
-    printk("machine_crash_shutdown: %d\n", smp_processor_id());
     local_irq_disable();
 
-#ifdef CONFIG_SMP
     nmi_shootdown_cpus();
-#endif
 
-#ifdef CONFIG_X86_IO_APIC
     disable_IO_APIC();
-#endif
+
     hvm_disable();
 
     crash_save_xen_notes();
diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/setup.c      Thu Dec 07 14:03:54 2006 +0000
@@ -305,6 +305,9 @@ void __init __start_xen(multiboot_info_t
         .stop_bits = 1
     };
 
+    extern void early_page_fault(void);
+    set_intr_gate(TRAP_page_fault, &early_page_fault);
+
     /* Parse the command-line options. */
     if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
         cmdline = __va(mbi->cmdline);
@@ -501,21 +504,19 @@ void __init __start_xen(multiboot_info_t
         kdump_start >>= PAGE_SHIFT;
         kdump_size >>= PAGE_SHIFT;
 
-        /* allocate pages for Kdump memory area */
+        /* Allocate pages for Kdump memory area. */
 
         k = alloc_boot_pages_at(kdump_size, kdump_start);
-
         if ( k != kdump_start )
             panic("Unable to reserve Kdump memory\n");
 
-        /* allocate pages for relocated initial images */
+        /* Allocate pages for relocated initial images. */
 
         k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
         k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
 
         k = alloc_boot_pages(k, 1);
-
-        if ( !k )
+        if ( k == 0 )
             panic("Unable to allocate initial images memory\n");
 
         move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/traps.c      Thu Dec 07 14:03:54 2006 +0000
@@ -935,6 +935,37 @@ asmlinkage int do_page_fault(struct cpu_
     return 0;
 }
 
+/*
+ * Early handler to deal with spurious page faults. For example, consider a 
+ * routine that uses a mapping immediately after installing it (making it 
+ * present). The CPU may speculatively execute the memory access before 
+ * executing the PTE write. The instruction will then be marked to cause a 
+ * page fault when it is retired, despite the fact that the PTE is present and 
+ * correct at that point in time.
+ */
+asmlinkage int do_early_page_fault(struct cpu_user_regs *regs)
+{
+    static int stuck;
+    static unsigned long prev_eip, prev_cr2;
+    unsigned long cr2 = read_cr2();
+
+    BUG_ON(smp_processor_id() != 0);
+
+    if ( (regs->eip != prev_eip) || (cr2 != prev_cr2) )
+    {
+        prev_eip = regs->eip;
+        prev_cr2 = cr2;
+        stuck    = 0;
+        return EXCRET_not_a_fault;
+    }
+
+    if ( stuck++ == 1000 )
+        panic("Early fatal page fault at %04x:%p (cr2=%p, ec=%04x)\n", 
+              regs->cs, _p(regs->eip), _p(cr2), regs->error_code);
+
+    return EXCRET_not_a_fault;
+}
+
 long do_fpu_taskswitch(int set)
 {
     struct vcpu *v = current;
diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/x86_32/domain_page.c
--- a/xen/arch/x86/x86_32/domain_page.c Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/x86_32/domain_page.c Thu Dec 07 14:03:54 2006 +0000
@@ -252,29 +252,3 @@ void unmap_domain_page_global(void *va)
     idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT;
     set_bit(idx, garbage);
 }
-
-paddr_t maddr_from_mapped_domain_page(void *va) 
-{
-    unsigned long __va = (unsigned long)va;
-    l2_pgentry_t *pl2e;
-    l1_pgentry_t *pl1e;
-    unsigned int idx;
-    struct mapcache *cache;
-    unsigned long mfn;
-
-    if ( (__va >= MAPCACHE_VIRT_START) && (__va < MAPCACHE_VIRT_END) )
-    {
-        cache = &mapcache_current_vcpu()->domain->arch.mapcache;
-        idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT;
-        mfn = l1e_get_pfn(cache->l1tab[idx]);
-    }
-    else
-    {
-        ASSERT(__va >= IOREMAP_VIRT_START);
-        pl2e = virt_to_xen_l2e(__va);
-        pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va);
-        mfn = l1e_get_pfn(*pl1e);
-    }
-    
-    return ((paddr_t)mfn << PAGE_SHIFT) | ((unsigned long)va & ~PAGE_MASK);
-}
diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/x86_32/entry.S       Thu Dec 07 14:03:54 2006 +0000
@@ -536,6 +536,14 @@ ENTRY(spurious_interrupt_bug)
         pushl $TRAP_spurious_int<<16
         jmp   handle_exception
 
+ENTRY(early_page_fault)
+        SAVE_ALL_NOSEGREGS(a)
+        movl  %esp,%edx
+        pushl %edx
+        call  do_early_page_fault
+        addl  $4,%esp
+        jmp   restore_all_xen
+
 ENTRY(nmi)
 #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
         # NMI entry protocol is incompatible with guest kernel in ring 0.
diff -r 27294bab3d62 -r 4ce643274b67 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/arch/x86/x86_64/entry.S       Thu Dec 07 14:03:54 2006 +0000
@@ -478,6 +478,12 @@ ENTRY(double_fault)
         call  do_double_fault
         ud2
 
+ENTRY(early_page_fault)
+        SAVE_ALL
+        movq  %rsp,%rdi
+        call  do_early_page_fault
+        jmp   restore_all_xen
+
 ENTRY(nmi)
         pushq $0
         SAVE_ALL
diff -r 27294bab3d62 -r 4ce643274b67 xen/include/xen/domain_page.h
--- a/xen/include/xen/domain_page.h     Thu Dec 07 13:47:13 2006 +0000
+++ b/xen/include/xen/domain_page.h     Thu Dec 07 14:03:54 2006 +0000
@@ -33,13 +33,6 @@ void unmap_domain_page(void *va);
  */
 void *map_domain_page_global(unsigned long mfn);
 void unmap_domain_page_global(void *va);
-
-/* 
- * Convert a VA (within a page previously mapped in the context of the
- * currently-executing VCPU via a call to map_domain_page(), or via a
- * previous call to map_domain_page_global()) to the mapped machine address.
- */
-paddr_t maddr_from_mapped_domain_page(void *va);
 
 #define DMCACHE_ENTRY_VALID 1U
 #define DMCACHE_ENTRY_HELD  2U
@@ -109,8 +102,6 @@ domain_mmap_cache_destroy(struct domain_
 #define map_domain_page_global(mfn)         maddr_to_virt((mfn)<<PAGE_SHIFT)
 #define unmap_domain_page_global(va)        ((void)(va))
 
-#define maddr_from_mapped_domain_page(va)   (virt_to_maddr(va))
-
 struct domain_mmap_cache { 
 };
 

_______________________________________________
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®.