Skip to contentSkip to conversation

P2M audit rework

PATCH New Andres Lagar-Cavilla 1 participant 3 messages Nov 24, 2011

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 P2M audit rework

Bring the p2m audit back from the dead. Tease out -ept and -pt specific code. TUrn it into a domctl.

 xen/arch/x86/domctl.c       |   30 +++++++++
 xen/arch/x86/mm/p2m-ept.c   |    1 +
 xen/arch/x86/mm/p2m-pod.c   |    5 -
 xen/arch/x86/mm/p2m-pt.c    |  137 +++++++------------------------------------
 xen/arch/x86/mm/p2m.c       |  124 ++++++++++++++++++++++++++++++++++++---
 xen/include/asm-x86/p2m.h   |   11 ++-
 xen/include/public/domctl.h |   12 +++
 tools/libxc/xc_domain.c     |   22 +++++++
 tools/libxc/xenctrl.h       |   27 ++++++++
 9 files changed, 235 insertions(+), 134 deletions(-)
#1 lore raw

PATCH 1/1 Rework stale p2m auditing

 xen/arch/x86/domctl.c       |   30 +++++++++
 xen/arch/x86/mm/p2m-ept.c   |    1 +
 xen/arch/x86/mm/p2m-pod.c   |    5 -
 xen/arch/x86/mm/p2m-pt.c    |  137 +++++++------------------------------------
 xen/arch/x86/mm/p2m.c       |  124 ++++++++++++++++++++++++++++++++++++---
 xen/include/asm-x86/p2m.h   |   11 ++-
 xen/include/public/domctl.h |   12 +++
 7 files changed, 186 insertions(+), 134 deletions(-)

The p2m audit code doesn't even compile, let alone work. It also partially supports ept. Make it:

- compile
- lay groundwork for eventual ept support
- move out of the way of all calls and turn it into a domctl. It's obviously not being used by anybody presently.
- enable it via said domctl

xen/arch/x86/domctl.c +30 -0
diff -r 9e44fd6e4955 -r f964ff59ca6c xen/arch/x86/domctl.c
@@ -1449,6 +1449,36 @@ long arch_do_domctl(
     break;
 #endif /* __x86_64__ */
 
+    case XEN_DOMCTL_audit_p2m:
+    {
+        struct domain *d;
+
+        ret = -ESRCH;
+        d = rcu_lock_domain_by_id(domctl->domain);
+        if ( d != NULL )
+        {
+            ret = -EPERM;
+            if ( (domctl->domain != DOMID_SELF) &&
+                 (d != current->domain) &&
+                 (IS_PRIV_FOR(current->domain, d)) )
+            {
+#if P2M_AUDIT
+                audit_p2m(d,
+                          &domctl->u.audit_p2m.orphans_debug,
+                          &domctl->u.audit_p2m.orphans_invalid,
+                          &domctl->u.audit_p2m.m2p_bad,
+                          &domctl->u.audit_p2m.p2m_bad);
+                ret = (copy_to_guest(u_domctl, domctl, 1)) ?
+                        -EFAULT : 0;
+#else
+                ret = -ENOSYS;
+#endif /* P2M_AUDIT */
+            }
+            rcu_unlock_domain(d);
+        }
+    }
+    break;
+
     case XEN_DOMCTL_set_access_required:
     {
         struct domain *d;
xen/arch/x86/mm/p2m-ept.c +1 -0
diff -r 9e44fd6e4955 -r f964ff59ca6c xen/arch/x86/mm/p2m-ept.c
@@ -817,6 +817,7 @@ void ept_p2m_init(struct p2m_domain *p2m
     p2m->set_entry = ept_set_entry;
     p2m->get_entry = ept_get_entry;
     p2m->change_entry_type_global = ept_change_entry_type_global;
+    p2m->audit_p2m = NULL;
 }
 
 static void ept_dump_p2m_table(unsigned char key)
xen/arch/x86/mm/p2m-pod.c +0 -5
diff -r 9e44fd6e4955 -r f964ff59ca6c xen/arch/x86/mm/p2m-pod.c
@@ -522,7 +522,6 @@ p2m_pod_decrease_reservation(struct doma
     steal_for_cache =  ( p2m->pod.entry_count > p2m->pod.count );
 
     p2m_lock(p2m);
-    audit_p2m(p2m, 1);
 
     if ( unlikely(d->is_dying) )
         goto out_unlock;
@@ -616,7 +615,6 @@ out_entry_check:
     }
 
 out_unlock:
-    audit_p2m(p2m, 1);
     p2m_unlock(p2m);
 
 out:
@@ -986,7 +984,6 @@ p2m_pod_demand_populate(struct p2m_domai
          */
         set_p2m_entry(p2m, gfn_aligned, _mfn(0), PAGE_ORDER_2M,
                       p2m_populate_on_demand, p2m->default_access);
-        audit_p2m(p2m, 1);
         return 0;
     }
 
@@ -1108,7 +1105,6 @@ guest_physmap_mark_populate_on_demand(st
         return rc;
 
     p2m_lock(p2m);
-    audit_p2m(p2m, 1);
 
     P2M_DEBUG("mark pod gfn=%#lx\n", gfn);
 
@@ -1142,7 +1138,6 @@ guest_physmap_mark_populate_on_demand(st
         BUG_ON(p2m->pod.entry_count < 0);
     }
 
-    audit_p2m(p2m, 1);
     p2m_unlock(p2m);
 
 out:
xen/arch/x86/mm/p2m-pt.c +23 -114

172 lines not on this page · raw message

xen/arch/x86/mm/p2m.c +113 -11

191 lines not on this page · raw message

xen/include/asm-x86/p2m.h +7 -4
diff -r 9e44fd6e4955 -r f964ff59ca6c xen/include/asm-x86/p2m.h
@@ -245,6 +245,7 @@ struct p2m_domain {
                                           unsigned long gfn, l1_pgentry_t *p,
                                           mfn_t table_mfn, l1_pgentry_t new,
                                           unsigned int level);
+    long               (*audit_p2m)(struct p2m_domain *p2m);
 
     /* Default P2M access type for each page in the the domain: new pages,
      * swapped in pages, cleared pages, and pages that are ambiquously
@@ -559,13 +560,15 @@ int set_p2m_entry(struct p2m_domain *p2m
 extern void p2m_pt_init(struct p2m_domain *p2m);
 
 /* Debugging and auditing of the P2M code? */
-#define P2M_AUDIT     0
+#define P2M_AUDIT     1
 #define P2M_DEBUGGING 0
 
 #if P2M_AUDIT
-extern void audit_p2m(struct p2m_domain *p2m, int strict_m2p);
-#else
-# define audit_p2m(_p2m, _m2p) do { (void)(_p2m),(_m2p); } while (0)
+extern void audit_p2m(struct domain *d,
+                        uint64_t *orphans_debug,
+                        uint64_t *orphans_invalid,
+                        uint64_t *m2p_bad,
+                        uint64_t *p2m_bad);
 #endif /* P2M_AUDIT */
 
 /* Printouts */
xen/include/public/domctl.h +12 -0
diff -r 9e44fd6e4955 -r f964ff59ca6c xen/include/public/domctl.h
@@ -800,6 +800,16 @@ struct xen_domctl_mem_sharing_op {
 typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_sharing_op_t);
 
+struct xen_domctl_audit_p2m {
+    /* OUT error counts */
+    uint64_t orphans_debug;
+    uint64_t orphans_invalid;
+    uint64_t m2p_bad;
+    uint64_t p2m_bad;
+};
+typedef struct xen_domctl_audit_p2m xen_domctl_audit_p2m_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_audit_p2m_t);
+
 #if defined(__i386__) || defined(__x86_64__)
 /* XEN_DOMCTL_setvcpuextstate */
 /* XEN_DOMCTL_getvcpuextstate */
@@ -898,6 +908,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_setvcpuextstate               62
 #define XEN_DOMCTL_getvcpuextstate               63
 #define XEN_DOMCTL_set_access_required           64
+#define XEN_DOMCTL_audit_p2m                     65
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -951,6 +962,7 @@ struct xen_domctl {
         struct xen_domctl_vcpuextstate      vcpuextstate;
 #endif
         struct xen_domctl_set_access_required access_required;
+        struct xen_domctl_audit_p2m         audit_p2m;
         struct xen_domctl_gdbsx_memio       gdbsx_guest_memio;
         struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
         struct xen_domctl_gdbsx_domstatus   gdbsx_domstatus;
#2 lore raw

PATCH 1/1 Add libxc wrapper for p2m audit domctl

In reply to Andres Lagar-Cavilla
 tools/libxc/xc_domain.c |  22 ++++++++++++++++++++++
 tools/libxc/xenctrl.h   |  27 +++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)
tools/libxc/xc_domain.c +22 -0
diff -r f964ff59ca6c -r 1994287f9fc1 tools/libxc/xc_domain.c
@@ -1472,6 +1472,28 @@ int xc_domain_debug_control(xc_interface
     return do_domctl(xc, &domctl);
 }
 
+int xc_domain_p2m_audit(xc_interface *xch, 
+                        uint32_t domid,
+                        uint64_t *orphans_debug,
+                        uint64_t *orphans_invalid,
+                        uint64_t *m2p_bad,   
+                        uint64_t *p2m_bad)
+{
+    DECLARE_DOMCTL;
+    int rc;
+
+    domctl.cmd = XEN_DOMCTL_audit_p2m;
+    domctl.domain = domid;
+    rc = do_domctl(xch, &domctl);
+
+    *orphans_debug      = domctl.u.audit_p2m.orphans_debug;
+    *orphans_invalid    = domctl.u.audit_p2m.orphans_invalid;
+    *m2p_bad            = domctl.u.audit_p2m.m2p_bad;
+    *p2m_bad            = domctl.u.audit_p2m.p2m_bad;
+
+    return rc;
+}
+
 int xc_domain_set_access_required(xc_interface *xch,
                                   uint32_t domid,
                                   unsigned int required)
tools/libxc/xenctrl.h +27 -0
diff -r f964ff59ca6c -r 1994287f9fc1 tools/libxc/xenctrl.h
@@ -712,6 +712,33 @@ int xc_domain_setdebugging(xc_interface 
                            unsigned int enable);
 
 /**
+ * This function audits the (top level) p2m of a domain 
+ * and returns the different error counts, if any.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id whose top level p2m we 
+ *       want to audit
+ * @parm orphans_debug count of m2p entries for valid
+ *       domain pages containing a debug value
+ * @parm orphans_invalid count of m2p entries for valid
+ *       domain pages containing an invalid value
+ * @parm m2p_bad count of m2p entries mismatching the
+ *       associated p2m entry for this domain
+ * @parm p2m_bad count of p2m entries for this domain
+ *       mismatching the associated m2p entry
+ * return 0 on success, -1 on failure
+ * errno values on failure include: 
+ *          -ENOSYS: not implemented
+ *          -EFAULT: could not copy results back to guest
+ */
+int xc_domain_p2m_audit(xc_interface *xch,
+				        uint32_t domid,
+                        uint64_t *orphans_debug,
+                        uint64_t *orphans_invalid,
+                        uint64_t *m2p_bad,   
+                        uint64_t *p2m_bad);
+
+/**
  * This function sets or clears the requirement that an access memory
  * event listener is required on the domain.
  *