On 07/09/12 15:28, Will Deacon wrote: > On Thu, Sep 06, 2012 at 06:16:03PM +0100, Marc Zyngier wrote: >> 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/ARM. >> >> Cc: Will Deacon <will.deacon@xxxxxxx> >> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> >> --- >> arch/arm/include/asm/perf_event.h | 7 ++++++- >> arch/arm/kernel/perf_event.c | 36 ++++++++++++++++++++++++++++++++++++ >> 2 files changed, 42 insertions(+), 1 deletion(-) >> >> diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h >> index e074948..77537bb 100644 >> --- a/arch/arm/include/asm/perf_event.h >> +++ b/arch/arm/include/asm/perf_event.h >> @@ -12,6 +12,11 @@ >> #ifndef __ARM_PERF_EVENT_H__ >> #define __ARM_PERF_EVENT_H__ >> >> -/* Nothing to see here... */ >> +/* Not much to see here... */ > > You can just remove this silly comment :) Now you're taking away the little fun I had hacking this. Life is soooo cruel... ;-) >> +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 /* __ARM_PERF_EVENT_H__ */ >> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c >> index ab243b8..8836425 100644 >> --- a/arch/arm/kernel/perf_event.c >> +++ b/arch/arm/kernel/perf_event.c >> @@ -817,6 +817,10 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) >> { >> struct frame_tail __user *tail; >> >> + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { >> + /* TODO: We don't support guest os callchain now */ >> + return; >> + } >> >> tail = (struct frame_tail __user *)regs->ARM_fp - 1; >> >> @@ -844,9 +848,41 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) >> { >> struct stackframe fr; >> >> + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { >> + /* TODO: We don't support guest os callchain now */ >> + return; >> + } >> + > > Will we ever support this? It sounds incredibly difficult -- how can you > walk the guest stack without things disappearing under your feet? It's hard, but not impossible: - Stop the world (all vcpus) - Repeatedly call into HYP mode to resolve all the VAs needed by the backtrace (cringe...) - Restart the world - Witness your guest running at the speed of a snail lost in the Sahara. I reckon it is a perfect project for a summer student! :-) >> +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; >> +} > > Hmm, both of these look like they should be made generic but I see that x86 > and ppc do have some differences, so I guess we should have our own copies > for the time being... We can probably factor in the common code and let ARM use the default. I'll have a look if I get a chance. Thanks, M. -- Jazz is not dead. It just smells funny... _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm