Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf intel-pt: Add support for new branch instructions ERETS and ERETU

Intel Flexible Return and Event Delivery (FRED) adds instructions ERETS
(return to supervisor) and ERETU (return to user). Intel PT instruction
decoder needs to know about these instructions because they are
branch instructions. Similar to IRET instructions, when the decoder
encounters one of these instructions it will match it to a TIP (target
instruction pointer) packet that informs what the branch destination is.

The existing "x86 instruction decoder - new instructions" test can be
used to test the result e.g.

$ perf test -v ins |& grep eret
Decoded ok: f2 0f 01 ca erets
Decoded ok: f3 0f 01 ca eretu

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20230320183517.15099-2-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
052072f6 34f576c9

+24
+4
tools/perf/arch/x86/tests/insn-x86.c
··· 29 29 #include "insn-x86-dat-64.c" 30 30 {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"}, 31 31 {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"}, 32 + {{0xf2, 0x0f, 0x01, 0xca}, 4, 0, "erets", "indirect", "f2 0f 01 ca \terets"}, 33 + {{0xf3, 0x0f, 0x01, 0xca}, 4, 0, "eretu", "indirect", "f3 0f 01 ca \teretu"}, 32 34 {{0}, 0, 0, NULL, NULL, NULL}, 33 35 }; 34 36 ··· 51 49 {"syscall", INTEL_PT_OP_SYSCALL}, 52 50 {"sysret", INTEL_PT_OP_SYSRET}, 53 51 {"vmentry", INTEL_PT_OP_VMENTRY}, 52 + {"erets", INTEL_PT_OP_ERETS}, 53 + {"eretu", INTEL_PT_OP_ERETU}, 54 54 {NULL, 0}, 55 55 }; 56 56 struct val_data *val;
+18
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
··· 52 52 op = INTEL_PT_OP_VMENTRY; 53 53 branch = INTEL_PT_BR_INDIRECT; 54 54 break; 55 + case 0xca: 56 + switch (insn->prefixes.bytes[3]) { 57 + case 0xf2: /* erets */ 58 + op = INTEL_PT_OP_ERETS; 59 + branch = INTEL_PT_BR_INDIRECT; 60 + break; 61 + case 0xf3: /* eretu */ 62 + op = INTEL_PT_OP_ERETU; 63 + branch = INTEL_PT_BR_INDIRECT; 64 + break; 65 + default: 66 + break; 67 + } 68 + break; 55 69 default: 56 70 break; 57 71 } ··· 244 230 [INTEL_PT_OP_SYSCALL] = "Syscall", 245 231 [INTEL_PT_OP_SYSRET] = "Sysret", 246 232 [INTEL_PT_OP_VMENTRY] = "VMentry", 233 + [INTEL_PT_OP_ERETS] = "Erets", 234 + [INTEL_PT_OP_ERETU] = "Eretu", 247 235 }; 248 236 249 237 const char *intel_pt_insn_name(enum intel_pt_insn_op op) ··· 289 273 case INTEL_PT_OP_LOOP: 290 274 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL; 291 275 case INTEL_PT_OP_IRET: 276 + case INTEL_PT_OP_ERETS: 277 + case INTEL_PT_OP_ERETU: 292 278 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | 293 279 PERF_IP_FLAG_INTERRUPT; 294 280 case INTEL_PT_OP_INT:
+2
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
··· 25 25 INTEL_PT_OP_SYSCALL, 26 26 INTEL_PT_OP_SYSRET, 27 27 INTEL_PT_OP_VMENTRY, 28 + INTEL_PT_OP_ERETS, 29 + INTEL_PT_OP_ERETU, 28 30 }; 29 31 30 32 enum intel_pt_insn_branch {