1 // SPDX-License-Identifier: GPL-2.0 2 #include <elf.h> 3 #include <errno.h> 4 #include <string.h> 5 #include "dwarf-regs.h" 6 #include "perf_regs.h" 7 #include "util/sample.h" 8 #include "debug.h" 9 10 int perf_sdt_arg_parse_op(uint16_t e_machine, char *old_op, char **new_op) 11 { 12 int ret = SDT_ARG_SKIP; 13 14 switch (e_machine) { 15 case EM_AARCH64: 16 ret = __perf_sdt_arg_parse_op_arm64(old_op, new_op); 17 break; 18 case EM_PPC: 19 case EM_PPC64: 20 ret = __perf_sdt_arg_parse_op_powerpc(old_op, new_op); 21 break; 22 case EM_386: 23 case EM_X86_64: 24 ret = __perf_sdt_arg_parse_op_x86(old_op, new_op); 25 break; 26 case EM_S390: 27 ret = __perf_sdt_arg_parse_op_s390(old_op, new_op); 28 break; 29 default: 30 pr_debug("Unknown ELF machine %d, standard arguments parse will be skipped.\n", 31 e_machine); 32 break; 33 } 34 35 return ret; 36 } 37 38 uint64_t perf_intr_reg_mask(uint16_t e_machine) 39 { 40 uint64_t mask = 0; 41 42 switch (e_machine) { 43 case EM_ARM: 44 mask = __perf_reg_mask_arm(/*intr=*/true); 45 break; 46 case EM_AARCH64: 47 mask = __perf_reg_mask_arm64(/*intr=*/true); 48 break; 49 case EM_CSKY: 50 mask = __perf_reg_mask_csky(/*intr=*/true); 51 break; 52 case EM_LOONGARCH: 53 mask = __perf_reg_mask_loongarch(/*intr=*/true); 54 break; 55 case EM_MIPS: 56 mask = __perf_reg_mask_mips(/*intr=*/true); 57 break; 58 case EM_PPC: 59 case EM_PPC64: 60 mask = __perf_reg_mask_powerpc(/*intr=*/true); 61 break; 62 case EM_RISCV: 63 mask = __perf_reg_mask_riscv(/*intr=*/true); 64 break; 65 case EM_S390: 66 mask = __perf_reg_mask_s390(/*intr=*/true); 67 break; 68 case EM_386: 69 case EM_X86_64: 70 mask = __perf_reg_mask_x86(/*intr=*/true); 71 break; 72 default: 73 pr_debug("Unknown ELF machine %d, interrupt sampling register mask will be empty.\n", 74 e_machine); 75 break; 76 } 77 78 return mask; 79 } 80 81 uint64_t perf_user_reg_mask(uint16_t e_machine) 82 { 83 uint64_t mask = 0; 84 85 switch (e_machine) { 86 case EM_ARM: 87 mask = __perf_reg_mask_arm(/*intr=*/false); 88 break; 89 case EM_AARCH64: 90 mask = __perf_reg_mask_arm64(/*intr=*/false); 91 break; 92 case EM_CSKY: 93 mask = __perf_reg_mask_csky(/*intr=*/false); 94 break; 95 case EM_LOONGARCH: 96 mask = __perf_reg_mask_loongarch(/*intr=*/false); 97 break; 98 case EM_MIPS: 99 mask = __perf_reg_mask_mips(/*intr=*/false); 100 break; 101 case EM_PPC: 102 case EM_PPC64: 103 mask = __perf_reg_mask_powerpc(/*intr=*/false); 104 break; 105 case EM_RISCV: 106 mask = __perf_reg_mask_riscv(/*intr=*/false); 107 break; 108 case EM_S390: 109 mask = __perf_reg_mask_s390(/*intr=*/false); 110 break; 111 case EM_386: 112 case EM_X86_64: 113 mask = __perf_reg_mask_x86(/*intr=*/false); 114 break; 115 default: 116 pr_debug("Unknown ELF machine %d, user sampling register mask will be empty.\n", 117 e_machine); 118 break; 119 } 120 121 return mask; 122 } 123 124 const char *perf_reg_name(int id, uint16_t e_machine, uint32_t e_flags) 125 { 126 const char *reg_name = NULL; 127 128 switch (e_machine) { 129 case EM_ARM: 130 reg_name = __perf_reg_name_arm(id); 131 break; 132 case EM_AARCH64: 133 reg_name = __perf_reg_name_arm64(id); 134 break; 135 case EM_CSKY: 136 reg_name = __perf_reg_name_csky(id, e_flags); 137 break; 138 case EM_LOONGARCH: 139 reg_name = __perf_reg_name_loongarch(id); 140 break; 141 case EM_MIPS: 142 reg_name = __perf_reg_name_mips(id); 143 break; 144 case EM_PPC: 145 case EM_PPC64: 146 reg_name = __perf_reg_name_powerpc(id); 147 break; 148 case EM_RISCV: 149 reg_name = __perf_reg_name_riscv(id); 150 break; 151 case EM_S390: 152 reg_name = __perf_reg_name_s390(id); 153 break; 154 case EM_386: 155 case EM_X86_64: 156 reg_name = __perf_reg_name_x86(id); 157 break; 158 default: 159 break; 160 } 161 if (reg_name) 162 return reg_name; 163 164 pr_debug("Failed to find register %d for ELF machine type %u\n", id, e_machine); 165 return "unknown"; 166 } 167 168 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) 169 { 170 int i, idx = 0; 171 u64 mask = regs->mask; 172 173 if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE) 174 return -EINVAL; 175 176 if (regs->cache_mask & (1ULL << id)) 177 goto out; 178 179 if (!(mask & (1ULL << id))) 180 return -EINVAL; 181 182 for (i = 0; i < id; i++) { 183 if (mask & (1ULL << i)) 184 idx++; 185 } 186 187 regs->cache_mask |= (1ULL << id); 188 regs->cache_regs[id] = regs->regs[idx]; 189 190 out: 191 *valp = regs->cache_regs[id]; 192 return 0; 193 } 194 195 uint64_t perf_arch_reg_ip(uint16_t e_machine) 196 { 197 switch (e_machine) { 198 case EM_ARM: 199 return __perf_reg_ip_arm(); 200 case EM_AARCH64: 201 return __perf_reg_ip_arm64(); 202 case EM_CSKY: 203 return __perf_reg_ip_csky(); 204 case EM_LOONGARCH: 205 return __perf_reg_ip_loongarch(); 206 case EM_MIPS: 207 return __perf_reg_ip_mips(); 208 case EM_PPC: 209 case EM_PPC64: 210 return __perf_reg_ip_powerpc(); 211 case EM_RISCV: 212 return __perf_reg_ip_riscv(); 213 case EM_S390: 214 return __perf_reg_ip_s390(); 215 case EM_386: 216 case EM_X86_64: 217 return __perf_reg_ip_x86(); 218 default: 219 pr_err("Failed to find IP register for ELF machine type %u\n", e_machine); 220 return 0; 221 } 222 } 223 224 uint64_t perf_arch_reg_sp(uint16_t e_machine) 225 { 226 switch (e_machine) { 227 case EM_ARM: 228 return __perf_reg_sp_arm(); 229 case EM_AARCH64: 230 return __perf_reg_sp_arm64(); 231 case EM_CSKY: 232 return __perf_reg_sp_csky(); 233 case EM_LOONGARCH: 234 return __perf_reg_sp_loongarch(); 235 case EM_MIPS: 236 return __perf_reg_sp_mips(); 237 case EM_PPC: 238 case EM_PPC64: 239 return __perf_reg_sp_powerpc(); 240 case EM_RISCV: 241 return __perf_reg_sp_riscv(); 242 case EM_S390: 243 return __perf_reg_sp_s390(); 244 case EM_386: 245 case EM_X86_64: 246 return __perf_reg_sp_x86(); 247 default: 248 pr_err("Failed to find SP register for ELF machine type %u\n", e_machine); 249 return 0; 250 } 251 } 252