ia64/xen-unstable

changeset 6720:3f4d14357976

pagefault handler fixes.
author kaf24@firebug.cl.cam.ac.uk
date Fri Sep 09 13:28:23 2005 +0000 (2005-09-09)
parents 47dca2f335de
children ec4a3f2d060e
files xen/arch/x86/mm.c xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/mm.c	Fri Sep 09 13:20:51 2005 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Fri Sep 09 13:28:23 2005 +0000
     1.3 @@ -3185,7 +3185,7 @@ int ptwr_do_page_fault(struct domain *d,
     1.4      struct pfn_info *page;
     1.5      l1_pgentry_t     pte;
     1.6      l2_pgentry_t    *pl2e, l2e;
     1.7 -    int              which;
     1.8 +    int              which, flags;
     1.9      unsigned long    l2_idx;
    1.10  
    1.11      if ( unlikely(shadow_mode_enabled(d)) )
    1.12 @@ -3206,8 +3206,24 @@ int ptwr_do_page_fault(struct domain *d,
    1.13      pfn  = l1e_get_pfn(pte);
    1.14      page = &frame_table[pfn];
    1.15  
    1.16 +#ifdef CONFIG_X86_64
    1.17 +#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
    1.18 +#else
    1.19 +#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT)
    1.20 +#endif
    1.21 +
    1.22 +    /*
    1.23 +     * Check the required flags for a valid wrpt mapping. If the page is
    1.24 +     * already writable then we can return straight to the guest (SMP race).
    1.25 +     * We decide whether or not to propagate the fault by testing for write
    1.26 +     * permissions in page directories by writing back to the linear mapping.
    1.27 +     */
    1.28 +    if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS )
    1.29 +        return !__put_user(
    1.30 +            pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1);
    1.31 +
    1.32      /* We are looking only for read-only mappings of p.t. pages. */
    1.33 -    if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
    1.34 +    if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) ||
    1.35           ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
    1.36           ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
    1.37           (page_get_owner(page) != d) )
     2.1 --- a/xen/arch/x86/traps.c	Fri Sep 09 13:20:51 2005 +0000
     2.2 +++ b/xen/arch/x86/traps.c	Fri Sep 09 13:28:23 2005 +0000
     2.3 @@ -470,20 +470,32 @@ static int handle_perdomain_mapping_faul
     2.4      return EXCRET_fault_fixed;
     2.5  }
     2.6  
     2.7 -asmlinkage int do_page_fault(struct cpu_user_regs *regs)
     2.8 +#ifdef HYPERVISOR_VIRT_END
     2.9 +#define IN_HYPERVISOR_RANGE(va) \
    2.10 +    (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
    2.11 +#else
    2.12 +#define IN_HYPERVISOR_RANGE(va) \
    2.13 +    (((va) >= HYPERVISOR_VIRT_START))
    2.14 +#endif
    2.15 +
    2.16 +static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
    2.17  {
    2.18 -    unsigned long addr, fixup;
    2.19 -    struct vcpu *v = current;
    2.20 +    struct vcpu   *v = current;
    2.21      struct domain *d = v->domain;
    2.22  
    2.23 -    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
    2.24 -
    2.25 -    DEBUGGER_trap_entry(TRAP_page_fault, regs);
    2.26 -
    2.27 -    perfc_incrc(page_faults);
    2.28 -
    2.29 -    if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
    2.30 -                !shadow_mode_enabled(d)) )
    2.31 +    if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
    2.32 +    {
    2.33 +        if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
    2.34 +            return shadow_fault(addr, regs);
    2.35 +        if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) )
    2.36 +            return handle_perdomain_mapping_fault(
    2.37 +                addr - PERDOMAIN_VIRT_START, regs);
    2.38 +    }
    2.39 +    else if ( unlikely(shadow_mode_enabled(d)) )
    2.40 +    {
    2.41 +        return shadow_fault(addr, regs);
    2.42 +    }
    2.43 +    else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
    2.44      {
    2.45          LOCK_BIGLOCK(d);
    2.46          if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
    2.47 @@ -495,14 +507,9 @@ asmlinkage int do_page_fault(struct cpu_
    2.48              return EXCRET_fault_fixed;
    2.49          }
    2.50  
    2.51 -        if ( ((addr < HYPERVISOR_VIRT_START) 
    2.52 -#if defined(__x86_64__)
    2.53 -              || (addr >= HYPERVISOR_VIRT_END)
    2.54 -#endif        
    2.55 -            )     
    2.56 -             &&
    2.57 -             KERNEL_MODE(v, regs) &&
    2.58 -             ((regs->error_code & 3) == 3) && /* write-protection fault */
    2.59 +        if ( KERNEL_MODE(v, regs) &&
    2.60 +             /* Protection violation on write? No reserved-bit violation? */
    2.61 +             ((regs->error_code & 0xb) == 0x3) &&
    2.62               ptwr_do_page_fault(d, addr, regs) )
    2.63          {
    2.64              UNLOCK_BIGLOCK(d);
    2.65 @@ -511,44 +518,52 @@ asmlinkage int do_page_fault(struct cpu_
    2.66          UNLOCK_BIGLOCK(d);
    2.67      }
    2.68  
    2.69 -    if ( unlikely(shadow_mode_enabled(d)) &&
    2.70 -         ((addr < HYPERVISOR_VIRT_START) ||
    2.71 -#if defined(__x86_64__)
    2.72 -          (addr >= HYPERVISOR_VIRT_END) ||
    2.73 -#endif
    2.74 -          (shadow_mode_external(d) && GUEST_CONTEXT(v, regs))) &&
    2.75 -         shadow_fault(addr, regs) )
    2.76 -        return EXCRET_fault_fixed;
    2.77 +    return 0;
    2.78 +}
    2.79 +
    2.80 +/*
    2.81 + * #PF error code:
    2.82 + *  Bit 0: Protection violation (=1) ; Page not present (=0)
    2.83 + *  Bit 1: Write access
    2.84 + *  Bit 2: Supervisor mode
    2.85 + *  Bit 3: Reserved bit violation
    2.86 + *  Bit 4: Instruction fetch
    2.87 + */
    2.88 +asmlinkage int do_page_fault(struct cpu_user_regs *regs)
    2.89 +{
    2.90 +    unsigned long addr, fixup;
    2.91 +    int rc;
    2.92 +
    2.93 +    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
    2.94 +
    2.95 +    DEBUGGER_trap_entry(TRAP_page_fault, regs);
    2.96 +
    2.97 +    perfc_incrc(page_faults);
    2.98  
    2.99 -    if ( unlikely(addr >= PERDOMAIN_VIRT_START) &&
   2.100 -         unlikely(addr < PERDOMAIN_VIRT_END) &&
   2.101 -         handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) )
   2.102 -        return EXCRET_fault_fixed;
   2.103 +    if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
   2.104 +        return rc;
   2.105  
   2.106 -    if ( !GUEST_MODE(regs) )
   2.107 -        goto xen_fault;
   2.108 +    if ( unlikely(!GUEST_MODE(regs)) )
   2.109 +    {
   2.110 +        if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
   2.111 +        {
   2.112 +            perfc_incrc(copy_user_faults);
   2.113 +            regs->eip = fixup;
   2.114 +            return 0;
   2.115 +        }
   2.116 +
   2.117 +        DEBUGGER_trap_fatal(TRAP_page_fault, regs);
   2.118 +
   2.119 +        show_registers(regs);
   2.120 +        show_page_walk(addr);
   2.121 +        panic("CPU%d FATAL PAGE FAULT\n"
   2.122 +              "[error_code=%04x]\n"
   2.123 +              "Faulting linear address: %p\n",
   2.124 +              smp_processor_id(), regs->error_code, addr);
   2.125 +    }
   2.126  
   2.127      propagate_page_fault(addr, regs->error_code);
   2.128      return 0;
   2.129 -
   2.130 - xen_fault:
   2.131 -
   2.132 -    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
   2.133 -    {
   2.134 -        perfc_incrc(copy_user_faults);
   2.135 -        regs->eip = fixup;
   2.136 -        return 0;
   2.137 -    }
   2.138 -
   2.139 -    DEBUGGER_trap_fatal(TRAP_page_fault, regs);
   2.140 -
   2.141 -    show_registers(regs);
   2.142 -    show_page_walk(addr);
   2.143 -    panic("CPU%d FATAL PAGE FAULT\n"
   2.144 -          "[error_code=%04x]\n"
   2.145 -          "Faulting linear address: %p\n",
   2.146 -          smp_processor_id(), regs->error_code, addr);
   2.147 -    return 0;
   2.148  }
   2.149  
   2.150  long do_fpu_taskswitch(int set)