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

[Xen-changelog] [xen-unstable] [XEN] Shadow-mode-refcount PTE update fix.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID f5121d001d1ad66165d67c96a6e1f8f18375b1c3
# Parent  245f7ce8763e2f4968a4f0ce2ac7022b0eddb723
[XEN] Shadow-mode-refcount PTE update fix.

Add back in support for emulated PTE updates which is critical for
shdow_refcount operation.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/mm/shadow/common.c    |  328 +++++++++++++++++++++----------------
 xen/arch/x86/mm/shadow/multi.c     |   20 +-
 xen/arch/x86/mm/shadow/private.h   |   11 -
 xen/include/asm-x86/guest_access.h |   16 -
 4 files changed, 217 insertions(+), 158 deletions(-)

diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Sat Dec 09 15:04:27 2006 +0000
+++ b/xen/arch/x86/mm/shadow/common.c   Sat Dec 09 16:29:52 2006 +0000
@@ -185,15 +185,7 @@ hvm_read(enum x86_segment seg,
     //        In this case, that is only a user vs supervisor access check.
     //
     if ( (rc = hvm_copy_from_guest_virt(val, addr, bytes)) == 0 )
-    {
-#if 0
-        struct vcpu *v = current;
-        SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n",
-                       v->domain->domain_id, v->vcpu_id, 
-                       addr, *val, bytes);
-#endif
         return X86EMUL_CONTINUE;
-    }
 
     /* If we got here, there was nothing mapped here, or a bad GFN 
      * was mapped here.  This should never happen: we're here because
@@ -206,14 +198,202 @@ hvm_read(enum x86_segment seg,
     return X86EMUL_PROPAGATE_FAULT;
 }
 
-void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt, 
-                           struct cpu_user_regs *regs)
+static int
+hvm_emulate_read(enum x86_segment seg,
+                 unsigned long offset,
+                 unsigned long *val,
+                 unsigned int bytes,
+                 struct x86_emulate_ctxt *ctxt)
+{
+    return hvm_read(seg, offset, val, bytes, hvm_access_read,
+                    container_of(ctxt, struct sh_emulate_ctxt, ctxt));
+}
+
+static int
+hvm_emulate_insn_fetch(enum x86_segment seg,
+                       unsigned long offset,
+                       unsigned long *val,
+                       unsigned int bytes,
+                       struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    unsigned int insn_off = offset - ctxt->regs->eip;
+
+    /* Fall back if requested bytes are not in the prefetch cache. */
+    if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) )
+        return hvm_read(seg, offset, val, bytes,
+                        hvm_access_insn_fetch, sh_ctxt);
+
+    /* Hit the cache. Simple memcpy. */
+    *val = 0;
+    memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes);
+    return X86EMUL_CONTINUE;
+}
+
+static int
+hvm_emulate_write(enum x86_segment seg,
+                  unsigned long offset,
+                  unsigned long val,
+                  unsigned int bytes,
+                  struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    unsigned long addr;
+    int rc;
+
+    rc = hvm_translate_linear_addr(
+        seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
+    if ( rc )
+        return rc;
+
+    return v->arch.shadow.mode->x86_emulate_write(
+        v, addr, &val, bytes, sh_ctxt);
+}
+
+static int 
+hvm_emulate_cmpxchg(enum x86_segment seg,
+                    unsigned long offset,
+                    unsigned long old,
+                    unsigned long new,
+                    unsigned int bytes,
+                    struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    unsigned long addr;
+    int rc;
+
+    rc = hvm_translate_linear_addr(
+        seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
+    if ( rc )
+        return rc;
+
+    return v->arch.shadow.mode->x86_emulate_cmpxchg(
+        v, addr, old, new, bytes, sh_ctxt);
+}
+
+static int 
+hvm_emulate_cmpxchg8b(enum x86_segment seg,
+                      unsigned long offset,
+                      unsigned long old_lo,
+                      unsigned long old_hi,
+                      unsigned long new_lo,
+                      unsigned long new_hi,
+                      struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    unsigned long addr;
+    int rc;
+
+    rc = hvm_translate_linear_addr(
+        seg, offset, 8, hvm_access_write, sh_ctxt, &addr);
+    if ( rc )
+        return rc;
+
+    return v->arch.shadow.mode->x86_emulate_cmpxchg8b(
+        v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt);
+}
+
+static struct x86_emulate_ops hvm_shadow_emulator_ops = {
+    .read       = hvm_emulate_read,
+    .insn_fetch = hvm_emulate_insn_fetch,
+    .write      = hvm_emulate_write,
+    .cmpxchg    = hvm_emulate_cmpxchg,
+    .cmpxchg8b  = hvm_emulate_cmpxchg8b,
+};
+
+static int
+pv_emulate_read(enum x86_segment seg,
+                unsigned long offset,
+                unsigned long *val,
+                unsigned int bytes,
+                struct x86_emulate_ctxt *ctxt)
+{
+    unsigned int rc;
+
+    *val = 0;
+    if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 )
+    {
+        propagate_page_fault(offset + bytes - rc, 0); /* read fault */
+        return X86EMUL_PROPAGATE_FAULT;
+    }
+
+    return X86EMUL_CONTINUE;
+}
+
+static int
+pv_emulate_write(enum x86_segment seg,
+                 unsigned long offset,
+                 unsigned long val,
+                 unsigned int bytes,
+                 struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    return v->arch.shadow.mode->x86_emulate_write(
+        v, offset, &val, bytes, sh_ctxt);
+}
+
+static int 
+pv_emulate_cmpxchg(enum x86_segment seg,
+                   unsigned long offset,
+                   unsigned long old,
+                   unsigned long new,
+                   unsigned int bytes,
+                   struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    return v->arch.shadow.mode->x86_emulate_cmpxchg(
+        v, offset, old, new, bytes, sh_ctxt);
+}
+
+static int 
+pv_emulate_cmpxchg8b(enum x86_segment seg,
+                     unsigned long offset,
+                     unsigned long old_lo,
+                     unsigned long old_hi,
+                     unsigned long new_lo,
+                     unsigned long new_hi,
+                     struct x86_emulate_ctxt *ctxt)
+{
+    struct sh_emulate_ctxt *sh_ctxt =
+        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+    struct vcpu *v = current;
+    return v->arch.shadow.mode->x86_emulate_cmpxchg8b(
+        v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt);
+}
+
+static struct x86_emulate_ops pv_shadow_emulator_ops = {
+    .read       = pv_emulate_read,
+    .insn_fetch = pv_emulate_read,
+    .write      = pv_emulate_write,
+    .cmpxchg    = pv_emulate_cmpxchg,
+    .cmpxchg8b  = pv_emulate_cmpxchg8b,
+};
+
+struct x86_emulate_ops *shadow_init_emulation(
+    struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs)
 {
     struct segment_register *creg;
     struct vcpu *v = current;
     unsigned long addr;
 
     sh_ctxt->ctxt.regs = regs;
+
+    if ( !is_hvm_vcpu(v) )
+    {
+        sh_ctxt->ctxt.mode = X86EMUL_MODE_HOST;
+        return &pv_shadow_emulator_ops;
+    }
 
     /* Segment cache initialisation. Primed with CS. */
     sh_ctxt->valid_seg_regs = 0;
@@ -237,131 +417,9 @@ void shadow_init_emulation(struct sh_emu
          !hvm_copy_from_guest_virt(
              sh_ctxt->insn_buf, addr, sizeof(sh_ctxt->insn_buf)))
         ? sizeof(sh_ctxt->insn_buf) : 0;
-}
-
-static int
-sh_x86_emulate_read(enum x86_segment seg,
-                    unsigned long offset,
-                    unsigned long *val,
-                    unsigned int bytes,
-                    struct x86_emulate_ctxt *ctxt)
-{
-    return hvm_read(seg, offset, val, bytes, hvm_access_read,
-                    container_of(ctxt, struct sh_emulate_ctxt, ctxt));
-}
-
-static int
-sh_x86_emulate_insn_fetch(enum x86_segment seg,
-                          unsigned long offset,
-                          unsigned long *val,
-                          unsigned int bytes,
-                          struct x86_emulate_ctxt *ctxt)
-{
-    struct sh_emulate_ctxt *sh_ctxt =
-        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
-    unsigned int insn_off = offset - ctxt->regs->eip;
-
-    /* Fall back if requested bytes are not in the prefetch cache. */
-    if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) )
-        return hvm_read(seg, offset, val, bytes,
-                        hvm_access_insn_fetch, sh_ctxt);
-
-    /* Hit the cache. Simple memcpy. */
-    *val = 0;
-    memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes);
-    return X86EMUL_CONTINUE;
-}
-
-static int
-sh_x86_emulate_write(enum x86_segment seg,
-                     unsigned long offset,
-                     unsigned long val,
-                     unsigned int bytes,
-                     struct x86_emulate_ctxt *ctxt)
-{
-    struct sh_emulate_ctxt *sh_ctxt =
-        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
-    struct vcpu *v = current;
-    unsigned long addr;
-    int rc;
-
-    rc = hvm_translate_linear_addr(
-        seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
-    if ( rc )
-        return rc;
-
-#if 0
-    SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n",
-                  v->domain->domain_id, v->vcpu_id, addr, val, bytes);
-#endif
-    return v->arch.shadow.mode->x86_emulate_write(
-        v, addr, &val, bytes, sh_ctxt);
-}
-
-static int 
-sh_x86_emulate_cmpxchg(enum x86_segment seg,
-                       unsigned long offset,
-                       unsigned long old,
-                       unsigned long new,
-                       unsigned int bytes,
-                       struct x86_emulate_ctxt *ctxt)
-{
-    struct sh_emulate_ctxt *sh_ctxt =
-        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
-    struct vcpu *v = current;
-    unsigned long addr;
-    int rc;
-
-    rc = hvm_translate_linear_addr(
-        seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
-    if ( rc )
-        return rc;
-
-#if 0
-    SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx n:=%#lx bytes=%u\n",
-                   v->domain->domain_id, v->vcpu_id, addr, old, new, bytes);
-#endif
-    return v->arch.shadow.mode->x86_emulate_cmpxchg(
-        v, addr, old, new, bytes, sh_ctxt);
-}
-
-static int 
-sh_x86_emulate_cmpxchg8b(enum x86_segment seg,
-                         unsigned long offset,
-                         unsigned long old_lo,
-                         unsigned long old_hi,
-                         unsigned long new_lo,
-                         unsigned long new_hi,
-                         struct x86_emulate_ctxt *ctxt)
-{
-    struct sh_emulate_ctxt *sh_ctxt =
-        container_of(ctxt, struct sh_emulate_ctxt, ctxt);
-    struct vcpu *v = current;
-    unsigned long addr;
-    int rc;
-
-    rc = hvm_translate_linear_addr(
-        seg, offset, 8, hvm_access_write, sh_ctxt, &addr);
-    if ( rc )
-        return rc;
-
-#if 0
-    SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx:%lx n:=%#lx:%lx\n",
-                   v->domain->domain_id, v->vcpu_id, addr, old_hi, old_lo,
-                   new_hi, new_lo, ctxt);
-#endif
-    return v->arch.shadow.mode->x86_emulate_cmpxchg8b(
-        v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt);
-}
-
-
-struct x86_emulate_ops shadow_emulator_ops = {
-    .read       = sh_x86_emulate_read,
-    .insn_fetch = sh_x86_emulate_insn_fetch,
-    .write      = sh_x86_emulate_write,
-    .cmpxchg    = sh_x86_emulate_cmpxchg,
-    .cmpxchg8b  = sh_x86_emulate_cmpxchg8b,
-};
+
+    return &hvm_shadow_emulator_ops;
+}
 
 /**************************************************************************/
 /* Code for "promoting" a guest page to the point where the shadow code is
diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Sat Dec 09 15:04:27 2006 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Sat Dec 09 16:29:52 2006 +0000
@@ -2585,6 +2585,7 @@ static int sh_page_fault(struct vcpu *v,
     shadow_l1e_t sl1e, *ptr_sl1e;
     paddr_t gpa;
     struct sh_emulate_ctxt emul_ctxt;
+    struct x86_emulate_ops *emul_ops;
     int r, mmio;
     fetch_type_t ft = 0;
 
@@ -2811,13 +2812,14 @@ static int sh_page_fault(struct vcpu *v,
     return EXCRET_fault_fixed;
 
  emulate:
-    if ( !is_hvm_domain(d) || !guest_mode(regs) )
+    if ( !shadow_mode_refcounts(d) || !guest_mode(regs) )
         goto not_a_shadow_fault;
 
-    hvm_store_cpu_guest_regs(v, regs, NULL);
+    if ( is_hvm_domain(d) )
+        hvm_store_cpu_guest_regs(v, regs, NULL);
     SHADOW_PRINTK("emulate: eip=%#lx\n", regs->eip);
 
-    shadow_init_emulation(&emul_ctxt, regs);
+    emul_ops = shadow_init_emulation(&emul_ctxt, regs);
 
     /*
      * We do not emulate user writes. Instead we use them as a hint that the
@@ -2825,7 +2827,7 @@ static int sh_page_fault(struct vcpu *v,
      * it seems very unlikely that any OS grants user access to page tables.
      */
     if ( (regs->error_code & PFEC_user_mode) ||
-         x86_emulate_memop(&emul_ctxt.ctxt, &shadow_emulator_ops) )
+         x86_emulate_memop(&emul_ctxt.ctxt, emul_ops) )
     {
         SHADOW_PRINTK("emulator failure, unshadowing mfn %#lx\n", 
                        mfn_x(gmfn));
@@ -2837,7 +2839,8 @@ static int sh_page_fault(struct vcpu *v,
     }
 
     /* Emulator has changed the user registers: write back */
-    hvm_load_cpu_guest_regs(v, regs);
+    if ( is_hvm_domain(d) )
+        hvm_load_cpu_guest_regs(v, regs);
     goto done;
 
  mmio:
@@ -3814,9 +3817,10 @@ static inline void * emulate_map_dest(st
 
  page_fault:
     errcode |= PFEC_write_access;
-    if ( ring_3(sh_ctxt->ctxt.regs) )
-        errcode |= PFEC_user_mode;
-    hvm_inject_exception(TRAP_page_fault, errcode, vaddr);
+    if ( is_hvm_vcpu(v) )
+        hvm_inject_exception(TRAP_page_fault, errcode, vaddr);
+    else
+        propagate_page_fault(vaddr, errcode);
     return NULL;
 }
 
diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Sat Dec 09 15:04:27 2006 +0000
+++ b/xen/arch/x86/mm/shadow/private.h  Sat Dec 09 16:29:52 2006 +0000
@@ -257,9 +257,6 @@ static inline int sh_type_is_pinnable(st
  * Various function declarations 
  */
 
-/* x86 emulator support */
-extern struct x86_emulate_ops shadow_emulator_ops;
-
 /* Hash table functions */
 mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t);
 void  shadow_hash_insert(struct vcpu *v, 
@@ -513,17 +510,17 @@ struct sh_emulate_ctxt {
 struct sh_emulate_ctxt {
     struct x86_emulate_ctxt ctxt;
 
-    /* Cache of up to 15 bytes of instruction. */
+    /* [HVM] Cache of up to 15 bytes of instruction. */
     uint8_t insn_buf[15];
     uint8_t insn_buf_bytes;
 
-    /* Cache of segment registers already gathered for this emulation. */
+    /* [HVM] Cache of segment registers already gathered for this emulation. */
     unsigned int valid_seg_regs;
     struct segment_register seg_reg[6];
 };
 
-void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt,
-                           struct cpu_user_regs *regs);
+struct x86_emulate_ops *shadow_init_emulation(
+    struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs);
 
 #endif /* _XEN_SHADOW_PRIVATE_H */
 
diff -r 245f7ce8763e -r f5121d001d1a xen/include/asm-x86/guest_access.h
--- a/xen/include/asm-x86/guest_access.h        Sat Dec 09 15:04:27 2006 +0000
+++ b/xen/include/asm-x86/guest_access.h        Sat Dec 09 16:29:52 2006 +0000
@@ -34,7 +34,7 @@
 #define copy_to_guest_offset(hnd, off, ptr, nr) ({      \
     const typeof(ptr) _x = (hnd).p;                     \
     const typeof(ptr) _y = (ptr);                       \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) :  \
     copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));       \
 })
