提交 75e42462 编写于 作者: M Marc Zyngier 提交者: Catalin Marinas

arm64: perf: add guest vs host discrimination

Add minimal guest support to perf, so it can distinguish whether
the PMU interrupt was in the host or the guest, as well as collecting
some very basic information (guest PC, user vs kernel mode).

This is not feature complete though, as it doesn't support backtracing
in the guest.

Based on the x86 implementation, tested with KVM/arm64.
Signed-off-by: NMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: NCatalin Marinas <catalin.marinas@arm.com>
上级 10a3cc2f
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
#ifndef __ASM_PERF_EVENT_H #ifndef __ASM_PERF_EVENT_H
#define __ASM_PERF_EVENT_H #define __ASM_PERF_EVENT_H
/* It's quiet around here... */ #ifdef CONFIG_HW_PERF_EVENTS
struct pt_regs;
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
extern unsigned long perf_misc_flags(struct pt_regs *regs);
#define perf_misc_flags(regs) perf_misc_flags(regs)
#endif
#endif #endif
...@@ -1331,6 +1331,11 @@ void perf_callchain_user(struct perf_callchain_entry *entry, ...@@ -1331,6 +1331,11 @@ void perf_callchain_user(struct perf_callchain_entry *entry,
{ {
struct frame_tail __user *tail; struct frame_tail __user *tail;
if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
/* We don't support guest os callchain now */
return;
}
tail = (struct frame_tail __user *)regs->regs[29]; tail = (struct frame_tail __user *)regs->regs[29];
while (entry->nr < PERF_MAX_STACK_DEPTH && while (entry->nr < PERF_MAX_STACK_DEPTH &&
...@@ -1355,8 +1360,40 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, ...@@ -1355,8 +1360,40 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
{ {
struct stackframe frame; struct stackframe frame;
if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
/* We don't support guest os callchain now */
return;
}
frame.fp = regs->regs[29]; frame.fp = regs->regs[29];
frame.sp = regs->sp; frame.sp = regs->sp;
frame.pc = regs->pc; frame.pc = regs->pc;
walk_stackframe(&frame, callchain_trace, entry); walk_stackframe(&frame, callchain_trace, entry);
} }
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
return perf_guest_cbs->get_guest_ip();
return instruction_pointer(regs);
}
unsigned long perf_misc_flags(struct pt_regs *regs)
{
int misc = 0;
if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
if (perf_guest_cbs->is_user_mode())
misc |= PERF_RECORD_MISC_GUEST_USER;
else
misc |= PERF_RECORD_MISC_GUEST_KERNEL;
} else {
if (user_mode(regs))
misc |= PERF_RECORD_MISC_USER;
else
misc |= PERF_RECORD_MISC_KERNEL;
}
return misc;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册