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

[Xen-devel] [PATCH v1] x86/mm: Suppresses vm_events caused by page-walks


  • To: xen-devel@xxxxxxxxxxxxx
  • From: Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx>
  • Date: Fri, 24 Aug 2018 17:11:19 +0300
  • Cc: tamas@xxxxxxxxxxxxx, rcojocaru@xxxxxxxxxxxxxxx, george.dunlap@xxxxxxxxxxxxx, andrew.cooper3@xxxxxxxxxx, tim@xxxxxxx, jbeulich@xxxxxxxx, Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx>
  • Comment: DomainKeys? See http://domainkeys.sourceforge.net/
  • Delivery-date: Fri, 24 Aug 2018 14:11:32 +0000
  • Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=bitdefender.com; b=YTKV22ID+DiGPrUomIHYZ+2oj2e0mAVfPy0T4Z3pUTWH2+e6SDFj2rNsTE3i9ILKYRxa2+lwryCLtz9FFJT8VA0Tf8r9Y7R1d303jV9kDQIwpI7DSPfJTelaUXlp93i3LgzZUcRQxJ2pvH0f+GpcN7mkX2K9F7fJuU1xaql27BILvEDyYMQ9nXVWdAEzHqOFrX3SUL6M7Y/Om4d/LdeCvBl1DXun0jOqbMspDpB6k/HD/vDICBwZpt8IyBnxVQC7/ZhHyYyG/N5g4UwrWMVTtwrLkFFMeBLS1I60ZnycPW/NbEhZJIlitr/L56+Nl06e5w7AZFr+iStJFOv/OxThLw==; h=Received:Received:Received:Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer;
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

The original version of the patch emulated the current instruction
(which, as a side-effect, emulated the page-walk as well), however we
need finer-grained control. We want to emulate the page-walk, but still
get an EPT violation event if the current instruction would trigger one.
This patch performs just the page-walk emulation.

Signed-off-by: Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx>
---
 xen/arch/x86/mm/guest_walk.c     |  7 ++++++-
 xen/arch/x86/mm/hap/guest_walk.c | 32 +++++++++++++++++++++++++++++++-
 xen/arch/x86/mm/hap/hap.c        | 12 ++++++++----
 xen/arch/x86/mm/hap/private.h    | 10 ++++++++++
 xen/arch/x86/mm/mem_access.c     | 15 ++++++++++++++-
 xen/arch/x86/mm/shadow/multi.c   |  6 +++---
 xen/include/asm-x86/guest_pt.h   |  3 ++-
 xen/include/asm-x86/paging.h     |  5 ++++-
 8 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c
