Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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      * The pt_regs struct does not store
0041      * ds, es, fs, gs in 64 bit mode.
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 /* CONFIG_X86_64 */
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      * If we're in an NMI that interrupted task_pt_regs setup, then
0147      * we can't sample user regs at all.  This check isn't really
0148      * sufficient, though, as we could be in an NMI inside an interrupt
0149      * that happened during task_pt_regs setup.
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      * These registers are always saved on 64-bit syscall entry.
0160      * On 32-bit entry points, they are saved too except r8..r11.
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      * Store user space frame-pointer value on sample
0179      * to facilitate stack unwinding for cases when
0180      * user space executable code has such support
0181      * enabled at compile time:
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      * For this to be at all useful, we need a reasonable guess for
0192      * the ABI.  Be careful: we're in NMI context, and we're
0193      * considering current to be the current task, so we should
0194      * be careful not to look at any other percpu variables that might
0195      * change during context switches.
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 /* CONFIG_X86_32 */