0001
0002 #include <linux/errno.h>
0003 #include <linux/kernel.h>
0004 #include <linux/sched.h>
0005 #include <linux/sched/task_stack.h>
0006 #include <linux/perf_event.h>
0007 #include <linux/bug.h>
0008 #include <linux/stddef.h>
0009 #include <asm/perf_regs.h>
0010 #include <asm/ptrace.h>
0011
0012 #ifdef CONFIG_X86_32
0013 #define PERF_REG_X86_MAX PERF_REG_X86_32_MAX
0014 #else
0015 #define PERF_REG_X86_MAX PERF_REG_X86_64_MAX
0016 #endif
0017
0018 #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
0019
0020 static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = {
0021 PT_REGS_OFFSET(PERF_REG_X86_AX, ax),
0022 PT_REGS_OFFSET(PERF_REG_X86_BX, bx),
0023 PT_REGS_OFFSET(PERF_REG_X86_CX, cx),
0024 PT_REGS_OFFSET(PERF_REG_X86_DX, dx),
0025 PT_REGS_OFFSET(PERF_REG_X86_SI, si),
0026 PT_REGS_OFFSET(PERF_REG_X86_DI, di),
0027 PT_REGS_OFFSET(PERF_REG_X86_BP, bp),
0028 PT_REGS_OFFSET(PERF_REG_X86_SP, sp),
0029 PT_REGS_OFFSET(PERF_REG_X86_IP, ip),
0030 PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags),
0031 PT_REGS_OFFSET(PERF_REG_X86_CS, cs),
0032 PT_REGS_OFFSET(PERF_REG_X86_SS, ss),
0033 #ifdef CONFIG_X86_32
0034 PT_REGS_OFFSET(PERF_REG_X86_DS, ds),
0035 PT_REGS_OFFSET(PERF_REG_X86_ES, es),
0036 PT_REGS_OFFSET(PERF_REG_X86_FS, fs),
0037 PT_REGS_OFFSET(PERF_REG_X86_GS, gs),
0038 #else
0039
0040
0041
0042
0043 (unsigned int) -1,
0044 (unsigned int) -1,
0045 (unsigned int) -1,
0046 (unsigned int) -1,
0047 #endif
0048 #ifdef CONFIG_X86_64
0049 PT_REGS_OFFSET(PERF_REG_X86_R8, r8),
0050 PT_REGS_OFFSET(PERF_REG_X86_R9, r9),
0051 PT_REGS_OFFSET(PERF_REG_X86_R10, r10),
0052 PT_REGS_OFFSET(PERF_REG_X86_R11, r11),
0053 PT_REGS_OFFSET(PERF_REG_X86_R12, r12),
0054 PT_REGS_OFFSET(PERF_REG_X86_R13, r13),
0055 PT_REGS_OFFSET(PERF_REG_X86_R14, r14),
0056 PT_REGS_OFFSET(PERF_REG_X86_R15, r15),
0057 #endif
0058 };
0059
0060 u64 perf_reg_value(struct pt_regs *regs, int idx)
0061 {
0062 struct x86_perf_regs *perf_regs;
0063
0064 if (idx >= PERF_REG_X86_XMM0 && idx < PERF_REG_X86_XMM_MAX) {
0065 perf_regs = container_of(regs, struct x86_perf_regs, regs);
0066 if (!perf_regs->xmm_regs)
0067 return 0;
0068 return perf_regs->xmm_regs[idx - PERF_REG_X86_XMM0];
0069 }
0070
0071 if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset)))
0072 return 0;
0073
0074 return regs_get_register(regs, pt_regs_offset[idx]);
0075 }
0076
0077 #define PERF_REG_X86_RESERVED (((1ULL << PERF_REG_X86_XMM0) - 1) & \
0078 ~((1ULL << PERF_REG_X86_MAX) - 1))
0079
0080 #ifdef CONFIG_X86_32
0081 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_R8) | \
0082 (1ULL << PERF_REG_X86_R9) | \
0083 (1ULL << PERF_REG_X86_R10) | \
0084 (1ULL << PERF_REG_X86_R11) | \
0085 (1ULL << PERF_REG_X86_R12) | \
0086 (1ULL << PERF_REG_X86_R13) | \
0087 (1ULL << PERF_REG_X86_R14) | \
0088 (1ULL << PERF_REG_X86_R15))
0089
0090 int perf_reg_validate(u64 mask)
0091 {
0092 if (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)))
0093 return -EINVAL;
0094
0095 return 0;
0096 }
0097
0098 u64 perf_reg_abi(struct task_struct *task)
0099 {
0100 return PERF_SAMPLE_REGS_ABI_32;
0101 }
0102
0103 void perf_get_regs_user(struct perf_regs *regs_user,
0104 struct pt_regs *regs)
0105 {
0106 regs_user->regs = task_pt_regs(current);
0107 regs_user->abi = perf_reg_abi(current);
0108 }
0109 #else
0110 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
0111 (1ULL << PERF_REG_X86_ES) | \
0112 (1ULL << PERF_REG_X86_FS) | \
0113 (1ULL << PERF_REG_X86_GS))
0114
0115 int perf_reg_validate(u64 mask)
0116 {
0117 if (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)))
0118 return -EINVAL;
0119
0120 return 0;
0121 }
0122
0123 u64 perf_reg_abi(struct task_struct *task)
0124 {
0125 if (!user_64bit_mode(task_pt_regs(task)))
0126 return PERF_SAMPLE_REGS_ABI_32;
0127 else
0128 return PERF_SAMPLE_REGS_ABI_64;
0129 }
0130
0131 static DEFINE_PER_CPU(struct pt_regs, nmi_user_regs);
0132
0133 void perf_get_regs_user(struct perf_regs *regs_user,
0134 struct pt_regs *regs)
0135 {
0136 struct pt_regs *regs_user_copy = this_cpu_ptr(&nmi_user_regs);
0137 struct pt_regs *user_regs = task_pt_regs(current);
0138
0139 if (!in_nmi()) {
0140 regs_user->regs = user_regs;
0141 regs_user->abi = perf_reg_abi(current);
0142 return;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151 if (regs->sp > (unsigned long)&user_regs->r11 &&
0152 regs->sp <= (unsigned long)(user_regs + 1)) {
0153 regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
0154 regs_user->regs = NULL;
0155 return;
0156 }
0157
0158
0159
0160
0161
0162 regs_user_copy->ip = user_regs->ip;
0163 regs_user_copy->ax = user_regs->ax;
0164 regs_user_copy->cx = user_regs->cx;
0165 regs_user_copy->dx = user_regs->dx;
0166 regs_user_copy->si = user_regs->si;
0167 regs_user_copy->di = user_regs->di;
0168 regs_user_copy->r8 = user_regs->r8;
0169 regs_user_copy->r9 = user_regs->r9;
0170 regs_user_copy->r10 = user_regs->r10;
0171 regs_user_copy->r11 = user_regs->r11;
0172 regs_user_copy->orig_ax = user_regs->orig_ax;
0173 regs_user_copy->flags = user_regs->flags;
0174 regs_user_copy->sp = user_regs->sp;
0175 regs_user_copy->cs = user_regs->cs;
0176 regs_user_copy->ss = user_regs->ss;
0177
0178
0179
0180
0181
0182
0183 regs_user_copy->bp = user_regs->bp;
0184
0185 regs_user_copy->bx = -1;
0186 regs_user_copy->r12 = -1;
0187 regs_user_copy->r13 = -1;
0188 regs_user_copy->r14 = -1;
0189 regs_user_copy->r15 = -1;
0190
0191
0192
0193
0194
0195
0196
0197 regs_user->abi = user_64bit_mode(user_regs) ?
0198 PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32;
0199
0200 regs_user->regs = regs_user_copy;
0201 }
0202 #endif