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-changelog

[Xen-changelog] [xen-unstable] [XEN] Shadow: emulate a few extra instruc

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Shadow: emulate a few extra instructions on PAE pagetable writes
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 04 Jun 2007 03:16:22 -0700
Delivery-date: Mon, 04 Jun 2007 03:35:39 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1180704731 -3600
# Node ID 13eca4bf2c69aff4c9b689d0dff45929e44e4edb
# Parent  b182bd560e47ba3497211603a840ffb3afa13dc8
[XEN] Shadow: emulate a few extra instructions on PAE pagetable writes
in the hope of catching the "other half" write without another enter/exit.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/mm/shadow/common.c  |   32 ++++++++++++++
 xen/arch/x86/mm/shadow/multi.c   |   86 ++++++++++++++++++++++++++++-----------
 xen/arch/x86/mm/shadow/private.h |    7 ++-
 xen/include/asm-x86/domain.h     |    2 
 xen/include/asm-x86/perfc_defn.h |    3 +
 5 files changed, 103 insertions(+), 27 deletions(-)

diff -r b182bd560e47 -r 13eca4bf2c69 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Thu May 31 16:09:11 2007 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Fri Jun 01 14:32:11 2007 +0100
@@ -248,7 +248,7 @@ hvm_emulate_insn_fetch(enum x86_segment 
 {
     struct sh_emulate_ctxt *sh_ctxt =
         container_of(ctxt, struct sh_emulate_ctxt, ctxt);
-    unsigned int insn_off = offset - ctxt->regs->eip;
+    unsigned int insn_off = offset - sh_ctxt->insn_buf_eip;
 
     /* Fall back if requested bytes are not in the prefetch cache. */
     if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) )
@@ -450,6 +450,7 @@ struct x86_emulate_ops *shadow_init_emul
     }
 
     /* Attempt to prefetch whole instruction. */