index f67aeda..54140b9 100644
--- a/xen/arch/x86/mm/guest_walk.c
+++ b/xen/arch/x86/mm/guest_walk.c
@@ -82,7 +82,7 @@ static bool set_ad_bits(guest_intpte_t *guest_p, 
guest_intpte_t *walk_p,
 bool
 guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
                   unsigned long va, walk_t *gw,
-                  uint32_t walk, mfn_t top_mfn, void *top_map)
+                  uint32_t walk, mfn_t top_mfn, void *top_map, uint32_t *gf)
 {
     struct domain *d = v->domain;
     p2m_type_t p2mt;
@@ -361,6 +361,11 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
      * see whether the access should succeed.
      */
     ar = (ar_and & AR_ACCUM_AND) | (ar_or & AR_ACCUM_OR);
+    if ( gf )
+    {
+        *gf = ar;
+        goto out;
+    }
 
     /*
      * Sanity check.  If EFER.NX is disabled, _PAGE_NX_BIT is reserved and
diff --git a/xen/arch/x86/mm/hap/guest_walk.c b/xen/arch/x86/mm/hap/guest_walk.c
index cb3f9ce..c916b67 100644
--- a/xen/arch/x86/mm/hap/guest_walk.c
+++ b/xen/arch/x86/mm/hap/guest_walk.c
@@ -29,6 +29,9 @@ asm(".file \"" __OBJECT_FILE__ "\"");
 #define _hap_gva_to_gfn(levels) hap_gva_to_gfn_##levels##_levels
 #define hap_gva_to_gfn(levels) _hap_gva_to_gfn(levels)
 
+#define _hap_pte_flags(levels) hap_pte_flags_##levels##_levels
+#define hap_pte_flags(levels) _hap_pte_flags(levels)
+
 #define _hap_p2m_ga_to_gfn(levels) hap_p2m_ga_to_gfn_##levels##_levels
 #define hap_p2m_ga_to_gfn(levels) _hap_p2m_ga_to_gfn(levels)
 
@@ -39,6 +42,33 @@ asm(".file \"" __OBJECT_FILE__ "\"");
 #include <asm/guest_pt.h>
 #include <asm/p2m.h>
 
+bool hap_pte_flags(GUEST_PAGING_LEVELS)(
+    struct vcpu *v, struct p2m_domain *p2m,
+    unsigned long va, uint32_t walk, unsigned long cr3,
+    uint32_t *gf)
+{
+    walk_t gw;
+    mfn_t top_mfn;
+    void *top_map;
+    gfn_t top_gfn;
+    struct page_info *top_page;
+    p2m_type_t p2mt;
+
+    top_gfn = _gfn(cr3 >> PAGE_SHIFT);
+    top_page = p2m_get_page_from_gfn(p2m, top_gfn, &p2mt, NULL,
+                                     P2M_ALLOC | P2M_UNSHARE);
+    top_mfn = page_to_mfn(top_page);
+
+    /* Map the top-level table and call the tree-walker */
+    ASSERT(mfn_valid(top_mfn));
+    top_map = map_domain_page(top_mfn);
+#if GUEST_PAGING_LEVELS == 3
+    top_map += (cr3 & ~(PAGE_MASK | 31));
+#endif
+
+    return guest_walk_tables(v, p2m, va, &gw, walk, top_mfn, top_map, gf);
+}
+
 unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
     struct vcpu *v, struct p2m_domain *p2m, unsigned long gva, uint32_t *pfec)
 {
@@ -91,7 +121,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)(
 #if GUEST_PAGING_LEVELS == 3
     top_map += (cr3 & ~(PAGE_MASK | 31));
 #endif
-    walk_ok = guest_walk_tables(v, p2m, ga, &gw, *pfec, top_mfn, top_map);
+    walk_ok = guest_walk_tables(v, p2m, ga, &gw, *pfec, top_mfn, top_map, 
NULL);
     unmap_domain_page(top_map);
     put_page(top_page);
 
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 812a840..2da7b63 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -767,7 +767,8 @@ static const struct paging_mode hap_paging_real_mode = {
     .update_cr3             = hap_update_cr3,
     .update_paging_modes    = hap_update_paging_modes,
     .write_p2m_entry        = hap_write_p2m_entry,
-    .guest_levels           = 1
+    .guest_levels           = 1,
+    .pte_flags              = hap_pte_flags_2_levels
 };
 
 static const struct paging_mode hap_paging_protected_mode = {
@@ -778,7 +779,8 @@ static const struct paging_mode hap_paging_protected_mode = 
{
     .update_cr3             = hap_update_cr3,
     .update_paging_modes    = hap_update_paging_modes,
     .write_p2m_entry        = hap_write_p2m_entry,
-    .guest_levels           = 2
+    .guest_levels           = 2,
+    .pte_flags              = hap_pte_flags_2_levels
 };
 
 static const struct paging_mode hap_paging_pae_mode = {
@@ -789,7 +791,8 @@ static const struct paging_mode hap_paging_pae_mode = {
     .update_cr3             = hap_update_cr3,
     .update_paging_modes    = hap_update_paging_modes,
     .write_p2m_entry        = hap_write_p2m_entry,
-    .guest_levels           = 3
+    .guest_levels           = 3,
+    .pte_flags              = hap_pte_flags_3_levels
 };
 
 static const struct paging_mode hap_paging_long_mode = {
@@ -800,7 +803,8 @@ static const struct paging_mode hap_paging_long_mode = {
     .update_cr3             = hap_update_cr3,
     .update_paging_modes    = hap_update_paging_modes,
     .write_p2m_entry        = hap_write_p2m_entry,
-    .guest_levels           = 4
+    .guest_levels           = 4,
+    .pte_flags              = hap_pte_flags_4_levels
 };
 
 /*
diff --git a/xen/arch/x86/mm/hap/private.h b/xen/arch/x86/mm/hap/private.h
index 973fbe8..615b02a 100644
--- a/xen/arch/x86/mm/hap/private.h
+++ b/xen/arch/x86/mm/hap/private.h
@@ -47,4 +47,14 @@ unsigned long hap_p2m_ga_to_gfn_4_levels(struct vcpu *v,
     struct p2m_domain *p2m, unsigned long cr3,
     paddr_t ga, uint32_t *pfec, unsigned int *page_order);
 
+bool hap_pte_flags_2_levels(struct vcpu *v, struct p2m_domain *p2m,
+                            unsigned long va, uint32_t walk, unsigned long cr3,
+                            uint32_t *gf);
+bool hap_pte_flags_3_levels(struct vcpu *v, struct p2m_domain *p2m,
+                            unsigned long va, uint32_t walk, unsigned long cr3,
+                            uint32_t *gf);
+bool hap_pte_flags_4_levels(struct vcpu *v, struct p2m_domain *p2m,
+                            unsigned long va,  uint32_t walk, unsigned long 
cr3,
+                            uint32_t *gf);
+
 #endif /* __HAP_PRIVATE_H__ */
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
index 03a864156..b01194d 100644
--- a/xen/arch/x86/mm/mem_access.c
+++ b/xen/arch/x86/mm/mem_access.c
@@ -212,7 +212,20 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long gla,
          d->arch.monitor.inguest_pagefault_disabled &&
          npfec.kind != npfec_kind_with_gla ) /* don't send a mem_event */
     {
-        hvm_emulate_one_vm_event(EMUL_KIND_NORMAL, TRAP_invalid_op, 
X86_EVENT_NO_EC);
+        struct hvm_hw_cpu ctxt;
+        uint32_t pfec = PFEC_page_present;
+        unsigned long gfn;
+        uint32_t gflags;
+
+        hvm_funcs.save_cpu_ctxt(v, &ctxt);
+        paging_get_hostmode(v)->pte_flags(v, p2m, gla, 0, ctxt.cr3, &gflags);
+        if ( gflags & _PAGE_RW )
+            pfec |= PFEC_write_access;
+
+        if ( gflags & _PAGE_USER )
+            pfec |= PFEC_user_mode;
+
+        gfn = paging_ga_to_gfn_cr3(v, ctxt.cr3, gla, &pfec, NULL);
 
         return true;
     }
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 021ae25..199873f3 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -178,12 +178,12 @@ sh_walk_guest_tables(struct vcpu *v, unsigned long va, 
walk_t *gw,
     return guest_walk_tables(v, p2m_get_hostp2m(v->domain), va, gw, pfec,
 #if GUEST_PAGING_LEVELS == 3 /* PAE */
                              INVALID_MFN,
-                             v->arch.paging.shadow.gl3e
+                             v->arch.paging.shadow.gl3e,
 #else /* 32 or 64 */
                              pagetable_get_mfn(v->arch.guest_table),
-                             v->arch.paging.shadow.guest_vtable
+                             v->arch.paging.shadow.guest_vtable,
 #endif
-                             );
+                            NULL );
 }
 
 /* This validation is called with lock held, and after write permission
diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
index 08031c8..523ae34 100644
--- a/xen/include/asm-x86/guest_pt.h
+++ b/xen/include/asm-x86/guest_pt.h
@@ -425,7 +425,8 @@ static inline unsigned int guest_walk_to_page_order(const 
walk_t *gw)
 
 bool
 guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
-                  walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map);
+                  walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map,
+                  uint32_t *gf);
 
 /* Pretty-print the contents of a guest-walk */
 static inline void print_gw(const walk_t *gw)
diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h
index f008551..e5f21c9 100644
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -122,7 +122,10 @@ struct paging_mode {
     void          (*write_p2m_entry       )(struct domain *d, unsigned long 
gfn,
                                             l1_pgentry_t *p, l1_pgentry_t new,
                                             unsigned int level);
-
+    bool          (*pte_flags             )(struct vcpu *v,
+                                            struct p2m_domain *p2m,
+                                            unsigned long va, uint32_t walk,
+                                            unsigned long cr3, uint32_t *gf);
     unsigned int guest_levels;
 
     /* paging support extension */
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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