Re: [PATCH 02/16] perf: Unified API to record selective sets of arch registers

From: Stephane Eranian
Date: Mon Apr 23 2012 - 06:10:58 EST


On Tue, Apr 17, 2012 at 1:17 PM, Jiri Olsa <jolsa@xxxxxxxxxx> wrote:
> This brings a new API to help the selective dump of registers on
> event sampling, and its implementation in x86.
>
> - The informations about the desired registers will be passed
> Âto a single u64 mask. It's up to the architecture to map the
> Âregisters into the mask bits.
>
> - The architecture must provide a non-zero and unique id to
> Âidentify the origin of a register set because interpreting a
> Âregister dump requires to know from which architecture it comes.
> ÂThe achitecture is considered different between the 32 and 64 bits
> Âversion. x86-32 has the id 1, x86-64 has the id 2.
>
> Signed-off-by: Frederic Weisbecker <fweisbec@xxxxxxxxx>
> Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
> ---
> Âarch/x86/include/asm/perf_regs.h  Â|  16 ++++++
> Âarch/x86/include/asm/perf_regs_32.h | Â 84 +++++++++++++++++++++++++++++
> Âarch/x86/include/asm/perf_regs_64.h | Â101 +++++++++++++++++++++++++++++++++++
> Âinclude/asm-generic/perf_regs.h   |  23 ++++++++
> Â4 files changed, 224 insertions(+), 0 deletions(-)
> Âcreate mode 100644 arch/x86/include/asm/perf_regs.h
> Âcreate mode 100644 arch/x86/include/asm/perf_regs_32.h
> Âcreate mode 100644 arch/x86/include/asm/perf_regs_64.h
> Âcreate mode 100644 include/asm-generic/perf_regs.h
>
> diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h
> new file mode 100644
> index 0000000..80b7fbe
> --- /dev/null
> +++ b/arch/x86/include/asm/perf_regs.h
> @@ -0,0 +1,16 @@
> +#ifndef _ASM_X86_PERF_REGS_H
> +#define _ASM_X86_PERF_REGS_H
> +
> +enum {
> + Â Â Â PERF_REGS_VERSION_NONE Â = 0UL,
> + Â Â Â PERF_REGS_VERSION_X86_32 = 1UL,
> + Â Â Â PERF_REGS_VERSION_X86_64 = 2UL,
> +};
> +
I don't really like the term VERSION here. It's not a versioning
problem you're trying to solve. It's an ABI problem, unless I am
mistaken. You should rename to PERF_REGS_ABI_X86_32 and
PERF_REGS_ABI_X86_64.

I assume the NONE is here to cover the case where you don't
have a user machine state, i.e., hit a kernel thread. Is that right?


> +#ifdef CONFIG_X86_32
> +#include "perf_regs_32.h"
> +#else
> +#include "perf_regs_64.h"
> +#endif
> +
How are you going to deal with 32-bit binaries sampled on a 64-bit system?

