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