^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2016 Anju T, IBM Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/perf_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) u64 PERF_REG_EXTENDED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define REG_RESERVED (~(PERF_REG_EXTENDED_MASK | PERF_REG_PMU_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) PT_REGS_OFFSET(PERF_REG_POWERPC_R1, gpr[1]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) PT_REGS_OFFSET(PERF_REG_POWERPC_R2, gpr[2]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) PT_REGS_OFFSET(PERF_REG_POWERPC_R3, gpr[3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) PT_REGS_OFFSET(PERF_REG_POWERPC_R4, gpr[4]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) PT_REGS_OFFSET(PERF_REG_POWERPC_R5, gpr[5]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) PT_REGS_OFFSET(PERF_REG_POWERPC_R6, gpr[6]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) PT_REGS_OFFSET(PERF_REG_POWERPC_R7, gpr[7]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) PT_REGS_OFFSET(PERF_REG_POWERPC_R8, gpr[8]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) PT_REGS_OFFSET(PERF_REG_POWERPC_R9, gpr[9]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) PT_REGS_OFFSET(PERF_REG_POWERPC_R10, gpr[10]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) PT_REGS_OFFSET(PERF_REG_POWERPC_R11, gpr[11]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) PT_REGS_OFFSET(PERF_REG_POWERPC_R12, gpr[12]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) PT_REGS_OFFSET(PERF_REG_POWERPC_R13, gpr[13]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) PT_REGS_OFFSET(PERF_REG_POWERPC_R14, gpr[14]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) PT_REGS_OFFSET(PERF_REG_POWERPC_R15, gpr[15]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) PT_REGS_OFFSET(PERF_REG_POWERPC_R16, gpr[16]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) PT_REGS_OFFSET(PERF_REG_POWERPC_R17, gpr[17]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) PT_REGS_OFFSET(PERF_REG_POWERPC_R18, gpr[18]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) PT_REGS_OFFSET(PERF_REG_POWERPC_R19, gpr[19]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) PT_REGS_OFFSET(PERF_REG_POWERPC_R20, gpr[20]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) PT_REGS_OFFSET(PERF_REG_POWERPC_R21, gpr[21]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) PT_REGS_OFFSET(PERF_REG_POWERPC_R22, gpr[22]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) PT_REGS_OFFSET(PERF_REG_POWERPC_R23, gpr[23]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) PT_REGS_OFFSET(PERF_REG_POWERPC_R24, gpr[24]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) PT_REGS_OFFSET(PERF_REG_POWERPC_R25, gpr[25]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) PT_REGS_OFFSET(PERF_REG_POWERPC_R26, gpr[26]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) PT_REGS_OFFSET(PERF_REG_POWERPC_R27, gpr[27]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) PT_REGS_OFFSET(PERF_REG_POWERPC_R28, gpr[28]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) PT_REGS_OFFSET(PERF_REG_POWERPC_R29, gpr[29]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) PT_REGS_OFFSET(PERF_REG_POWERPC_R30, gpr[30]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) PT_REGS_OFFSET(PERF_REG_POWERPC_R31, gpr[31]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) PT_REGS_OFFSET(PERF_REG_POWERPC_NIP, nip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) PT_REGS_OFFSET(PERF_REG_POWERPC_MSR, msr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) PT_REGS_OFFSET(PERF_REG_POWERPC_ORIG_R3, orig_gpr3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) PT_REGS_OFFSET(PERF_REG_POWERPC_CTR, ctr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) PT_REGS_OFFSET(PERF_REG_POWERPC_LINK, link),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) PT_REGS_OFFSET(PERF_REG_POWERPC_XER, xer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) PT_REGS_OFFSET(PERF_REG_POWERPC_CCR, ccr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, softe),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, mq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) PT_REGS_OFFSET(PERF_REG_POWERPC_TRAP, trap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Function to return the extended register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static u64 get_ext_regs_value(int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case PERF_REG_POWERPC_MMCR0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return mfspr(SPRN_MMCR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case PERF_REG_POWERPC_MMCR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return mfspr(SPRN_MMCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case PERF_REG_POWERPC_MMCR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return mfspr(SPRN_MMCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case PERF_REG_POWERPC_MMCR3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return mfspr(SPRN_MMCR3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case PERF_REG_POWERPC_SIER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return mfspr(SPRN_SIER2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case PERF_REG_POWERPC_SIER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return mfspr(SPRN_SIER3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) default: return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u64 perf_reg_value(struct pt_regs *regs, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u64 perf_reg_extended_max = PERF_REG_POWERPC_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (cpu_has_feature(CPU_FTR_ARCH_31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) perf_reg_extended_max = PERF_REG_MAX_ISA_31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) else if (cpu_has_feature(CPU_FTR_ARCH_300))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) perf_reg_extended_max = PERF_REG_MAX_ISA_300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (idx == PERF_REG_POWERPC_SIER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) IS_ENABLED(CONFIG_PPC32) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) !is_sier_available()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (idx == PERF_REG_POWERPC_MMCRA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) IS_ENABLED(CONFIG_PPC32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (idx >= PERF_REG_POWERPC_MAX && idx < perf_reg_extended_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return get_ext_regs_value(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * If the idx is referring to value beyond the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * supported registers, return 0 with a warning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (WARN_ON_ONCE(idx >= perf_reg_extended_max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return regs_get_register(regs, pt_regs_offset[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int perf_reg_validate(u64 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!mask || mask & REG_RESERVED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u64 perf_reg_abi(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!test_tsk_thread_flag(task, TIF_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return PERF_SAMPLE_REGS_ABI_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return PERF_SAMPLE_REGS_ABI_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) void perf_get_regs_user(struct perf_regs *regs_user,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) regs_user->regs = task_pt_regs(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) PERF_SAMPLE_REGS_ABI_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }