|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |