ia64/xen-unstable

changeset 12853:4ce643274b67

[XEN] Early page fault handler to deal with spurious page faults.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Dec 07 14:03:54 2006 +0000 (2006-12-07)
parents 27294bab3d62
children dcca88fc849c
files xen/arch/x86/crash.c xen/arch/x86/setup.c xen/arch/x86/traps.c xen/arch/x86/x86_32/domain_page.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/entry.S xen/include/xen/domain_page.h
line diff
     1.1 --- a/xen/arch/x86/crash.c	Thu Dec 07 13:47:13 2006 +0000
     1.2 +++ b/xen/arch/x86/crash.c	Thu Dec 07 14:03:54 2006 +0000
     1.3 @@ -27,7 +27,6 @@
     1.4  #include <public/xen.h>
     1.5  #include <asm/hvm/hvm.h>
     1.6  
     1.7 -#ifdef CONFIG_SMP
     1.8  static atomic_t waiting_for_crash_ipi;
     1.9  
    1.10  static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
    1.11 @@ -71,9 +70,7 @@ static void nmi_shootdown_cpus(void)
    1.12      atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
    1.13      /* Would it be better to replace the trap vector here? */
    1.14      set_nmi_callback(crash_nmi_callback);
    1.15 -    /* Ensure the new callback function is set before sending
    1.16 -     * out the NMI
    1.17 -     */
    1.18 +    /* Ensure the new callback function is set before sending out the NMI. */
    1.19      wmb();
    1.20  
    1.21      smp_send_nmi_allbutself();
    1.22 @@ -88,7 +85,6 @@ static void nmi_shootdown_cpus(void)
    1.23      /* Leave the nmi callback set */
    1.24      disable_local_APIC();
    1.25  }
    1.26 -#endif
    1.27  
    1.28  static void crash_save_xen_notes(void)
    1.29  {
    1.30 @@ -102,16 +98,12 @@ static void crash_save_xen_notes(void)
    1.31  
    1.32  void machine_crash_shutdown(void)
    1.33  {
    1.34 -    printk("machine_crash_shutdown: %d\n", smp_processor_id());
    1.35      local_irq_disable();
    1.36  
    1.37 -#ifdef CONFIG_SMP
    1.38      nmi_shootdown_cpus();
    1.39 -#endif
    1.40  
    1.41 -#ifdef CONFIG_X86_IO_APIC
    1.42      disable_IO_APIC();
    1.43 -#endif
    1.44 +
    1.45      hvm_disable();
    1.46  
    1.47      crash_save_xen_notes();
     2.1 --- a/xen/arch/x86/setup.c	Thu Dec 07 13:47:13 2006 +0000
     2.2 +++ b/xen/arch/x86/setup.c	Thu Dec 07 14:03:54 2006 +0000
     2.3 @@ -305,6 +305,9 @@ void __init __start_xen(multiboot_info_t
     2.4          .stop_bits = 1
     2.5      };
     2.6  
     2.7 +    extern void early_page_fault(void);
     2.8 +    set_intr_gate(TRAP_page_fault, &early_page_fault);
     2.9 +
    2.10      /* Parse the command-line options. */
    2.11      if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
    2.12          cmdline = __va(mbi->cmdline);
    2.13 @@ -501,21 +504,19 @@ void __init __start_xen(multiboot_info_t
    2.14          kdump_start >>= PAGE_SHIFT;
    2.15          kdump_size >>= PAGE_SHIFT;
    2.16  
    2.17 -        /* allocate pages for Kdump memory area */
    2.18 +        /* Allocate pages for Kdump memory area. */
    2.19  
    2.20          k = alloc_boot_pages_at(kdump_size, kdump_start);
    2.21 -
    2.22          if ( k != kdump_start )
    2.23              panic("Unable to reserve Kdump memory\n");
    2.24  
    2.25 -        /* allocate pages for relocated initial images */
    2.26 +        /* Allocate pages for relocated initial images. */
    2.27  
    2.28          k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
    2.29          k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
    2.30  
    2.31          k = alloc_boot_pages(k, 1);
    2.32 -
    2.33 -        if ( !k )
    2.34 +        if ( k == 0 )
    2.35              panic("Unable to allocate initial images memory\n");
    2.36  
    2.37          move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
     3.1 --- a/xen/arch/x86/traps.c	Thu Dec 07 13:47:13 2006 +0000
     3.2 +++ b/xen/arch/x86/traps.c	Thu Dec 07 14:03:54 2006 +0000
     3.3 @@ -935,6 +935,37 @@ asmlinkage int do_page_fault(struct cpu_
     3.4      return 0;
     3.5  }
     3.6  
     3.7 +/*
     3.8 + * Early handler to deal with spurious page faults. For example, consider a 
     3.9 + * routine that uses a mapping immediately after installing it (making it 
    3.10 + * present). The CPU may speculatively execute the memory access before 
    3.11 + * executing the PTE write. The instruction will then be marked to cause a 
    3.12 + * page fault when it is retired, despite the fact that the PTE is present and 
    3.13 + * correct at that point in time.
    3.14 + */
    3.15 +asmlinkage int do_early_page_fault(struct cpu_user_regs *regs)
    3.16 +{
    3.17 +    static int stuck;
    3.18 +    static unsigned long prev_eip, prev_cr2;
    3.19 +    unsigned long cr2 = read_cr2();
    3.20 +
    3.21 +    BUG_ON(smp_processor_id() != 0);
    3.22 +
    3.23 +    if ( (regs->eip != prev_eip) || (cr2 != prev_cr2) )
    3.24 +    {
    3.25 +        prev_eip = regs->eip;
    3.26 +        prev_cr2 = cr2;
    3.27 +        stuck    = 0;
    3.28 +        return EXCRET_not_a_fault;
    3.29 +    }
    3.30 +
    3.31 +    if ( stuck++ == 1000 )
    3.32 +        panic("Early fatal page fault at %04x:%p (cr2=%p, ec=%04x)\n", 
    3.33 +              regs->cs, _p(regs->eip), _p(cr2), regs->error_code);
    3.34 +
    3.35 +    return EXCRET_not_a_fault;
    3.36 +}
    3.37 +
    3.38  long do_fpu_taskswitch(int set)
    3.39  {
    3.40      struct vcpu *v = current;
     4.1 --- a/xen/arch/x86/x86_32/domain_page.c	Thu Dec 07 13:47:13 2006 +0000
     4.2 +++ b/xen/arch/x86/x86_32/domain_page.c	Thu Dec 07 14:03:54 2006 +0000
     4.3 @@ -252,29 +252,3 @@ void unmap_domain_page_global(void *va)
     4.4      idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT;
     4.5      set_bit(idx, garbage);
     4.6  }
     4.7 -
     4.8 -paddr_t maddr_from_mapped_domain_page(void *va) 
     4.9 -{
    4.10 -    unsigned long __va = (unsigned long)va;
    4.11 -    l2_pgentry_t *pl2e;
    4.12 -    l1_pgentry_t *pl1e;
    4.13 -    unsigned int idx;
    4.14 -    struct mapcache *cache;
    4.15 -    unsigned long mfn;
    4.16 -
    4.17 -    if ( (__va >= MAPCACHE_VIRT_START) && (__va < MAPCACHE_VIRT_END) )
    4.18 -    {
    4.19 -        cache = &mapcache_current_vcpu()->domain->arch.mapcache;
    4.20 -        idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT;
    4.21 -        mfn = l1e_get_pfn(cache->l1tab[idx]);
    4.22 -    }
    4.23 -    else
    4.24 -    {
    4.25 -        ASSERT(__va >= IOREMAP_VIRT_START);
    4.26 -        pl2e = virt_to_xen_l2e(__va);
    4.27 -        pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va);
    4.28 -        mfn = l1e_get_pfn(*pl1e);
    4.29 -    }
    4.30 -    
    4.31 -    return ((paddr_t)mfn << PAGE_SHIFT) | ((unsigned long)va & ~PAGE_MASK);
    4.32 -}
     5.1 --- a/xen/arch/x86/x86_32/entry.S	Thu Dec 07 13:47:13 2006 +0000
     5.2 +++ b/xen/arch/x86/x86_32/entry.S	Thu Dec 07 14:03:54 2006 +0000
     5.3 @@ -536,6 +536,14 @@ ENTRY(spurious_interrupt_bug)
     5.4          pushl $TRAP_spurious_int<<16
     5.5          jmp   handle_exception
     5.6  
     5.7 +ENTRY(early_page_fault)
     5.8 +        SAVE_ALL_NOSEGREGS(a)
     5.9 +        movl  %esp,%edx
    5.10 +        pushl %edx
    5.11 +        call  do_early_page_fault
    5.12 +        addl  $4,%esp
    5.13 +        jmp   restore_all_xen
    5.14 +
    5.15  ENTRY(nmi)
    5.16  #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
    5.17          # NMI entry protocol is incompatible with guest kernel in ring 0.
     6.1 --- a/xen/arch/x86/x86_64/entry.S	Thu Dec 07 13:47:13 2006 +0000
     6.2 +++ b/xen/arch/x86/x86_64/entry.S	Thu Dec 07 14:03:54 2006 +0000
     6.3 @@ -478,6 +478,12 @@ ENTRY(double_fault)
     6.4          call  do_double_fault
     6.5          ud2
     6.6  
     6.7 +ENTRY(early_page_fault)
     6.8 +        SAVE_ALL
     6.9 +        movq  %rsp,%rdi
    6.10 +        call  do_early_page_fault
    6.11 +        jmp   restore_all_xen
    6.12 +
    6.13  ENTRY(nmi)
    6.14          pushq $0
    6.15          SAVE_ALL
     7.1 --- a/xen/include/xen/domain_page.h	Thu Dec 07 13:47:13 2006 +0000
     7.2 +++ b/xen/include/xen/domain_page.h	Thu Dec 07 14:03:54 2006 +0000
     7.3 @@ -34,13 +34,6 @@ void unmap_domain_page(void *va);
     7.4  void *map_domain_page_global(unsigned long mfn);
     7.5  void unmap_domain_page_global(void *va);
     7.6  
     7.7 -/* 
     7.8 - * Convert a VA (within a page previously mapped in the context of the
     7.9 - * currently-executing VCPU via a call to map_domain_page(), or via a
    7.10 - * previous call to map_domain_page_global()) to the mapped machine address.
    7.11 - */
    7.12 -paddr_t maddr_from_mapped_domain_page(void *va);
    7.13 -
    7.14  #define DMCACHE_ENTRY_VALID 1U
    7.15  #define DMCACHE_ENTRY_HELD  2U
    7.16  
    7.17 @@ -109,8 +102,6 @@ domain_mmap_cache_destroy(struct domain_
    7.18  #define map_domain_page_global(mfn)         maddr_to_virt((mfn)<<PAGE_SHIFT)
    7.19  #define unmap_domain_page_global(va)        ((void)(va))
    7.20  
    7.21 -#define maddr_from_mapped_domain_page(va)   (virt_to_maddr(va))
    7.22 -
    7.23  struct domain_mmap_cache { 
    7.24  };
    7.25