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