From nobody Sun May 10 09:54:15 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53BEBC433F5 for ; Mon, 9 May 2022 15:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238295AbiEIP2H (ORCPT ); Mon, 9 May 2022 11:28:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230354AbiEIP17 (ORCPT ); Mon, 9 May 2022 11:27:59 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D30F2B031E for ; Mon, 9 May 2022 08:24:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1652109845; x=1683645845; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NoOuv2sVQKVnkCazGHVLdKtPkXcHV8vFl+UvJJbw3v4=; b=Ojo+jM462I9uHxct8Qb5TTgK4o4qVdbZMExgE4fRsRsKTAR+sUaEFlHq zphi/q1+Nq9FKPciaRYlsPvvAwaAJemWs5uXRDvJl42LTTk5XgrFb4fdw 2L2A+EULTH4vFLsDDtYgg6rZYLx89wvq9KtE5KOndFFBMfwmx+uIFyZxu mLeQVLfTy3FqvV4WQdPwSV8TrMY9C91B/a6dkqTytTrDmPl7ntE9art4N WzfH3rhgduG4Gy7XR815si9uvPvxqO7xZOyeL7vSDX8TQhkqsqYCCv66N uPdB/u9dcCaco97p9XqkZ09mKknNpNx6IkIFHJMYLkXtFFT8LBbFo00+7 Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10342"; a="294306856" X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="294306856" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 May 2022 08:24:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="592705298" Received: from ahunter-desktop.fi.intel.com ([10.237.72.92]) by orsmga008.jf.intel.com with ESMTP; 09 May 2022 08:24:03 -0700 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , linux-kernel@vger.kernel.org Subject: [PATCH 1/3] perf intel-pt: Add support for emulated ptwrite Date: Mon, 9 May 2022 18:23:58 +0300 Message-Id: <20220509152400.376613-2-adrian.hunter@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220509152400.376613-1-adrian.hunter@intel.com> References: <20220509152400.376613-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" ptwrite is an Intel x86 instruction that writes arbitrary values into an Intel PT trace. It is not supported on all hardware, so provide an alternative that makes use of TNT packets to convey the payload data. TNT packets encode Taken/Not-taken conditional branch information, so taking branches based on the payload value will encode the value into the TNT packet. Refer to the changes to the documentation file perf-intel-pt.txt in this patch for an example. Signed-off-by: Adrian Hunter --- tools/perf/Documentation/perf-intel-pt.txt | 88 +++++++++++++++++ .../util/intel-pt-decoder/intel-pt-decoder.c | 99 ++++++++++++++++++- .../util/intel-pt-decoder/intel-pt-decoder.h | 1 + .../intel-pt-decoder/intel-pt-insn-decoder.c | 1 + .../intel-pt-decoder/intel-pt-insn-decoder.h | 1 + tools/perf/util/intel-pt.c | 37 ++++++- 6 files changed, 224 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-intel-pt.txt b/tools/perf/Docume= ntation/perf-intel-pt.txt index 92532d0d3618..8acd704e8a39 100644 --- a/tools/perf/Documentation/perf-intel-pt.txt +++ b/tools/perf/Documentation/perf-intel-pt.txt @@ -468,6 +468,8 @@ ptw Enable PTWRITE packets which are produced when a p= twrite instruction which contains "1" if the feature is supported and "0" otherwise. =20 + As an alternative, refer to "Emulated PTWRITE" further below. + fup_on_ptw Enable a FUP packet to follow the PTWRITE packet. The FUP pack= et provides the address of the ptwrite instruction. In the absence of fup_on_ptw, the decoder will use the address of the previous branch @@ -1471,6 +1473,92 @@ In that case the --itrace q option is forced because= walking executable code to reconstruct the control flow is not possible. =20 =20 +Emulated PTWRITE +---------------- + +Later perf tools support a method to emulate the ptwrite instruction, which +can be useful if hardware does not support the ptwrite instruction. + +Instead of using the ptwrite instruction, a function is used which produces +a trace that encodes the payload data into TNT packets. Here is an example +of the function: + + #include + + void perf_emulate_ptwrite(uint64_t x) + __attribute__((externally_visible, noipa, no_instrument_function, naked)); + + #define PERF_EMULATE_PTWRITE_8_BITS \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" \ + "1: shl %rax\n" \ + " jc 1f\n" + + /* Undefined instruction */ + #define PERF_EMULATE_PTWRITE_UD2 ".byte 0x0f, 0x0b\n" + + #define PERF_EMULATE_PTWRITE_MAGIC PERF_EMULATE_PTWRITE_UD2 ".asci= i \"perf,ptwrite \"\n" + + void perf_emulate_ptwrite(uint64_t x __attribute__ ((__unused__))) + { + /* Assumes SysV ABI : x passed in rdi */ + __asm__ volatile ( + "jmp 1f\n" + PERF_EMULATE_PTWRITE_MAGIC + "1: mov %rdi, %rax\n" + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + PERF_EMULATE_PTWRITE_8_BITS + "1: ret\n" + ); + } + +For example, a test program with the function above: + + #include + #include + #include + + #include "perf_emulate_ptwrite.h" + + int main(int argc, char *argv[]) + { + uint64_t x =3D 0; + + if (argc > 1) + x =3D strtoull(argv[1], NULL, 0); + perf_emulate_ptwrite(x); + return 0; + } + +Can be compiled and traced: + + $ gcc -Wall -Wextra -O3 -g -o eg_ptw eg_ptw.c + $ perf record -e intel_pt//u ./eg_ptw 0x1234567890abcdef + [ perf record: Woken up 1 times to write data ] + [ perf record: Captured and wrote 0.017 MB perf.data ] + $ perf script --itrace=3Dew + eg_ptw 19875 [007] 8061.235912: ptwrite: IP: 0 payload: 0= x1234567890abcdef 55701249a196 perf_emulate_ptwrite+0x16 (/home/user/e= g_ptw) + $ + + EXAMPLE ------- =20 diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/pe= rf/util/intel-pt-decoder/intel-pt-decoder.c index e1d8f7504cbe..0ac860c8dd2b 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -137,6 +137,7 @@ struct intel_pt_decoder { bool in_psb; bool hop; bool leap; + bool emulated_ptwrite; bool vm_time_correlation; bool vm_tm_corr_dry_run; bool vm_tm_corr_reliable; @@ -481,6 +482,8 @@ static int intel_pt_ext_err(int code) return INTEL_PT_ERR_LOST; case -ELOOP: return INTEL_PT_ERR_NELOOP; + case -ECONNRESET: + return INTEL_PT_ERR_EPTW; default: return INTEL_PT_ERR_UNK; } @@ -497,6 +500,7 @@ static const char *intel_pt_err_msgs[] =3D { [INTEL_PT_ERR_LOST] =3D "Lost trace data", [INTEL_PT_ERR_UNK] =3D "Unknown error!", [INTEL_PT_ERR_NELOOP] =3D "Never-ending loop (refer perf config intel-pt.= max-loops)", + [INTEL_PT_ERR_EPTW] =3D "Broken emulated ptwrite", }; =20 int intel_pt__strerror(int code, char *buf, size_t buflen) @@ -1535,17 +1539,108 @@ static int intel_pt_walk_tip(struct intel_pt_decod= er *decoder) return intel_pt_bug(decoder); } =20 +struct eptw_data { + int bit_countdown; + uint64_t payload; +}; + +static int intel_pt_eptw_lookahead_cb(struct intel_pt_pkt_info *pkt_info) +{ + struct eptw_data *data =3D pkt_info->data; + int nr_bits; + + switch (pkt_info->packet.type) { + case INTEL_PT_PAD: + case INTEL_PT_MNT: + case INTEL_PT_MODE_EXEC: + case INTEL_PT_MODE_TSX: + case INTEL_PT_MTC: + case INTEL_PT_FUP: + case INTEL_PT_CYC: + case INTEL_PT_CBR: + case INTEL_PT_TSC: + case INTEL_PT_TMA: + case INTEL_PT_PIP: + case INTEL_PT_VMCS: + case INTEL_PT_PSB: + case INTEL_PT_PSBEND: + case INTEL_PT_PTWRITE: + case INTEL_PT_PTWRITE_IP: + case INTEL_PT_EXSTOP: + case INTEL_PT_EXSTOP_IP: + case INTEL_PT_MWAIT: + case INTEL_PT_PWRE: + case INTEL_PT_PWRX: + case INTEL_PT_BBP: + case INTEL_PT_BIP: + case INTEL_PT_BEP: + case INTEL_PT_BEP_IP: + case INTEL_PT_CFE: + case INTEL_PT_CFE_IP: + case INTEL_PT_EVD: + break; + + case INTEL_PT_TNT: + nr_bits =3D data->bit_countdown; + if (nr_bits > pkt_info->packet.count) + nr_bits =3D pkt_info->packet.count; + data->payload <<=3D nr_bits; + data->payload |=3D pkt_info->packet.payload >> (64 - nr_bits); + data->bit_countdown -=3D nr_bits; + return !data->bit_countdown; + + case INTEL_PT_TIP_PGE: + case INTEL_PT_TIP_PGD: + case INTEL_PT_TIP: + case INTEL_PT_BAD: + case INTEL_PT_OVF: + case INTEL_PT_TRACESTOP: + default: + return 1; + } + + return 0; +} + +static int intel_pt_emulated_ptwrite(struct intel_pt_decoder *decoder) +{ + int n =3D 64 - decoder->tnt.count; + struct eptw_data data =3D { + .bit_countdown =3D n, + .payload =3D decoder->tnt.payload >> n, + }; + + decoder->emulated_ptwrite =3D false; + intel_pt_log("Emulated ptwrite detected\n"); + + intel_pt_pkt_lookahead(decoder, intel_pt_eptw_lookahead_cb, &data); + if (data.bit_countdown) + return -ECONNRESET; + + decoder->state.type =3D INTEL_PT_PTW; + decoder->state.from_ip =3D decoder->ip; + decoder->state.to_ip =3D 0; + decoder->state.ptw_payload =3D data.payload; + return 0; +} + static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder) { struct intel_pt_insn intel_pt_insn; int err; =20 while (1) { + if (decoder->emulated_ptwrite) + return intel_pt_emulated_ptwrite(decoder); err =3D intel_pt_walk_insn(decoder, &intel_pt_insn, 0); - if (err =3D=3D INTEL_PT_RETURN) + if (err =3D=3D INTEL_PT_RETURN) { + decoder->emulated_ptwrite =3D intel_pt_insn.emulated_ptwrite; return 0; - if (err) + } + if (err) { + decoder->emulated_ptwrite =3D false; return err; + } =20 if (intel_pt_insn.op =3D=3D INTEL_PT_OP_RET) { if (!decoder->return_compression) { diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/pe= rf/util/intel-pt-decoder/intel-pt-decoder.h index efb2cb3ae0ca..c773028df80e 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -58,6 +58,7 @@ enum { INTEL_PT_ERR_LOST, INTEL_PT_ERR_UNK, INTEL_PT_ERR_NELOOP, + INTEL_PT_ERR_EPTW, INTEL_PT_ERR_MAX, }; =20 diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/too= ls/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c index 9d5e65cec89b..1376077183f7 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c @@ -32,6 +32,7 @@ static void intel_pt_insn_decoder(struct insn *insn, int ext; =20 intel_pt_insn->rel =3D 0; + intel_pt_insn->emulated_ptwrite =3D false; =20 if (insn_is_avx(insn)) { intel_pt_insn->op =3D INTEL_PT_OP_OTHER; diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/too= ls/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h index c2861cfdd768..e3338b56a75f 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h @@ -37,6 +37,7 @@ enum intel_pt_insn_branch { struct intel_pt_insn { enum intel_pt_insn_op op; enum intel_pt_insn_branch branch; + bool emulated_ptwrite; int length; int32_t rel; unsigned char buf[INTEL_PT_INSN_BUF_SZ]; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index ec43d364d0de..c7e115fefe7d 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -530,6 +530,7 @@ struct intel_pt_cache_entry { u64 byte_cnt; enum intel_pt_insn_op op; enum intel_pt_insn_branch branch; + bool emulated_ptwrite; int length; int32_t rel; char insn[INTEL_PT_INSN_BUF_SZ]; @@ -616,6 +617,7 @@ static int intel_pt_cache_add(struct dso *dso, struct m= achine *machine, e->byte_cnt =3D byte_cnt; e->op =3D intel_pt_insn->op; e->branch =3D intel_pt_insn->branch; + e->emulated_ptwrite =3D intel_pt_insn->emulated_ptwrite; e->length =3D intel_pt_insn->length; e->rel =3D intel_pt_insn->rel; memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ); @@ -702,6 +704,28 @@ static int intel_pt_get_guest(struct intel_pt_queue *p= tq) return 0; } =20 +static inline bool intel_pt_jmp_16(struct intel_pt_insn *intel_pt_insn) +{ + return intel_pt_insn->rel =3D=3D 16 && intel_pt_insn->branch =3D=3D INTEL= _PT_BR_UNCONDITIONAL; +} + +#define PTWRITE_MAGIC "\x0f\x0bperf,ptwrite " +#define PTWRITE_MAGIC_LEN 16 + +static bool intel_pt_emulated_ptwrite(struct dso *dso, struct machine *mac= hine, u64 offset) +{ + unsigned char buf[PTWRITE_MAGIC_LEN]; + ssize_t len; + + len =3D dso__data_read_offset(dso, machine, offset, buf, PTWRITE_MAGIC_LE= N); + if (len =3D=3D PTWRITE_MAGIC_LEN && !memcmp(buf, PTWRITE_MAGIC, PTWRITE_M= AGIC_LEN)) { + intel_pt_log("Emulated ptwrite signature found\n"); + return true; + } + intel_pt_log("Emulated ptwrite signature not found\n"); + return false; +} + static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, uint64_t max_insn_cnt, @@ -764,6 +788,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn= *intel_pt_insn, *ip +=3D e->byte_cnt; intel_pt_insn->op =3D e->op; intel_pt_insn->branch =3D e->branch; + intel_pt_insn->emulated_ptwrite =3D e->emulated_ptwrite; intel_pt_insn->length =3D e->length; intel_pt_insn->rel =3D e->rel; memcpy(intel_pt_insn->buf, e->insn, @@ -795,8 +820,18 @@ static int intel_pt_walk_next_insn(struct intel_pt_ins= n *intel_pt_insn, =20 insn_cnt +=3D 1; =20 - if (intel_pt_insn->branch !=3D INTEL_PT_BR_NO_BRANCH) + if (intel_pt_insn->branch !=3D INTEL_PT_BR_NO_BRANCH) { + bool eptw; + u64 offs; + + if (!intel_pt_jmp_16(intel_pt_insn)) + goto out; + /* Check for emulated ptwrite */ + offs =3D offset + intel_pt_insn->length; + eptw =3D intel_pt_emulated_ptwrite(al.map->dso, machine, offs); + intel_pt_insn->emulated_ptwrite =3D eptw; goto out; + } =20 if (max_insn_cnt && insn_cnt >=3D max_insn_cnt) goto out_no_cache; --=20 2.25.1 From nobody Sun May 10 09:54:15 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36007C433F5 for ; Mon, 9 May 2022 15:24:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238282AbiEIP2L (ORCPT ); Mon, 9 May 2022 11:28:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238236AbiEIP2B (ORCPT ); Mon, 9 May 2022 11:28:01 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 263C12B031C for ; Mon, 9 May 2022 08:24:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1652109847; x=1683645847; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7BI3ZK+h+P3VwEMDxcAP7FNTp6syom8qcPR9b2opId4=; b=ghvLdJpK9RGV6otcmeaT4/b4QKCRxS0pP4eJA9cRkMJS8Sl+iQiOO6Fs p8kMFyrwgcyHJPFf0VPLykWYB4eRViCR4wwkresKZFb6gTqL3mdrCC0cr A3cfFxriqwh+Ksp3R6HGxhfkWWlyz7hqR8+hJ8R8uqhYFp0aWkWXdvhZc EWFbskUgQgFy88wlHzsAqlmvfD8U8DiHvt9FMGt/Mit0Zitt96oN1VIWt aEgFudMo2ZMmELQQ5CwmPIhZOosTW3cp8ly0aLGnGg3BeyoO01BccZFHU hoh+pwOgEd3uUb+geYa7gVs1V4h3x7OXINnUlo6YkVDTtahmwsQtKJ3vt g==; X-IronPort-AV: E=McAfee;i="6400,9594,10342"; a="294306864" X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="294306864" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 May 2022 08:24:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="592705398" Received: from ahunter-desktop.fi.intel.com ([10.237.72.92]) by orsmga008.jf.intel.com with ESMTP; 09 May 2022 08:24:05 -0700 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , linux-kernel@vger.kernel.org Subject: [PATCH 2/3] perf script: Print Intel ptwrite value as a string if it is ASCII Date: Mon, 9 May 2022 18:23:59 +0300 Message-Id: <20220509152400.376613-3-adrian.hunter@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220509152400.376613-1-adrian.hunter@intel.com> References: <20220509152400.376613-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" It can be convenient to put a string value into a ptwrite payload as a quick and easy way to identify what is being printed. To make that useful, if the Intel ptwrite payload value contains only printable ASCII characters padded with NULLs, then print it also as a string. Using the example program from the "Emulated PTWRITE" section of tools/perf/Documentation/perf-intel-pt.txt: $ echo -n "Hello" | od -t x8 0000000 0000006f6c6c6548 0000005 $ perf record -e intel_pt//u ./eg_ptw 0x0000006f6c6c6548 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.016 MB perf.data ] $ perf script --itrace=3Dew eg_ptw 35563 [005] 18256.087338: ptwrite: IP: 0 payload: 0x= 6f6c6c6548 Hello 55e764db5196 perf_emulate_ptwrite+0x16 (/home/user/eg= _ptw) $ Signed-off-by: Adrian Hunter --- tools/perf/builtin-script.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index cf5eab5431b4..ae6d216df438 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1742,16 +1742,44 @@ static int perf_sample__fprintf_pt_spacing(int len,= FILE *fp) return perf_sample__fprintf_spacing(len, 34, fp); } =20 +/* If a value contains only printable ASCII characters padded with NULLs */ +static bool ptw_is_prt(u64 val) +{ + char c; + u32 i; + + for (i =3D 0; i < sizeof(val); i++) { + c =3D ((char *)&val)[i]; + if (!c) + break; + if (!isprint(c) || !isascii(c)) + return false; + } + for (; i < sizeof(val); i++) { + c =3D ((char *)&val)[i]; + if (c) + return false; + } + return true; +} + static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, = FILE *fp) { struct perf_synth_intel_ptwrite *data =3D perf_sample__synth_ptr(sample); + char str[sizeof(u64) + 1] =3D ""; int len; + u64 val; =20 if (perf_sample__bad_synth_size(sample, *data)) return 0; =20 - len =3D fprintf(fp, " IP: %u payload: %#" PRIx64 " ", - data->ip, le64_to_cpu(data->payload)); + val =3D le64_to_cpu(data->payload); + if (ptw_is_prt(val)) { + memcpy(str, &val, sizeof(val)); + str[sizeof(val)] =3D 0; + } + len =3D fprintf(fp, " IP: %u payload: %#" PRIx64 " %s ", + data->ip, val, str); return len + perf_sample__fprintf_pt_spacing(len, fp); } =20 --=20 2.25.1 From nobody Sun May 10 09:54:15 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48CDAC433F5 for ; Mon, 9 May 2022 15:24:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238305AbiEIP2P (ORCPT ); Mon, 9 May 2022 11:28:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238229AbiEIP2D (ORCPT ); Mon, 9 May 2022 11:28:03 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E4802B09F1 for ; Mon, 9 May 2022 08:24:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1652109849; x=1683645849; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/sViUog6BCJi155DSkmrPcl4AzpSt9KMDE0A8R8Se/U=; b=Gq1Ad5V0ITZgAczgR9niGde8+Co/t1KejXfPDd56XcLiKEKj5/WjGk71 J3fLHMd7g7GoNUuRJtvjof59veCSkenw+2gH6RA58jSt7cuxm6i0GRNSR ZFqamInSprbD7apV24cGnxzi0+KFdQ1fhDlpdehle5X4iHsJK+I4Ff2K6 zxInLH2xsilzVpKegZSn9klpeQuWtybvTn1dTgh0AZotL+83Bdo3tBBBn xf/y5uwqW3uNTnDTe1SE9wvu4ZP+X/rVCxGYL2g0Hc0heuu1Ru0e6mC7a XzWejjet1oBkfJhBLwRP7J5Oo6cN6I4J8xhArPA5rIX0aJLjJ1CRwVtDt w==; X-IronPort-AV: E=McAfee;i="6400,9594,10342"; a="294306875" X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="294306875" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 May 2022 08:24:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,211,1647327600"; d="scan'208";a="592705512" Received: from ahunter-desktop.fi.intel.com ([10.237.72.92]) by orsmga008.jf.intel.com with ESMTP; 09 May 2022 08:24:07 -0700 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , linux-kernel@vger.kernel.org Subject: [PATCH 3/3] perf scripts python: intel-pt-events.py: Print ptwrite value as a string if it is ASCII Date: Mon, 9 May 2022 18:24:00 +0300 Message-Id: <20220509152400.376613-4-adrian.hunter@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220509152400.376613-1-adrian.hunter@intel.com> References: <20220509152400.376613-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" It can be convenient to put a string value into a ptwrite payload as a quick and easy way to identify what is being printed. To make that useful, if the Intel ptwrite payload value contains only printable ASCII characters padded with NULLs, then print it also as a string. Using the example program from the "Emulated PTWRITE" section of tools/perf/Documentation/perf-intel-pt.txt: $ echo -n "Hello" | od -t x8 0000000 0000006f6c6c6548 0000005 $ perf record -e intel_pt//u ./eg_ptw 0x0000006f6c6c6548 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.016 MB perf.data ] $ perf script --itrace=3Dew intel-pt-events.py Intel PT Branch Trace, Power Events, Event Trace and PTWRITE Switch In 38524/38524 [001] 24166.044995916 0/0 eg_ptw 38524/38524 [001] 24166.045380004 ptwrite jmp = IP: 0 payload: 0x6f6c6c6548 Hello 56532c7ce196 perf_emula= te_ptwrite+0x16 (/home/ahunter/git/work/eg_ptw) End Signed-off-by: Adrian Hunter --- tools/perf/scripts/python/intel-pt-events.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scri= pts/python/intel-pt-events.py index 973bd12b7b40..9b7746b89381 100644 --- a/tools/perf/scripts/python/intel-pt-events.py +++ b/tools/perf/scripts/python/intel-pt-events.py @@ -104,7 +104,13 @@ def print_ptwrite(raw_buf): flags =3D data[0] payload =3D data[1] exact_ip =3D flags & 1 - print("IP: %u payload: %#x" % (exact_ip, payload), end=3D' ') + try: + s =3D payload.to_bytes(8, "little").decode("ascii").rstrip("\x00") + if not s.isprintable(): + s =3D "" + except: + s =3D "" + print("IP: %u payload: %#x" % (exact_ip, payload), s, end=3D' ') =20 def print_cbr(raw_buf): data =3D struct.unpack_from("