+    sh_ctxt->insn_buf_eip = regs->eip;
     sh_ctxt->insn_buf_bytes =
         (!hvm_translate_linear_addr(
             x86_seg_cs, regs->eip, sizeof(sh_ctxt->insn_buf),
@@ -459,6 +460,35 @@ struct x86_emulate_ops *shadow_init_emul
         ? sizeof(sh_ctxt->insn_buf) : 0;
 
     return &hvm_shadow_emulator_ops;
+}
+
+/* Update an initialized emulation context to prepare for the next 
+ * instruction */
+void shadow_continue_emulation(struct sh_emulate_ctxt *sh_ctxt, 
+                               struct cpu_user_regs *regs)
+{
+    struct vcpu *v = current;
+    unsigned long addr, diff;
+
+    /* We don't refetch the segment bases, because we don't emulate
+     * writes to segment registers */
+
+    if ( is_hvm_vcpu(v) )
+    {
+        diff = regs->eip - sh_ctxt->insn_buf_eip;
+        if ( diff > sh_ctxt->insn_buf_bytes )
+        {
+            /* Prefetch more bytes. */
+            sh_ctxt->insn_buf_bytes =
+                (!hvm_translate_linear_addr(
+                    x86_seg_cs, regs->eip, sizeof(sh_ctxt->insn_buf),
+                    hvm_access_insn_fetch, sh_ctxt, &addr) &&
+                 !hvm_copy_from_guest_virt(
+                     sh_ctxt->insn_buf, addr, sizeof(sh_ctxt->insn_buf)))
+                ? sizeof(sh_ctxt->insn_buf) : 0;
+            sh_ctxt->insn_buf_eip = regs->eip;
+        }
+    }
 }
 
 /**************************************************************************/
diff -r b182bd560e47 -r 13eca4bf2c69 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Thu May 31 16:09:11 2007 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Fri Jun 01 14:32:11 2007 +0100
@@ -2871,6 +2871,20 @@ static int sh_page_fault(struct vcpu *v,
     if ( !shadow_mode_refcounts(d) || !guest_mode(regs) )
         goto not_a_shadow_fault;
 
+    /*
+     * We do not emulate user writes. Instead we use them as a hint that the
+     * page is no longer a page table. This behaviour differs from native, but
+     * it seems very unlikely that any OS grants user access to page tables.
+     */
+    if ( (regs->error_code & PFEC_user_mode) )
+    {
+        SHADOW_PRINTK("user-mode fault to PT, unshadowing mfn %#lx\n", 
+                      mfn_x(gmfn));
+        perfc_incr(shadow_fault_emulate_failed);
+        sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
+        goto done;
+    }
+
     if ( is_hvm_domain(d) )
     {
         /*
@@ -2897,14 +2911,7 @@ static int sh_page_fault(struct vcpu *v,
 
     emul_ops = shadow_init_emulation(&emul_ctxt, regs);
 
-    /*
-     * We do not emulate user writes. Instead we use them as a hint that the
-     * page is no longer a page table. This behaviour differs from native, but
-     * it seems very unlikely that any OS grants user access to page tables.
-     */
-    r = X86EMUL_UNHANDLEABLE;
-    if ( !(regs->error_code & PFEC_user_mode) )
-        r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
+    r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
 
     /*
      * NB. We do not unshadow on X86EMUL_EXCEPTION. It's not clear that it
@@ -2921,6 +2928,35 @@ static int sh_page_fault(struct vcpu *v,
          * though, this is a hint that this page should not be shadowed. */
         sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
     }
+
+#if GUEST_PAGING_LEVELS == 3 /* PAE guest */
+    if ( r == X86EMUL_OKAY ) {
+        int i;
+        /* Emulate up to four extra instructions in the hope of catching 
+         * the "second half" of a 64-bit pagetable write. */
+        for ( i = 0 ; i < 4 ; i++ )
+        {
+            shadow_continue_emulation(&emul_ctxt, regs);
+            v->arch.paging.last_write_was_pt = 0;
+            r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
+            if ( r == X86EMUL_OKAY )
+            {
+                if ( v->arch.paging.last_write_was_pt )
+                {
+                    perfc_incr(shadow_em_ex_pt);
+                    break; /* Don't emulate past the other half of the write */
+                }
+                else 
+                    perfc_incr(shadow_em_ex_non_pt);
+            }
+            else
+            {
+                perfc_incr(shadow_em_ex_fail);
+                break; /* Don't emulate again if we failed! */
+            }
+        }
+    }
+#endif /* PAE guest */
 
     /* Emulator has changed the user registers: write back */
     if ( is_hvm_domain(d) )
@@ -3878,6 +3914,11 @@ static inline void * emulate_map_dest(st
     gfn_t gfn;
     mfn_t mfn;
 
+    /* We don't emulate user-mode writes to page tables */
+    if ( ring_3(sh_ctxt->ctxt.regs) ) 
+        return NULL;
+
+    /* Walk the guest pagetables */
     guest_walk_tables(v, vaddr, &gw, 1);
     flags = accumulate_guest_flags(v, &gw);
     gfn = guest_l1e_get_gfn(gw.eff_l1e);
@@ -3885,27 +3926,24 @@ static inline void * emulate_map_dest(st
     sh_audit_gw(v, &gw);
     unmap_walk(v, &gw);
 
-    if ( !(flags & _PAGE_PRESENT) )
-    {
-        errcode = 0;
+    errcode = PFEC_write_access;
+    if ( !(flags & _PAGE_PRESENT) ) 
         goto page_fault;
-    }
-
-    if ( !(flags & _PAGE_RW) ||
-         (!(flags & _PAGE_USER) && ring_3(sh_ctxt->ctxt.regs)) )
-    {
-        errcode = PFEC_page_present;
+
+    errcode |= PFEC_page_present;
+    if ( !(flags & _PAGE_RW) ) 
         goto page_fault;
-    }
-
-    if ( !mfn_valid(mfn) )
+
+    if ( mfn_valid(mfn) )
+    {
+        *mfnp = mfn;
+        v->arch.paging.last_write_was_pt = !!sh_mfn_is_a_page_table(mfn);
+        return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK);
+    }
+    else 
         return NULL;
 
-    *mfnp = mfn;
-    return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK);
-
  page_fault:
-    errcode |= PFEC_write_access;
     if ( is_hvm_vcpu(v) )
         hvm_inject_exception(TRAP_page_fault, errcode, vaddr);
     else
diff -r b182bd560e47 -r 13eca4bf2c69 xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Thu May 31 16:09:11 2007 +0100
+++ b/xen/arch/x86/mm/shadow/private.h  Fri Jun 01 14:32:11 2007 +0100
@@ -634,9 +634,10 @@ struct sh_emulate_ctxt {
 struct sh_emulate_ctxt {
     struct x86_emulate_ctxt ctxt;
 
-    /* [HVM] Cache of up to 15 bytes of instruction. */
-    uint8_t insn_buf[15];
+    /* [HVM] Cache of up to 31 bytes of instruction. */
+    uint8_t insn_buf[31];
     uint8_t insn_buf_bytes;
+    unsigned long insn_buf_eip;
 
     /* [HVM] Cache of segment registers already gathered for this emulation. */
     unsigned int valid_seg_regs;
@@ -644,6 +645,8 @@ struct sh_emulate_ctxt {
 };
 
 struct x86_emulate_ops *shadow_init_emulation(
+    struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs);
+void shadow_continue_emulation(
     struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs);
 
 #endif /* _XEN_SHADOW_PRIVATE_H */
diff -r b182bd560e47 -r 13eca4bf2c69 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Thu May 31 16:09:11 2007 +0100
+++ b/xen/include/asm-x86/domain.h      Fri Jun 01 14:32:11 2007 +0100
@@ -171,6 +171,8 @@ struct paging_vcpu {
     struct paging_mode *mode;
     /* HVM guest: paging enabled (CR0.PG)?  */
     unsigned int translate_enabled:1;
+    /* HVM guest: last emulate was to a pagetable */
+    unsigned int last_write_was_pt:1;
 
     /* paging support extension */
     struct shadow_vcpu shadow;
diff -r b182bd560e47 -r 13eca4bf2c69 xen/include/asm-x86/perfc_defn.h
--- a/xen/include/asm-x86/perfc_defn.h  Thu May 31 16:09:11 2007 +0100
+++ b/xen/include/asm-x86/perfc_defn.h  Fri Jun 01 14:32:11 2007 +0100
@@ -90,5 +90,8 @@ PERFCOUNTER(shadow_invlpg,         "shad
 PERFCOUNTER(shadow_invlpg,         "shadow emulates invlpg")
 PERFCOUNTER(shadow_invlpg_fault,   "shadow invlpg faults")
 
+PERFCOUNTER(shadow_em_ex_pt,       "shadow extra pt write")
+PERFCOUNTER(shadow_em_ex_non_pt,   "shadow extra non-pt-write op")
+PERFCOUNTER(shadow_em_ex_fail,     "shadow extra emulation failed")
 
 /*#endif*/ /* __XEN_PERFC_DEFN_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] Shadow: emulate a few extra instructions on PAE pagetable writes, Xen patchbot-unstable <=