@@ -46,7 +46,7 @@
 #define copy_from_guest_offset(ptr, hnd, off, nr) ({    \
     const typeof(ptr) _x = (hnd).p;                     \
     const typeof(ptr) _y = (ptr);                       \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_from_user_hvm(_y, _x+(off), sizeof(*_x)*(nr)) :\
     copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));     \
 })
@@ -55,7 +55,7 @@
 #define copy_field_to_guest(hnd, ptr, field) ({         \
     const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
     const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_to_user_hvm(_x, _y, sizeof(*_x)) :             \
     copy_to_user(_x, _y, sizeof(*_x));                  \
 })
@@ -64,7 +64,7 @@
 #define copy_field_from_guest(ptr, hnd, field) ({       \
     const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
     const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_from_user_hvm(_y, _x, sizeof(*_x)) :           \
     copy_from_user(_y, _x, sizeof(*_x));                \
 })
@@ -80,7 +80,7 @@
 #define __copy_to_guest_offset(hnd, off, ptr, nr) ({    \
     const typeof(ptr) _x = (hnd).p;                     \
     const typeof(ptr) _y = (ptr);                       \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) :  \
     __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));     \
 })
@@ -88,7 +88,7 @@
 #define __copy_from_guest_offset(ptr, hnd, off, nr) ({  \
     const typeof(ptr) _x = (hnd).p;                     \
     const typeof(ptr) _y = (ptr);                       \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_from_user_hvm(_y, _x+(off),sizeof(*_x)*(nr)) : \
     __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));   \
 })
@@ -96,7 +96,7 @@
 #define __copy_field_to_guest(hnd, ptr, field) ({       \
     const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
     const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_to_user_hvm(_x, _y, sizeof(*_x)) :             \
     __copy_to_user(_x, _y, sizeof(*_x));                \
 })
@@ -104,7 +104,7 @@
 #define __copy_field_from_guest(ptr, hnd, field) ({     \
     const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
     const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    shadow_mode_translate(current->domain) ?            \
+    is_hvm_vcpu(current) ?                              \
     copy_from_user_hvm(_x, _y, sizeof(*_x)) :           \
     __copy_from_user(_y, _x, sizeof(*_x));              \
 })

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