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