^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * intel_pt_insn_decoder.c: Intel Processor Trace support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2013-2014, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <endian.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <byteswap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "../../../arch/x86/include/asm/insn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "../../../arch/x86/lib/inat.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "../../../arch/x86/lib/insn.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "intel-pt-insn-decoder.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "dump-insn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #error Instruction buffer size too small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Based on branch_type() from arch/x86/events/intel/lbr.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static void intel_pt_insn_decoder(struct insn *insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct intel_pt_insn *intel_pt_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) enum intel_pt_insn_op op = INTEL_PT_OP_OTHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) intel_pt_insn->rel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (insn_is_avx(insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) intel_pt_insn->op = INTEL_PT_OP_OTHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) intel_pt_insn->length = insn->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) switch (insn->opcode.bytes[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) case 0xf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) switch (insn->opcode.bytes[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case 0x05: /* syscall */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case 0x34: /* sysenter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) op = INTEL_PT_OP_SYSCALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case 0x07: /* sysret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case 0x35: /* sysexit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) op = INTEL_PT_OP_SYSRET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case 0x80 ... 0x8f: /* jcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) op = INTEL_PT_OP_JCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) branch = INTEL_PT_BR_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case 0x70 ... 0x7f: /* jcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) op = INTEL_PT_OP_JCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) branch = INTEL_PT_BR_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case 0xc2: /* near ret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case 0xc3: /* near ret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case 0xca: /* far ret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case 0xcb: /* far ret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) op = INTEL_PT_OP_RET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case 0xcf: /* iret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) op = INTEL_PT_OP_IRET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case 0xcc ... 0xce: /* int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) op = INTEL_PT_OP_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case 0xe8: /* call near rel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) op = INTEL_PT_OP_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) branch = INTEL_PT_BR_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case 0x9a: /* call far absolute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) op = INTEL_PT_OP_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case 0xe0 ... 0xe2: /* loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) op = INTEL_PT_OP_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) branch = INTEL_PT_BR_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case 0xe3: /* jcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) op = INTEL_PT_OP_JCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) branch = INTEL_PT_BR_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case 0xe9: /* jmp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case 0xeb: /* jmp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) op = INTEL_PT_OP_JMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) branch = INTEL_PT_BR_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case 0xea: /* far jmp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) op = INTEL_PT_OP_JMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) case 0xff: /* call near absolute, call far absolute ind */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ext = (insn->modrm.bytes[0] >> 3) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) switch (ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case 2: /* near ind call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case 3: /* far ind call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) op = INTEL_PT_OP_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) op = INTEL_PT_OP_JMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) branch = INTEL_PT_BR_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) intel_pt_insn->op = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) intel_pt_insn->branch = branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) intel_pt_insn->length = insn->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (branch == INTEL_PT_BR_CONDITIONAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) branch == INTEL_PT_BR_UNCONDITIONAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #if __BYTE_ORDER == __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) switch (insn->immediate.nbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) intel_pt_insn->rel = insn->immediate.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) intel_pt_insn->rel =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bswap_16((short)insn->immediate.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) intel_pt_insn->rel = bswap_32(insn->immediate.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) intel_pt_insn->rel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) intel_pt_insn->rel = insn->immediate.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct intel_pt_insn *intel_pt_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) insn_init(&insn, buf, len, x86_64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) insn_get_length(&insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!insn_complete(&insn) || insn.length > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) intel_pt_insn_decoder(&insn, intel_pt_insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (insn.length < INTEL_PT_INSN_BUF_SZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memcpy(intel_pt_insn->buf, buf, insn.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int arch_is_branch(const unsigned char *buf, size_t len, int x86_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct intel_pt_insn in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (intel_pt_get_insn(buf, len, x86_64, &in) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return in.branch != INTEL_PT_BR_NO_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u8 *inbuf, int inlen, int *lenp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int n, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) insn_init(&insn, inbuf, inlen, x->is64bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) insn_get_length(&insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!insn_complete(&insn) || insn.length > inlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return "<bad>";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (lenp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *lenp = insn.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) left = sizeof(x->out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) n = snprintf(x->out, left, "insn: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) left -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i < insn.length; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) left -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return x->out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) const char *branch_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) [INTEL_PT_OP_OTHER] = "Other",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) [INTEL_PT_OP_CALL] = "Call",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) [INTEL_PT_OP_RET] = "Ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) [INTEL_PT_OP_JCC] = "Jcc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) [INTEL_PT_OP_JMP] = "Jmp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) [INTEL_PT_OP_LOOP] = "Loop",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) [INTEL_PT_OP_IRET] = "IRet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) [INTEL_PT_OP_INT] = "Int",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) [INTEL_PT_OP_SYSCALL] = "Syscall",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) [INTEL_PT_OP_SYSRET] = "Sysret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const char *intel_pt_insn_name(enum intel_pt_insn_op op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return branch_name[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) size_t buf_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) switch (intel_pt_insn->branch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case INTEL_PT_BR_CONDITIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case INTEL_PT_BR_UNCONDITIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return snprintf(buf, buf_len, "%s %s%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) intel_pt_insn_name(intel_pt_insn->op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) intel_pt_insn->rel > 0 ? "+" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) intel_pt_insn->rel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case INTEL_PT_BR_NO_BRANCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case INTEL_PT_BR_INDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return snprintf(buf, buf_len, "%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) intel_pt_insn_name(intel_pt_insn->op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int intel_pt_insn_type(enum intel_pt_insn_op op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case INTEL_PT_OP_OTHER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case INTEL_PT_OP_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case INTEL_PT_OP_RET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case INTEL_PT_OP_JCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case INTEL_PT_OP_JMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return PERF_IP_FLAG_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case INTEL_PT_OP_LOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case INTEL_PT_OP_IRET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) PERF_IP_FLAG_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case INTEL_PT_OP_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) PERF_IP_FLAG_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case INTEL_PT_OP_SYSCALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) PERF_IP_FLAG_SYSCALLRET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case INTEL_PT_OP_SYSRET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) PERF_IP_FLAG_SYSCALLRET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }