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