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

[RFC PATCH v1 09/10] vpmu.c hypervisor stacktrace support in vPMU



Signed-off-by: Edwin Török <edwin.torok@xxxxxxxxx>
---
 xen/arch/x86/cpu/vpmu.c | 53 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/cpu/vpmu.c b/xen/arch/x86/cpu/vpmu.c
index 770f63f95a..ad02ab9dd8 100644
--- a/xen/arch/x86/cpu/vpmu.c
+++ b/xen/arch/x86/cpu/vpmu.c
@@ -160,9 +160,51 @@ static inline struct vcpu *choose_hwdom_vcpu(void)
     return hardware_domain->vcpu[idx];
 }
 
+static inline void vpmu_hypervisor_stacktrace(struct xen_pmu_hv_stacktrace 
*xenpmu_stack, uint64_t rsp, uint64_t rbp)
+{
+#ifdef CONFIG_FRAME_POINTER
+    /* Based on _show_trace in ../traps.c,
+     * TODO: there should be an iterator to share this code
+     * */
+    unsigned long *frame, addr;
+    uint64_t low = rsp, high = get_stack_trace_bottom(rsp), next = rbp;
+
+    while(xenpmu_stack->stacktrace_nr < sizeof(xenpmu_stack->stacktrace) / 
sizeof(xenpmu_stack->stacktrace[0])) {
+        /* Valid frame pointer? */
+        if ( (next < low) || (next >= high) )
+        {
+            /*
+             * Exception stack frames have a different layout, denoted by an
+             * inverted frame pointer.
+             */
+            next = ~next;
+            if ( (next < low) || (next >= high) )
+                break;
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[(offsetof(struct cpu_user_regs, rip) -
+                           offsetof(struct cpu_user_regs, rbp))
+                         / BYTES_PER_LONG];
+        }
+        else
+        {
+            /* Ordinary stack frame. */
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[1];
+        }
+
+        xenpmu_stack->stacktrace[PMU_MAX_STACKTRACE - 1 - 
xenpmu_stack->stacktrace_nr++] = addr;
+
+        low = (unsigned long)&frame[2];
+    }
+#endif
+}
+
 static inline void vpmu_convert_regs(struct xen_pmu_regs *r, uint64_t *flags,
                                      struct vcpu *sampled,
-                                     const struct cpu_user_regs *cur_regs) {
+                                     const struct cpu_user_regs *cur_regs)
+{
   r->ip = cur_regs->rip;
   r->sp = cur_regs->rsp;
   r->flags = cur_regs->rflags;
@@ -246,6 +288,7 @@ void vpmu_do_interrupt(void)
 
             /* avoid stale values when domid != DOMID_XEN */
             vpmu->xenpmu_hv_stacktrace->guest.r.regs.ip = 0;
+            vpmu->xenpmu_hv_stacktrace->stacktrace_nr = 0;
         }
 
         /* Store appropriate registers in xenpmu_data */
@@ -287,6 +330,11 @@ void vpmu_do_interrupt(void)
                 {
                     
vpmu_convert_regs(&vpmu->xenpmu_hv_stacktrace->guest.r.regs,
                                       NULL, sampled, guest_cpu_user_regs());
+
+                    /* can only call this when domid == DOMID_XEN */
+                    if (vpmu_features & XENPMU_FEATURE_HV_STACKTRACE)
+                      vpmu_hypervisor_stacktrace(vpmu->xenpmu_hv_stacktrace,
+                                                 regs->rsp, regs->rbp);
                 }
                 domid = DOMID_XEN;
             }
@@ -747,7 +795,8 @@ long do_xenpmu_op(
     case XENPMU_feature_set:
         if ( pmu_params.val & ~(XENPMU_FEATURE_INTEL_BTS |
                                 XENPMU_FEATURE_IPC_ONLY |
-                                XENPMU_FEATURE_ARCH_ONLY))
+                                XENPMU_FEATURE_ARCH_ONLY |
+                                XENPMU_FEATURE_HV_STACKTRACE))
             return -EINVAL;
 
         spin_lock(&vpmu_lock);
-- 
2.47.1




 


Rackspace

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