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

[Xen-devel] [PATCH 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 fbba70d76aec xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Sun Jun 28 02:34:55 2009 +0800
+++ b/xen/arch/x86/traps.c      Sun Jun 28 02:34:57 2009 +0800
@@ -1213,6 +1213,9 @@ static int fixup_page_fault(unsigned lon
              (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 fbba70d76aec xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Sun Jun 28 02:34:55 2009 +0800
+++ b/xen/arch/x86/x86_32/mm.c  Sun Jun 28 02:41:09 2009 +0800
@@ -383,6 +383,63 @@ 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;
+    l3_pgentry_t l3e;
+    l2_pgentry_t *pl2e;
+    l2_pgentry_t l2e, idle_l2e;
+    unsigned long mfn, cr3;
+
+    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) )
+        return 0;
+
+    mfn = l3e_get_pfn(l3e);
+    pl2e = map_domain_page(mfn);
+
+    l2e = pl2e[l2_table_offset(addr)];
+
+    if (l2e_get_flags(l2e) & _PAGE_PRESENT)
+        return 0;
+
+    memcpy(&pl2e[l2_table_offset(addr)],
+            &idle_pg_table_l2[l2_linear_offset(addr)],
+            sizeof(l2_pgentry_t));
+
+    return EXCRET_fault_fixed;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r fbba70d76aec xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Sun Jun 28 02:34:55 2009 +0800
+++ b/xen/arch/x86/x86_64/mm.c  Sun Jun 28 02:42:08 2009 +0800
@@ -643,6 +643,76 @@ 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 (guest_mode(regs) &&
+        ((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;
+    l4_pgentry_t l4e;
+    l3_pgentry_t  *pl3e;
+    l3_pgentry_t l3e;
+    l2_pgentry_t *pl2e;
+    l2_pgentry_t l2e, idle_l2e;
+    unsigned long mfn, idle_index;
+
+    if (!is_pv_32on64_domain(d))
+        return 0;
+
+    mfn = (read_cr3()) >> PAGE_SHIFT;
+
+    pl4e = map_domain_page(mfn);
+
+    l4e = pl4e[0];
+
+    if (!(l4e_get_flags(l4e) & _PAGE_PRESENT))
+        return 0;
+
+    mfn = l4e_get_pfn(l4e);
+    /* We don't need get page type here since it is current CR3 */
+    pl3e = map_domain_page(mfn);
+
+    l3e = pl3e[3];
+
+    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+        return 0;
+
+    mfn = l3e_get_pfn(l3e);
+    pl2e = map_domain_page(mfn);
+
+    l2e = pl2e[l2_table_offset(addr)];
+
+    if (l2e_get_flags(l2e) & _PAGE_PRESENT)
+        return 0;
+
+    idle_index = (l2_table_offset(addr) -
+                        COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d))/
+                  sizeof(l2_pgentry_t);
+    idle_l2e = compat_idle_pg_table_l2[idle_index];
+    if (!(l2e_get_flags(idle_l2e) & _PAGE_PRESENT))
+        return 0;
+    memcpy(&pl2e[l2_table_offset(addr)], 
&compat_idle_pg_table_l2[l2_table_offset(addr)],
+                sizeof(l2_pgentry_t));
+
+    memcpy(&pl2e[l2_table_offset(addr)],
+            &compat_idle_pg_table_l2[idle_index],
+            sizeof(l2_pgentry_t));
+    return EXCRET_fault_fixed;
+#endif
+    return 0;
+}
+
 #include "compat/mm.c"
 
 /*
diff -r fbba70d76aec xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Sun Jun 28 02:34:55 2009 +0800
+++ b/xen/include/asm-x86/mm.h  Sun Jun 28 02:34:57 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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.