> +#endif /* _ASM_X86_PERF_REGS_H */
> diff --git a/arch/x86/include/asm/perf_regs_32.h b/arch/x86/include/asm/perf_regs_32.h
> new file mode 100644
> index 0000000..3c5aa80
> --- /dev/null
> +++ b/arch/x86/include/asm/perf_regs_32.h
> @@ -0,0 +1,84 @@
> +#ifndef _ASM_X86_PERF_REGS_32_H
> +#define _ASM_X86_PERF_REGS_32_H
> +
> +enum perf_event_x86_32_regs {
> + Â Â Â PERF_X86_32_REG_EAX,
> + Â Â Â PERF_X86_32_REG_EBX,
> + Â Â Â PERF_X86_32_REG_ECX,
> + Â Â Â PERF_X86_32_REG_EDX,
> + Â Â Â PERF_X86_32_REG_ESI,
> + Â Â Â PERF_X86_32_REG_EDI,
> + Â Â Â PERF_X86_32_REG_EBP,
> + Â Â Â PERF_X86_32_REG_ESP,
> + Â Â Â PERF_X86_32_REG_EIP,
> + Â Â Â PERF_X86_32_REG_FLAGS,
> + Â Â Â PERF_X86_32_REG_CS,
> + Â Â Â PERF_X86_32_REG_DS,
> + Â Â Â PERF_X86_32_REG_ES,
> + Â Â Â PERF_X86_32_REG_FS,
> + Â Â Â PERF_X86_32_REG_GS,
> +
> + Â Â Â /* Non ABI */
> + Â Â Â PERF_X86_32_REG_MAX,
> + Â Â Â PERF_REG_IP = PERF_X86_32_REG_EIP,
> + Â Â Â PERF_REG_SP = PERF_X86_32_REG_ESP,
> +};
> +
> +#ifdef __KERNEL__
> +
> +#define PERF_X86_32_REG_RESERVED (~((1ULL << PERF_X86_32_REG_MAX) - 1ULL))
> +
> +static inline u64 perf_reg_version(void)
> +{
> + Â Â Â return PERF_REGS_VERSION_X86_32;
> +}
> +
> +static inline int perf_reg_validate(u64 mask)
> +{
> + Â Â Â if (mask & PERF_X86_32_REG_RESERVED)
> + Â Â Â Â Â Â Â return -EINVAL;
> +
> + Â Â Â return 0;
> +}
> +
> +static inline u64 perf_reg_value(struct pt_regs *regs, int idx)
> +{
> + Â Â Â switch (idx) {
> + Â Â Â case PERF_X86_32_REG_EAX:
> + Â Â Â Â Â Â Â return regs->ax;
> + Â Â Â case PERF_X86_32_REG_EBX:
> + Â Â Â Â Â Â Â return regs->bx;
> + Â Â Â case PERF_X86_32_REG_ECX:
> + Â Â Â Â Â Â Â return regs->cx;
> + Â Â Â case PERF_X86_32_REG_EDX:
> + Â Â Â Â Â Â Â return regs->dx;
> + Â Â Â case PERF_X86_32_REG_ESI:
> + Â Â Â Â Â Â Â return regs->si;
> + Â Â Â case PERF_X86_32_REG_EDI:
> + Â Â Â Â Â Â Â return regs->di;
> + Â Â Â case PERF_X86_32_REG_EBP:
> + Â Â Â Â Â Â Â return regs->bp;
> + Â Â Â case PERF_X86_32_REG_ESP:
> + Â Â Â Â Â Â Â return regs->sp;
> + Â Â Â case PERF_X86_32_REG_EIP:
> + Â Â Â Â Â Â Â return regs->ip;
> + Â Â Â case PERF_X86_32_REG_FLAGS:
> + Â Â Â Â Â Â Â return regs->flags;
> + Â Â Â case PERF_X86_32_REG_CS:
> + Â Â Â Â Â Â Â return regs->cs;
> + Â Â Â case PERF_X86_32_REG_DS:
> + Â Â Â Â Â Â Â return regs->ds;
> + Â Â Â case PERF_X86_32_REG_ES:
> + Â Â Â Â Â Â Â return regs->es;
> + Â Â Â case PERF_X86_32_REG_FS:
> + Â Â Â Â Â Â Â return regs->fs;
> + Â Â Â case PERF_X86_32_REG_GS:
> + Â Â Â Â Â Â Â return regs->gs;
> + Â Â Â }
> +
> + Â Â Â return 0;
> +}
> +
> +#endif /* __KERNEL__ */
> +
> +#endif /* _ASM_X86_PERF_REGS_32_H */
> diff --git a/arch/x86/include/asm/perf_regs_64.h b/arch/x86/include/asm/perf_regs_64.h
> new file mode 100644
> index 0000000..d775213
> --- /dev/null
> +++ b/arch/x86/include/asm/perf_regs_64.h
> @@ -0,0 +1,101 @@
> +#ifndef _ASM_X86_PERF_REGS_64_H
> +#define _ASM_X86_PERF_REGS_64_H
> +
> +#define PERF_X86_64_REG_VERSION Â Â Â Â Â Â Â Â1ULL
> +
> +enum perf_event_x86_64_regs {
> + Â Â Â PERF_X86_64_REG_RAX,
> + Â Â Â PERF_X86_64_REG_RBX,
> + Â Â Â PERF_X86_64_REG_RCX,
> + Â Â Â PERF_X86_64_REG_RDX,
> + Â Â Â PERF_X86_64_REG_RSI,
> + Â Â Â PERF_X86_64_REG_RDI,
> + Â Â Â PERF_X86_64_REG_R8,
> + Â Â Â PERF_X86_64_REG_R9,
> + Â Â Â PERF_X86_64_REG_R10,
> + Â Â Â PERF_X86_64_REG_R11,
> + Â Â Â PERF_X86_64_REG_R12,
> + Â Â Â PERF_X86_64_REG_R13,
> + Â Â Â PERF_X86_64_REG_R14,
> + Â Â Â PERF_X86_64_REG_R15,
> + Â Â Â PERF_X86_64_REG_RBP,
> + Â Â Â PERF_X86_64_REG_RSP,
> + Â Â Â PERF_X86_64_REG_RIP,
> + Â Â Â PERF_X86_64_REG_FLAGS,
> + Â Â Â PERF_X86_64_REG_CS,
> + Â Â Â PERF_X86_64_REG_SS,
> +
> + Â Â Â /* Non ABI */
> + Â Â Â PERF_X86_64_REG_MAX,
> + Â Â Â PERF_REG_IP = PERF_X86_64_REG_RIP,
> + Â Â Â PERF_REG_SP = PERF_X86_64_REG_RSP,
> +};
> +
> +#ifdef __KERNEL__
> +
> +#define PERF_X86_64_REG_RESERVED (~((1ULL << PERF_X86_64_REG_MAX) - 1ULL))
> +
> +static inline u64 perf_reg_version(void)
> +{
> + Â Â Â return PERF_REGS_VERSION_X86_64;
> +}
> +
> +static inline int perf_reg_validate(u64 mask)
> +{
> + Â Â Â if (mask & PERF_X86_64_REG_RESERVED)
> + Â Â Â Â Â Â Â return -EINVAL;
> +
> + Â Â Â return 0;
> +}
> +
> +static inline u64 perf_reg_value(struct pt_regs *regs, int idx)
> +{
> + Â Â Â switch (idx) {
> + Â Â Â case PERF_X86_64_REG_RAX:
> + Â Â Â Â Â Â Â return regs->ax;
> + Â Â Â case PERF_X86_64_REG_RBX:
> + Â Â Â Â Â Â Â return regs->bx;
> + Â Â Â case PERF_X86_64_REG_RCX:
> + Â Â Â Â Â Â Â return regs->cx;
> + Â Â Â case PERF_X86_64_REG_RDX:
> + Â Â Â Â Â Â Â return regs->dx;
> + Â Â Â case PERF_X86_64_REG_RSI:
> + Â Â Â Â Â Â Â return regs->si;
> + Â Â Â case PERF_X86_64_REG_RDI:
> + Â Â Â Â Â Â Â return regs->di;
> + Â Â Â case PERF_X86_64_REG_R8:
> + Â Â Â Â Â Â Â return regs->r8;
> + Â Â Â case PERF_X86_64_REG_R9:
> + Â Â Â Â Â Â Â return regs->r9;
> + Â Â Â case PERF_X86_64_REG_R10:
> + Â Â Â Â Â Â Â return regs->r10;
> + Â Â Â case PERF_X86_64_REG_R11:
> + Â Â Â Â Â Â Â return regs->r11;
> + Â Â Â case PERF_X86_64_REG_R12:
> + Â Â Â Â Â Â Â return regs->r12;
> + Â Â Â case PERF_X86_64_REG_R13:
> + Â Â Â Â Â Â Â return regs->r13;
> + Â Â Â case PERF_X86_64_REG_R14:
> + Â Â Â Â Â Â Â return regs->r14;
> + Â Â Â case PERF_X86_64_REG_R15:
> + Â Â Â Â Â Â Â return regs->r15;
> + Â Â Â case PERF_X86_64_REG_RBP:
> + Â Â Â Â Â Â Â return regs->bp;
> + Â Â Â case PERF_X86_64_REG_RSP:
> + Â Â Â Â Â Â Â return regs->sp;
> + Â Â Â case PERF_X86_64_REG_RIP:
> + Â Â Â Â Â Â Â return regs->ip;
> + Â Â Â case PERF_X86_64_REG_FLAGS:
> + Â Â Â Â Â Â Â return regs->flags;
> + Â Â Â case PERF_X86_64_REG_CS:
> + Â Â Â Â Â Â Â return regs->cs;
> + Â Â Â case PERF_X86_64_REG_SS:
> + Â Â Â Â Â Â Â return regs->ss;
> + Â Â Â }
> +
> + Â Â Â return 0;
> +}
> +
> +#endif /* __KERNEL__ */
> +
> +#endif /* _ASM_X86_PERF_REGS_64_H */
> diff --git a/include/asm-generic/perf_regs.h b/include/asm-generic/perf_regs.h
> new file mode 100644
> index 0000000..f616096
> --- /dev/null
> +++ b/include/asm-generic/perf_regs.h
> @@ -0,0 +1,23 @@
> +#ifndef __ASM_GENERIC_PERF_REGS_H
> +#define __ASM_GENERIC_PERF_REGS_H
> +
> +enum {
> + Â Â Â PERF_REGS_VERSION_NONE = 0UL,
> +};
> +
> +static inline int perf_reg_value(struct pt_regs *regs, int idx)
> +{
> + Â Â Â return 0;
> +}
> +
> +static inline int perf_reg_version(void)
> +{
> + Â Â Â return PERF_REGS_VERSION_NONE;
> +}
> +
> +static inline int perf_reg_validate(u64 mask)
> +{
> + Â Â Â return mask ? -ENOSYS : 0;
> +}
> +
> +#endif /* __ASM_GENERIC_PERF_REGS_H */
> --
> 1.7.7.6
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/