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

[Xen-changelog] pagefault handler fixes.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 3f4d143579763d6f280146c8f0d49922c55ae82d
# Parent  47dca2f335de3493e9bcef04459a7d37ccc5ebf0
pagefault handler fixes.

diff -r 47dca2f335de -r 3f4d14357976 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Sep  9 13:20:51 2005
+++ b/xen/arch/x86/mm.c Fri Sep  9 13:28:23 2005
@@ -3185,7 +3185,7 @@
     struct pfn_info *page;
     l1_pgentry_t     pte;
     l2_pgentry_t    *pl2e, l2e;
-    int              which;
+    int              which, flags;
     unsigned long    l2_idx;
 
     if ( unlikely(shadow_mode_enabled(d)) )
@@ -3206,8 +3206,24 @@
     pfn  = l1e_get_pfn(pte);
     page = &frame_table[pfn];
 
+#ifdef CONFIG_X86_64
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
+#else
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT)
+#endif
+
+    /*
+     * Check the required flags for a valid wrpt mapping. If the page is
+     * already writable then we can return straight to the guest (SMP race).
+     * We decide whether or not to propagate the fault by testing for write
+     * permissions in page directories by writing back to the linear mapping.
+     */
+    if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS )
+        return !__put_user(
+            pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1);
+
     /* We are looking only for read-only mappings of p.t. pages. */
-    if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
+    if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) ||
          ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
          ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
          (page_get_owner(page) != d) )
diff -r 47dca2f335de -r 3f4d14357976 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Fri Sep  9 13:20:51 2005
+++ b/xen/arch/x86/traps.c      Fri Sep  9 13:28:23 2005
@@ -470,20 +470,32 @@
     return EXCRET_fault_fixed;
 }
 
-asmlinkage int do_page_fault(struct cpu_user_regs *regs)
-{
-    unsigned long addr, fixup;
-    struct vcpu *v = current;
+#ifdef HYPERVISOR_VIRT_END
+#define IN_HYPERVISOR_RANGE(va) \
+    (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
+#else
+#define IN_HYPERVISOR_RANGE(va) \
+    (((va) >= HYPERVISOR_VIRT_START))
+#endif
+
+static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
+{
+    struct vcpu   *v = current;
     struct domain *d = v->domain;
 
-    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
-
-    DEBUGGER_trap_entry(TRAP_page_fault, regs);
-
-    perfc_incrc(page_faults);
-
-    if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
-                !shadow_mode_enabled(d)) )
+    if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
+    {
+        if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
+            return shadow_fault(addr, regs);
+        if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) )
+            return handle_perdomain_mapping_fault(
+                addr - PERDOMAIN_VIRT_START, regs);
+    }
+    else if ( unlikely(shadow_mode_enabled(d)) )
+    {
+        return shadow_fault(addr, regs);
+    }
+    else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
     {
         LOCK_BIGLOCK(d);
         if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
@@ -495,14 +507,9 @@
             return EXCRET_fault_fixed;
         }
 
-        if ( ((addr < HYPERVISOR_VIRT_START) 
-#if defined(__x86_64__)
-              || (addr >= HYPERVISOR_VIRT_END)
-#endif        
-            )     
-             &&
-             KERNEL_MODE(v, regs) &&
-             ((regs->error_code & 3) == 3) && /* write-protection fault */
+        if ( KERNEL_MODE(v, regs) &&
+             /* Protection violation on write? No reserved-bit violation? */
+             ((regs->error_code & 0xb) == 0x3) &&
              ptwr_do_page_fault(d, addr, regs) )
         {
             UNLOCK_BIGLOCK(d);
@@ -511,43 +518,51 @@
         UNLOCK_BIGLOCK(d);
     }
 
-    if ( unlikely(shadow_mode_enabled(d)) &&
-         ((addr < HYPERVISOR_VIRT_START) ||
-#if defined(__x86_64__)
-          (addr >= HYPERVISOR_VIRT_END) ||
-#endif
-          (shadow_mode_external(d) && GUEST_CONTEXT(v, regs))) &&
-         shadow_fault(addr, regs) )
-        return EXCRET_fault_fixed;
-
-    if ( unlikely(addr >= PERDOMAIN_VIRT_START) &&
-         unlikely(addr < PERDOMAIN_VIRT_END) &&
-         handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) )
-        return EXCRET_fault_fixed;
-
-    if ( !GUEST_MODE(regs) )
-        goto xen_fault;
+    return 0;
+}
+
+/*
+ * #PF error code:
+ *  Bit 0: Protection violation (=1) ; Page not present (=0)
+ *  Bit 1: Write access
+ *  Bit 2: Supervisor mode
+ *  Bit 3: Reserved bit violation
+ *  Bit 4: Instruction fetch
+ */
+asmlinkage int do_page_fault(struct cpu_user_regs *regs)
+{
+    unsigned long addr, fixup;
+    int rc;
+
+    __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
+
+    DEBUGGER_trap_entry(TRAP_page_fault, regs);
+
+    perfc_incrc(page_faults);
+
+    if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
+        return rc;
+
+    if ( unlikely(!GUEST_MODE(regs)) )
+    {
+        if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
+        {
+            perfc_incrc(copy_user_faults);
+            regs->eip = fixup;
+            return 0;
+        }
+
+        DEBUGGER_trap_fatal(TRAP_page_fault, regs);
+
+        show_registers(regs);
+        show_page_walk(addr);
+        panic("CPU%d FATAL PAGE FAULT\n"
+              "[error_code=%04x]\n"
+              "Faulting linear address: %p\n",
+              smp_processor_id(), regs->error_code, addr);
+    }
 
     propagate_page_fault(addr, regs->error_code);
-    return 0;
-
- xen_fault:
-
-    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
-    {
-        perfc_incrc(copy_user_faults);
-        regs->eip = fixup;
-        return 0;
-    }
-
-    DEBUGGER_trap_fatal(TRAP_page_fault, regs);
-
-    show_registers(regs);
-    show_page_walk(addr);
-    panic("CPU%d FATAL PAGE FAULT\n"
-          "[error_code=%04x]\n"
-          "Faulting linear address: %p\n",
-          smp_processor_id(), regs->error_code, addr);
     return 0;
 }
 

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