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