Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323660
b: refs/heads/master
c: c5e6319
h: refs/heads/master
v: v3
  • Loading branch information
Jiri Olsa authored and Arnaldo Carvalho de Melo committed Aug 10, 2012
1 parent 38eb329 commit e6b1efe
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b691f64360ecec49c44d534cf4c1798a438bfccb
refs/heads/master: c5e63197db519bae1c33e41ea0342a50f39e7a93
6 changes: 6 additions & 0 deletions trunk/arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ config HAVE_PERF_EVENTS_NMI
subsystem. Also has support for calculating CPU cycle events
to determine how many clock cycles in a given period.

config HAVE_PERF_REGS
bool
help
Support selective register dumps for perf events. This includes
bit-mapping of each registers and a unique architecture id.

config HAVE_ARCH_JUMP_LABEL
bool

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ config X86
select HAVE_MIXED_BREAKPOINTS_REGS
select PERF_EVENTS
select HAVE_PERF_EVENTS_NMI
select HAVE_PERF_REGS
select ANON_INODES
select HAVE_ALIGNED_STRUCT_PAGE if SLUB && !M386
select HAVE_CMPXCHG_LOCAL if !M386
Expand Down
33 changes: 33 additions & 0 deletions trunk/arch/x86/include/asm/perf_regs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef _ASM_X86_PERF_REGS_H
#define _ASM_X86_PERF_REGS_H

enum perf_event_x86_regs {
PERF_REG_X86_AX,
PERF_REG_X86_BX,
PERF_REG_X86_CX,
PERF_REG_X86_DX,
PERF_REG_X86_SI,
PERF_REG_X86_DI,
PERF_REG_X86_BP,
PERF_REG_X86_SP,
PERF_REG_X86_IP,
PERF_REG_X86_FLAGS,
PERF_REG_X86_CS,
PERF_REG_X86_SS,
PERF_REG_X86_DS,
PERF_REG_X86_ES,
PERF_REG_X86_FS,
PERF_REG_X86_GS,
PERF_REG_X86_R8,
PERF_REG_X86_R9,
PERF_REG_X86_R10,
PERF_REG_X86_R11,
PERF_REG_X86_R12,
PERF_REG_X86_R13,
PERF_REG_X86_R14,
PERF_REG_X86_R15,

PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
};
#endif /* _ASM_X86_PERF_REGS_H */
2 changes: 2 additions & 0 deletions trunk/arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
obj-$(CONFIG_OF) += devicetree.o
obj-$(CONFIG_UPROBES) += uprobes.o

obj-$(CONFIG_PERF_EVENTS) += perf_regs.o

###
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
Expand Down
90 changes: 90 additions & 0 deletions trunk/arch/x86/kernel/perf_regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/bug.h>
#include <linux/stddef.h>
#include <asm/perf_regs.h>
#include <asm/ptrace.h>

#ifdef CONFIG_X86_32
#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX
#else
#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX
#endif

#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)

static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = {
PT_REGS_OFFSET(PERF_REG_X86_AX, ax),
PT_REGS_OFFSET(PERF_REG_X86_BX, bx),
PT_REGS_OFFSET(PERF_REG_X86_CX, cx),
PT_REGS_OFFSET(PERF_REG_X86_DX, dx),
PT_REGS_OFFSET(PERF_REG_X86_SI, si),
PT_REGS_OFFSET(PERF_REG_X86_DI, di),
PT_REGS_OFFSET(PERF_REG_X86_BP, bp),
PT_REGS_OFFSET(PERF_REG_X86_SP, sp),
PT_REGS_OFFSET(PERF_REG_X86_IP, ip),
PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags),
PT_REGS_OFFSET(PERF_REG_X86_CS, cs),
PT_REGS_OFFSET(PERF_REG_X86_SS, ss),
#ifdef CONFIG_X86_32
PT_REGS_OFFSET(PERF_REG_X86_DS, ds),
PT_REGS_OFFSET(PERF_REG_X86_ES, es),
PT_REGS_OFFSET(PERF_REG_X86_FS, fs),
PT_REGS_OFFSET(PERF_REG_X86_GS, gs),
#else
/*
* The pt_regs struct does not store
* ds, es, fs, gs in 64 bit mode.
*/
(unsigned int) -1,
(unsigned int) -1,
(unsigned int) -1,
(unsigned int) -1,
#endif
#ifdef CONFIG_X86_64
PT_REGS_OFFSET(PERF_REG_X86_R8, r8),
PT_REGS_OFFSET(PERF_REG_X86_R9, r9),
PT_REGS_OFFSET(PERF_REG_X86_R10, r10),
PT_REGS_OFFSET(PERF_REG_X86_R11, r11),
PT_REGS_OFFSET(PERF_REG_X86_R12, r12),
PT_REGS_OFFSET(PERF_REG_X86_R13, r13),
PT_REGS_OFFSET(PERF_REG_X86_R14, r14),
PT_REGS_OFFSET(PERF_REG_X86_R15, r15),
#endif
};

u64 perf_reg_value(struct pt_regs *regs, int idx)
{
if (WARN_ON_ONCE(idx > ARRAY_SIZE(pt_regs_offset)))
return 0;

return regs_get_register(regs, pt_regs_offset[idx]);
}

#define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL))

#ifdef CONFIG_X86_32
int perf_reg_validate(u64 mask)
{
if (!mask || mask & REG_RESERVED)
return -EINVAL;

return 0;
}
#else /* CONFIG_X86_64 */
#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
(1ULL << PERF_REG_X86_ES) | \
(1ULL << PERF_REG_X86_FS) | \
(1ULL << PERF_REG_X86_GS))

int perf_reg_validate(u64 mask)
{
if (!mask || mask & REG_RESERVED)
return -EINVAL;

if (mask & REG_NOSUPPORT)
return -EINVAL;

return 0;
}
#endif /* CONFIG_X86_32 */
19 changes: 19 additions & 0 deletions trunk/include/linux/perf_regs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef _LINUX_PERF_REGS_H
#define _LINUX_PERF_REGS_H

#ifdef CONFIG_HAVE_PERF_REGS
#include <asm/perf_regs.h>
u64 perf_reg_value(struct pt_regs *regs, int idx);
int perf_reg_validate(u64 mask);
#else
static inline u64 perf_reg_value(struct pt_regs *regs, int idx)
{
return 0;
}

static inline int perf_reg_validate(u64 mask)
{
return mask ? -ENOSYS : 0;
}
#endif /* CONFIG_HAVE_PERF_REGS */
#endif /* _LINUX_PERF_REGS_H */

0 comments on commit e6b1efe

Please sign in to comment.