-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'arm-perf-3.19' of git://git.kernel.org/pub/scm/linux/kerne…
…l/git/will/linux into next/drivers Pull "ARM: perf: updates for 3.19" from Will Deacon: This patch series takes us slightly further on the road to big.LITTLE support in perf. The main change enabling this is moving the CCI PMU driver away from the arm-pmu abstraction, allowing the arch code to focus specifically on support for CPU PMUs. * tag 'arm-perf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux: arm: perf: fold hotplug notifier into arm_pmu arm: perf: dynamically allocate cpu hardware data arm: perf: fold percpu_pmu into pmu_hw_events arm: perf: kill get_hw_events() arm: perf: limit size of accounting data arm: perf: use IDR types for CPU PMUs arm: perf: make PMU probing data-driven arm: perf: add missing pr_info newlines arm: perf: factor out callchain code ARM: perf: use pr_* instead of printk ARM: perf: remove useless return and check of idx in counter handling bus: cci: move away from arm_pmu framework Signed-off-by: Arnd Bergmann <arnd@arndb.de>
- Loading branch information
Showing
10 changed files
with
772 additions
and
403 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* ARM callchain support | ||
* | ||
* Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles | ||
* Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com> | ||
* | ||
* This code is based on the ARM OProfile backtrace code. | ||
*/ | ||
#include <linux/perf_event.h> | ||
#include <linux/uaccess.h> | ||
|
||
#include <asm/stacktrace.h> | ||
|
||
/* | ||
* The registers we're interested in are at the end of the variable | ||
* length saved register structure. The fp points at the end of this | ||
* structure so the address of this struct is: | ||
* (struct frame_tail *)(xxx->fp)-1 | ||
* | ||
* This code has been adapted from the ARM OProfile support. | ||
*/ | ||
struct frame_tail { | ||
struct frame_tail __user *fp; | ||
unsigned long sp; | ||
unsigned long lr; | ||
} __attribute__((packed)); | ||
|
||
/* | ||
* Get the return address for a single stackframe and return a pointer to the | ||
* next frame tail. | ||
*/ | ||
static struct frame_tail __user * | ||
user_backtrace(struct frame_tail __user *tail, | ||
struct perf_callchain_entry *entry) | ||
{ | ||
struct frame_tail buftail; | ||
unsigned long err; | ||
|
||
if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) | ||
return NULL; | ||
|
||
pagefault_disable(); | ||
err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); | ||
pagefault_enable(); | ||
|
||
if (err) | ||
return NULL; | ||
|
||
perf_callchain_store(entry, buftail.lr); | ||
|
||
/* | ||
* Frame pointers should strictly progress back up the stack | ||
* (towards higher addresses). | ||
*/ | ||
if (tail + 1 >= buftail.fp) | ||
return NULL; | ||
|
||
return buftail.fp - 1; | ||
} | ||
|
||
void | ||
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()) { | ||
/* We don't support guest os callchain now */ | ||
return; | ||
} | ||
|
||
perf_callchain_store(entry, regs->ARM_pc); | ||
|
||
if (!current->mm) | ||
return; | ||
|
||
tail = (struct frame_tail __user *)regs->ARM_fp - 1; | ||
|
||
while ((entry->nr < PERF_MAX_STACK_DEPTH) && | ||
tail && !((unsigned long)tail & 0x3)) | ||
tail = user_backtrace(tail, entry); | ||
} | ||
|
||
/* | ||
* Gets called by walk_stackframe() for every stackframe. This will be called | ||
* whist unwinding the stackframe and is like a subroutine return so we use | ||
* the PC. | ||
*/ | ||
static int | ||
callchain_trace(struct stackframe *fr, | ||
void *data) | ||
{ | ||
struct perf_callchain_entry *entry = data; | ||
perf_callchain_store(entry, fr->pc); | ||
return 0; | ||
} | ||
|
||
void | ||
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()) { | ||
/* We don't support guest os callchain now */ | ||
return; | ||
} | ||
|
||
arm_get_current_stackframe(regs, &fr); | ||
walk_stackframe(&fr, 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; | ||
} |
Oops, something went wrong.