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

[Xen-devel] [PATCH 07 of 10] xenalyze: decode PV_HYPERCALL_V2 records



Newer version of Xen produce TRC_PV_HYPERCALL_V2 records instead of
the older TRC_PV_HYPERCALL format.  This updated format doesn't
included the IP but it does include select hypercall arguments.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>

diff --git a/pv.h b/pv.h
new file mode 100644
--- /dev/null
+++ b/pv.h
@@ -0,0 +1,41 @@
+/*
+ * PV event decoding.
+ *
+ * Copyright (C) 2012 Citrix Systems R&D Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef __PV_H
+
+#include "analyze.h"
+#include "trace.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ARG_MISSING 0x0
+#define ARG_32BIT 0x1
+#define ARG_64BIT 0x2
+
+#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
+
+static inline uint32_t pv_hypercall_op(const struct record_info *ri)
+{
+    return ri->d[0] & ~TRC_PV_HYPERCALL_V2_ARG_MASK;
+}
+
+static inline int pv_hypercall_arg_present(const struct record_info *ri, int 
arg)
+{
+    return (ri->d[0] >> (20 + 2*arg)) & 0x3;
+}
+
+uint64_t pv_hypercall_arg(const struct record_info *ri, int i);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/xenalyze.c b/xenalyze.c
--- a/xenalyze.c
+++ b/xenalyze.c
@@ -32,6 +32,7 @@
 #include "trace.h"
 #include "analyze.h"
 #include "mread.h"
+#include "pv.h"
 #include <errno.h>
 #include <strings.h>
 #include <string.h>
@@ -1480,6 +1481,7 @@ enum {
     PV_GDT_LDT_MAPPING_FAULT,
     PV_PTWR_EMULATION,
     PV_PTWR_EMULATION_PAE,
+    PV_HYPERCALL_V2 = 13,
     PV_MAX
 };
 
@@ -6518,6 +6520,96 @@ void pv_summary(struct pv_data *pv) {
     }
 }
 
+uint64_t pv_hypercall_arg(const struct record_info *ri, int arg)
+{
+    int i, word;
+
+    for (i = 0, word = 1; i < 6 && word < ri->extra_words; i++) {
+        int present = pv_hypercall_arg_present(ri, i);
+
+        /* Is this the argument we're looking for? */
+        if (i == arg) {
+            switch (present) {
+            case ARG_MISSING:
+                return 0;
+            case ARG_32BIT:
+                return ri->d[word];
+            case ARG_64BIT:
+                return (uint64_t)(ri->d[word + 1]) | ri->d[word];
+            }
+        }
+
+        /* Skip over any words for this argument. */
+        word += present;
+    }
+
+    return 0;
+}
+
+static const char *grant_table_op_cmd_to_str(uint32_t cmd)
+{
+    const char *cmd_str[] = {
+        "map_grant_ref", "unmap_grant_ref", "setup_table", "dump_table",
+        "transfer", "copy", "query_size", "unmap_and_replace",
+        "set_version", "get_status_frames", "get_version", "swap_grant_ref",
+    };
+    static char buf[32];
+
+    if (cmd <= 11)
+        return cmd_str[cmd];
+
+    snprintf(buf, sizeof(buf), "unknown (%d)", cmd);
+    return buf;
+}
+
+void pv_hypercall_v2_process(struct record_info *ri, struct pv_data *pv)
+{
+    int op = pv_hypercall_op(ri);
+
+    if(opt.summary_info) {
+        if(op < PV_HYPERCALL_MAX) 
+            pv->hypercall_count[op]++;
+    }
+
+    if(opt.dump_all) {
+        if(op < HYPERCALL_MAX)
+            printf(" %s hypercall %2x (%s)",
+                   ri->dump_header, op, hypercall_name[op]);
+        else
+            printf(" %s hypercall %2x",
+                   ri->dump_header, op);
+        switch(op) {
+        case HYPERCALL_mmu_update:
+            {
+                uint32_t count = pv_hypercall_arg(ri, 1);
+                printf(" %d updates%s", count & ~MMU_UPDATE_PREEMPTED,
+                       (count & MMU_UPDATE_PREEMPTED) ? " (preempted)" : "");
+            }
+            break;
+        case HYPERCALL_multicall:
+            {
+                uint32_t calls = pv_hypercall_arg(ri, 1);
+                printf(" %d calls", calls);
+            }
+            break;
+        case HYPERCALL_grant_table_op:
+            {
+                uint32_t cmd = pv_hypercall_arg(ri, 0);
+                uint32_t count = pv_hypercall_arg(ri, 2);
+                printf(" %s %d ops", grant_table_op_cmd_to_str(cmd), count);
+            }
+            break;
+        case HYPERCALL_mmuext_op:
+            {
+                uint32_t count = pv_hypercall_arg(ri, 1);
+                printf(" %d ops", count);
+            }
+            break;
+        }
+        printf("\n");
+    }
+}
+
 void pv_process(struct pcpu_info *p)
 {
     struct record_info *ri = &p->ri;
@@ -6550,9 +6642,9 @@ void pv_process(struct pcpu_info *p)
     case PV_PTWR_EMULATION_PAE:
         pv_ptwr_emulation_process(ri, pv);
         break;
-    case PV_PAGE_FAULT:
-        //pv_pf_process(ri, pv);
-        //break;
+    case PV_HYPERCALL_V2:
+        pv_hypercall_v2_process(ri, pv);
+        break;
     default:
         pv_generic_process(ri, pv);
         break;

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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