linux/arch/x86/kernel/perf_regs.c
<<
>>
Prefs
   1#include <linux/errno.h>
   2#include <linux/kernel.h>
   3#include <linux/sched.h>
   4#include <linux/perf_event.h>
   5#include <linux/bug.h>
   6#include <linux/stddef.h>
   7#include <asm/perf_regs.h>
   8#include <asm/ptrace.h>
   9
  10#ifdef CONFIG_X86_32
  11#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX
  12#else
  13#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX
  14#endif
  15
  16#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
  17
  18static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = {
  19        PT_REGS_OFFSET(PERF_REG_X86_AX, ax),
  20        PT_REGS_OFFSET(PERF_REG_X86_BX, bx),
  21        PT_REGS_OFFSET(PERF_REG_X86_CX, cx),
  22        PT_REGS_OFFSET(PERF_REG_X86_DX, dx),
  23        PT_REGS_OFFSET(PERF_REG_X86_SI, si),
  24        PT_REGS_OFFSET(PERF_REG_X86_DI, di),
  25        PT_REGS_OFFSET(PERF_REG_X86_BP, bp),
  26        PT_REGS_OFFSET(PERF_REG_X86_SP, sp),
  27        PT_REGS_OFFSET(PERF_REG_X86_IP, ip),
  28        PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags),
  29        PT_REGS_OFFSET(PERF_REG_X86_CS, cs),
  30        PT_REGS_OFFSET(PERF_REG_X86_SS, ss),
  31#ifdef CONFIG_X86_32
  32        PT_REGS_OFFSET(PERF_REG_X86_DS, ds),
  33        PT_REGS_OFFSET(PERF_REG_X86_ES, es),
  34        PT_REGS_OFFSET(PERF_REG_X86_FS, fs),
  35        PT_REGS_OFFSET(PERF_REG_X86_GS, gs),
  36#else
  37        /*
  38         * The pt_regs struct does not store
  39         * ds, es, fs, gs in 64 bit mode.
  40         */
  41        (unsigned int) -1,
  42        (unsigned int) -1,
  43        (unsigned int) -1,
  44        (unsigned int) -1,
  45#endif
  46#ifdef CONFIG_X86_64
  47        PT_REGS_OFFSET(PERF_REG_X86_R8, r8),
  48        PT_REGS_OFFSET(PERF_REG_X86_R9, r9),
  49        PT_REGS_OFFSET(PERF_REG_X86_R10, r10),
  50        PT_REGS_OFFSET(PERF_REG_X86_R11, r11),
  51        PT_REGS_OFFSET(PERF_REG_X86_R12, r12),
  52        PT_REGS_OFFSET(PERF_REG_X86_R13, r13),
  53        PT_REGS_OFFSET(PERF_REG_X86_R14, r14),
  54        PT_REGS_OFFSET(PERF_REG_X86_R15, r15),
  55#endif
  56};
  57
  58u64 perf_reg_value(struct pt_regs *regs, int idx)
  59{
  60        if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset)))
  61                return 0;
  62
  63        return regs_get_register(regs, pt_regs_offset[idx]);
  64}
  65
  66#define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL))
  67
  68#ifdef CONFIG_X86_32
  69int perf_reg_validate(u64 mask)
  70{
  71        if (!mask || mask & REG_RESERVED)
  72                return -EINVAL;
  73
  74        return 0;
  75}
  76
  77u64 perf_reg_abi(struct task_struct *task)
  78{
  79        return PERF_SAMPLE_REGS_ABI_32;
  80}
  81#else /* CONFIG_X86_64 */
  82#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
  83                       (1ULL << PERF_REG_X86_ES) | \
  84                       (1ULL << PERF_REG_X86_FS) | \
  85                       (1ULL << PERF_REG_X86_GS))
  86
  87int perf_reg_validate(u64 mask)
  88{
  89        if (!mask || mask & REG_RESERVED)
  90                return -EINVAL;
  91
  92        if (mask & REG_NOSUPPORT)
  93                return -EINVAL;
  94
  95        return 0;
  96}
  97
  98u64 perf_reg_abi(struct task_struct *task)
  99{
 100        if (test_tsk_thread_flag(task, TIF_IA32))
 101                return PERF_SAMPLE_REGS_ABI_32;
 102        else
 103                return PERF_SAMPLE_REGS_ABI_64;
 104}
 105#endif /* CONFIG_X86_32 */
 106