WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH v2.0 5/6] Handler m2p table and frametable fault in p

To: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Jan Beulich <JBeulich@xxxxxxxxxx>
Subject: [Xen-devel] [PATCH v2.0 5/6] Handler m2p table and frametable fault in page fault handler
From: "Jiang, Yunhong" <yunhong.jiang@xxxxxxxxx>
Date: Wed, 8 Jul 2009 15:43:50 +0800
Accept-language: en-US
Acceptlanguage: en-US
Cc: Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Wed, 08 Jul 2009 00:45:46 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: Acn/n9WuZph4ju1PScyitYkYEOe9Rw==
Thread-topic: [PATCH v2.0 5/6] Handler m2p table and frametable fault in page fault handler
After memory added, the m2p table and frametable maybe increased, and the 
idle_page_table is updated for it.
These new mapping are propgated to other guest, when access to the new 
m2p/frame table. The access can happen either in HV or in guest for read-only 
mapping.
The propagation is needed for 32 bit Xen environment, or compatibility guest in 
64 bit Xen environment.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>

diff -r 1e580fac45fb xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Jul 02 23:03:22 2009 +0800
+++ b/xen/arch/x86/traps.c      Tue Jul 07 02:34:51 2009 +0800
@@ -1061,13 +1061,24 @@ static int handle_gdt_ldt_mapping_fault(
     return EXCRET_fault_fixed;
 }
 
+static inline int in_hypervisor_range(unsigned long va, struct vcpu *v)
+{
 #ifdef HYPERVISOR_VIRT_END
-#define IN_HYPERVISOR_RANGE(va) \
-    (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
+    if  (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
 #else
-#define IN_HYPERVISOR_RANGE(va) \
-    (((va) >= HYPERVISOR_VIRT_START))
+    if (((va) >= HYPERVISOR_VIRT_START))
 #endif
+        return 1;
+    else
+#if defined(__x86_64__)
+        return ( is_pv_32on64_domain(v->domain) ?
+                   ((va >=  HYPERVISOR_COMPAT_VIRT_START(v->domain) &&
+                     (va < MACH2PHYS_COMPAT_VIRT_END)) ) : 0 );
+#else
+        return 0;
+#endif
+}
+
 
 static int __spurious_page_fault(
     unsigned long addr, unsigned int error_code)
@@ -1207,12 +1218,15 @@ static int fixup_page_fault(unsigned lon
         return ret;
     }
 
-    if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
+    if ( unlikely(in_hypervisor_range(addr, v)) )
     {
         if ( !(regs->error_code & PFEC_reserved_bit) &&
              (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) )
             return handle_gdt_ldt_mapping_fault(
                 addr - GDT_LDT_VIRT_START, regs);
+        if ( !(regs->error_code & PFEC_page_present) &&
+             (pagefault_by_memadd(addr, regs)) )
+             return handle_memadd_fault(addr, regs);
         return 0;
     }
 
diff -r 1e580fac45fb xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Thu Jul 02 23:03:22 2009 +0800
+++ b/xen/arch/x86/x86_32/mm.c  Tue Jul 07 01:48:03 2009 +0800
@@ -381,6 +381,76 @@ int check_descriptor(const struct domain
     return 0;
 }
 
+int pagefault_by_memadd(unsigned long addr, struct cpu_user_regs *regs)
+{
+    if ( guest_mode(regs) )
+    {
+        if ( ((addr >= RO_MPT_VIRT_START) && (addr < RO_MPT_VIRT_END)) )
+            return 1;
+    }
+    else
+    {
+        if ( (addr >= RO_MPT_VIRT_START) && (addr < RDWR_MPT_VIRT_END) )
+            return 1;
+    }
+
+    return 0;
+}
+
+int handle_memadd_fault(unsigned long addr, struct cpu_user_regs *regs)
+{
+    l3_pgentry_t  *pl3e = NULL;
+    l3_pgentry_t l3e;
+    l2_pgentry_t *pl2e = NULL;
+    l2_pgentry_t l2e, idle_l2e;
+    unsigned long mfn, cr3;
+    int rc = 0;
+
+    idle_l2e = idle_pg_table_l2[l2_linear_offset(addr)];
+    if (!(l2e_get_flags(idle_l2e) & _PAGE_PRESENT))
+        return 0;
+
+    cr3 = read_cr3();
+    mfn = cr3 >> PAGE_SHIFT;
+
+    /*
+     * No need get page type here and validate checking for xen mapping
+     */
+    pl3e = map_domain_page(mfn);
+    pl3e += (cr3 & 0xFE0UL) >> 3;
+    l3e = pl3e[3];
+
+    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+        goto done;
+
+    mfn = l3e_get_pfn(l3e);
+    pl2e = map_domain_page(mfn);
+
+    l2e = pl2e[l2_table_offset(addr)];
+
+    /*
+     * These entry will only be set by Xen HV.
+     * Other vCPU may setup it in another pCPU
+     */
+    if (l2e_get_flags(l2e) & _PAGE_PRESENT)
+    {
+        ASSERT(l2e_get_intpte(l2e) == l2e_get_intpte(idle_l2e));
+        rc = EXCRET_fault_fixed;
+        goto done;
+    }
+
+    pl2e[l2_table_offset(addr)] = idle_l2e;
+
+    rc = EXCRET_fault_fixed;
+
+done:
+    if (pl3e)
+        unmap_domain_page(pl3e);
+    if (pl2e)
+        unmap_domain_page(pl2e);
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 1e580fac45fb xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Thu Jul 02 23:03:22 2009 +0800
+++ b/xen/arch/x86/x86_64/mm.c  Mon Jul 06 23:47:48 2009 +0800
@@ -258,8 +258,12 @@ int setup_m2p_table(unsigned long spfn, 
     if ( mpt_size > RDWR_COMPAT_MPT_VIRT_END - RDWR_COMPAT_MPT_VIRT_START )
         mpt_size = RDWR_COMPAT_MPT_VIRT_END - RDWR_COMPAT_MPT_VIRT_START;
     mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
+
+    /* We don't support change the m2p_compat_vstart with memory hotplug */
+#if !defined(CONFIG_MEMORY_HOTPLUG)
     if ( (m2p_compat_vstart + mpt_size) < MACH2PHYS_COMPAT_VIRT_END )
         m2p_compat_vstart = MACH2PHYS_COMPAT_VIRT_END - mpt_size;
+#endif
 
     /* Has already setup */
     if ( (mpt_size >> PAGE_SHIFT) <= compat_mpt_pages )
@@ -645,6 +649,87 @@ unsigned int domain_clamp_alloc_bitsize(
     return min(d->arch.physaddr_bitsize, bits);
 }
 
+int pagefault_by_memadd(unsigned long addr, struct cpu_user_regs *regs)
+{
+    struct domain *d = current->domain;
+#ifdef CONFIG_COMPAT
+    if ( is_pv_32on64_domain(d) &&
+         (addr >= HYPERVISOR_COMPAT_VIRT_START(d)) &&
+           (addr < MACH2PHYS_COMPAT_VIRT_END) )
+            return 1;
+#endif
+    return 0;
+}
+
+int handle_memadd_fault(unsigned long addr, struct cpu_user_regs *regs)
+{
+#ifdef CONFIG_COMPAT
+    struct domain *d = current->domain;
+    l4_pgentry_t *pl4e = NULL;
+    l4_pgentry_t l4e;
+    l3_pgentry_t  *pl3e = NULL;
+    l3_pgentry_t l3e;
+    l2_pgentry_t *pl2e = NULL;
+    l2_pgentry_t l2e, idle_l2e;
+    unsigned long mfn, idle_index;
+    int rc = 0;
+
+    if (!is_pv_32on64_domain(d))
+        return 0;
+
+    idle_index = l2_table_offset(addr) -
+                        COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d);
+    idle_l2e = compat_idle_pg_table_l2[idle_index];
+    if (!(l2e_get_flags(idle_l2e) & _PAGE_PRESENT))
+        return 0;
+
+    mfn = (read_cr3()) >> PAGE_SHIFT;
+
+    pl4e = map_domain_page(mfn);
+
+    l4e = pl4e[0];
+
+    if (!(l4e_get_flags(l4e) & _PAGE_PRESENT))
+        goto done;
+
+    mfn = l4e_get_pfn(l4e);
+    /* We don't need get page type here since this is xen mapping */
+    pl3e = map_domain_page(mfn);
+
+    l3e = pl3e[3];
+
+    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+        goto done;
+
+    mfn = l3e_get_pfn(l3e);
+    pl2e = map_domain_page(mfn);
+
+    l2e = pl2e[l2_table_offset(addr)];
+
+    /*
+     * Race happen that other pCPU may have fixed it
+     */
+    if (l2e_get_flags(l2e) & _PAGE_PRESENT)
+    {
+        ASSERT(l2e_get_intpte(l2e) == l2e_get_intpte(idle_l2e));
+        rc = EXCRET_fault_fixed;
+        goto done;
+    }
+
+    pl2e[l2_table_offset(addr)] = idle_l2e;
+
+    rc = EXCRET_fault_fixed;
+#endif
+done:
+    if (pl4e)
+        unmap_domain_page(pl4e);
+    if (pl3e)
+        unmap_domain_page(pl3e);
+    if (pl2e)
+        unmap_domain_page(pl2e);
+    return rc;
+}
+
 #include "compat/mm.c"
 
 /*
diff -r 1e580fac45fb xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Thu Jul 02 23:03:22 2009 +0800
+++ b/xen/include/asm-x86/mm.h  Thu Jul 02 23:03:22 2009 +0800
@@ -518,6 +518,8 @@ int setup_m2p_table(unsigned long spfn, 
 int setup_m2p_table(unsigned long spfn, unsigned long epfn, int hotplug);
 unsigned long domain_get_maximum_gpfn(struct domain *d);
 
+int handle_memadd_fault(unsigned long addr, struct cpu_user_regs *regs);
+int pagefault_by_memadd(unsigned long addr, struct cpu_user_regs *regs);
 extern struct domain *dom_xen, *dom_io;        /* for vmcoreinfo */
 
 #endif /* __ASM_X86_MM_H__ */

Attachment: page_fault.patch
Description: page_fault.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH v2.0 5/6] Handler m2p table and frametable fault in page fault handler, Jiang, Yunhong <=