From patchwork Fri Oct 14 17:09:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 2763 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp291052wrs; Fri, 14 Oct 2022 10:13:20 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6PJF0x01xApP/okojPeanwhFyl4lx9XPkfwQL4VQxJ+DECSJtO2d2xI9JJWFLBMGkQ28xP X-Received: by 2002:a17:907:2d06:b0:78d:50db:130e with SMTP id gs6-20020a1709072d0600b0078d50db130emr4326196ejc.371.1665767599726; Fri, 14 Oct 2022 10:13:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665767599; cv=none; d=google.com; s=arc-20160816; b=V7e0jPep/QUgvFaxNL6H+6l/jLI70qG9LJUWGbbA9Qy8/GSZk3wJhe9auJlTWGN6ed khG2dFxUZuiyJDYOTPIJukI+bbzEw3RfuJ5rKaGwBzDAtfXMjQib0j5RY4qvaDF7Stde +0jhTR06dO59ysVdgt11fnNE1s6igs4q+KKroOYg2k0YoeZsXaRbTjfI4lFJAN/kjDBx umfKrknArTSSohSqBa9ORDNvqmfcq2x9XYBtZX9/WIlzx+5jNrKAKW70fkE/Ylx6Qsa/ kK4M9PEFha0T+/QYdOPtrUPC9cSnHn5LbJJjvdiKCZYasZwQoJrbozD7WrwF0Hl+9mdG Q1jA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:organization :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=o53/4aNc+E13CXp4H20YRBY2z5ey25Hx9er/139oLaI=; b=ciuy7BBgqo2RZqgPAdjCIcxlaMhHucOtQbfDoUZgsIPm9C2Yb4U1gRxb3PPbdWh2U2 DQQhEhfR3TdAexKlO8BnWUmE05ImnjUqfkW6GYURYZi0z6fvv4nhmJbNNG1iy+WJdm6e LH7MUjfuDa5Hzvijjtj5VC1iSBfpx+2BXAkNhmMH/8xp9rOPaWpGAKFE/rnLcLoFniMs xk8CuokuqQN23zh/IQEISNizWqbbbvfbiMfnjIdJaFhUSJXMdD1+HTyG/5Y1Ecum6mqP vBu5ozQQUTzMom2OCdb2cnX+H3F/7BXNfqaHKyqLkMej+Ny+yoaHJ5K8rz+4e3kz1siZ W3/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=U0IlDhdy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gn41-20020a1709070d2900b0077cfdda438csi2991696ejc.35.2022.10.14.10.12.51; Fri, 14 Oct 2022 10:13:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=U0IlDhdy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231238AbiJNRKG (ORCPT + 99 others); Fri, 14 Oct 2022 13:10:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231235AbiJNRJ5 (ORCPT ); Fri, 14 Oct 2022 13:09:57 -0400 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 002361E730; Fri, 14 Oct 2022 10:09:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1665767386; x=1697303386; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BfjeSY7KNgsN+P4GwvYyJZrJWkkSdPm7/zXQBtNNFk4=; b=U0IlDhdyvZhbsV/LC4L/j1/BucB5//BxJRMKM2PN19++Qq8qdTMpVeIu T5THxKIz3dWGHEX5lpO7pfdELg/9wZc6jV/O195D5TXsAcWGPvXOLNFah aYaXzb1+ayIEW0iEafBaTEDBg+m5L9+PMUEA5pXJxNJDaIKRCzoRizWRR DjfErPmmxPgx4ghOMZ4Zd+t1btcBBqR6pc5zrLhG0irIkxvGOJ2AlBfw0 d3EBGQETrbfF1I+ZdrKIS/XZZHe7kwA09cff9abixoHQEqnfbascTY8B9 p1dphRA8jLZp11OgC7+iJrfqHyjLIrAVd46Z7U3Hl2ISsa5O8Ne1EfoIW w==; X-IronPort-AV: E=McAfee;i="6500,9779,10500"; a="303041997" X-IronPort-AV: E=Sophos;i="5.95,184,1661842800"; d="scan'208";a="303041997" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 10:09:43 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10500"; a="696377013" X-IronPort-AV: E=Sophos;i="5.95,184,1661842800"; d="scan'208";a="696377013" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.43.79]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 10:09:37 -0700 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH 5/7] perf test: test_intel_pt.sh: Add jitdump test Date: Fri, 14 Oct 2022 20:09:03 +0300 Message-Id: <20221014170905.64069-6-adrian.hunter@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221014170905.64069-1-adrian.hunter@intel.com> References: <20221014170905.64069-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 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1746683926630931945?= X-GMAIL-MSGID: =?utf-8?q?1746683926630931945?= Add a test for decoding self-modifying code using a jitdump file. The test creates a workload that uses self-modifying code and generates its own jitdump file. The result is processed with perf inject --jit and checked for decoding errors. Note the test will fail without patch "perf inject: Fix GEN_ELF_TEXT_OFFSET for jit" applied. Signed-off-by: Adrian Hunter Signed-off-by: Adrian Hunter --- tools/perf/tests/shell/test_intel_pt.sh | 162 ++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/tools/perf/tests/shell/test_intel_pt.sh b/tools/perf/tests/shell/test_intel_pt.sh index 79dde57b561d..e0bf75981b9c 100755 --- a/tools/perf/tests/shell/test_intel_pt.sh +++ b/tools/perf/tests/shell/test_intel_pt.sh @@ -22,6 +22,7 @@ outfile="${temp_dir}/test-out.txt" errfile="${temp_dir}/test-err.txt" workload="${temp_dir}/workload" awkscript="${temp_dir}/awkscript" +jitdump_workload="${temp_dir}/jitdump_workload" cleanup() { @@ -50,6 +51,13 @@ perf_record_no_decode() perf record -B -N --no-bpf-event "$@" } +# perf record for testing should not need BPF events +perf_record_no_bpf() +{ + # Options for no BPF events + perf record --no-bpf-event "$@" +} + have_workload=false cat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true #include @@ -269,6 +277,159 @@ test_per_thread() return 0 } +test_jitdump() +{ + echo "--- Test tracing self-modifying code that uses jitdump ---" + + script_path=$(realpath "$0") + script_dir=$(dirname "$script_path") + jitdump_incl_dir="${script_dir}/../../util" + jitdump_h="${jitdump_incl_dir}/jitdump.h" + + if [ ! -e "${jitdump_h}" ] ; then + echo "SKIP: Include file jitdump.h not found" + return 2 + fi + + if [ -z "${have_jitdump_workload}" ] ; then + have_jitdump_workload=false + # Create a workload that uses self-modifying code and generates its own jitdump file + cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + + #include "jitdump.h" + + #define CHK_BYTE 0x5a + + static inline uint64_t rdtsc(void) + { + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((uint64_t)high) << 32; + } + + static FILE *open_jitdump(void) + { + struct jitheader header = { + .magic = JITHEADER_MAGIC, + .version = JITHEADER_VERSION, + .total_size = sizeof(header), + .pid = getpid(), + .timestamp = rdtsc(), + .flags = JITDUMP_FLAGS_ARCH_TIMESTAMP, + }; + char filename[256]; + FILE *f; + void *m; + + snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); + f = fopen(filename, "w+"); + if (!f) + goto err; + /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ + m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); + if (m == MAP_FAILED) + goto err_close; + munmap(m, 4096); + if (fwrite(&header,sizeof(header),1,f) != 1) + goto err_close; + return f; + + err_close: + fclose(f); + err: + return NULL; + } + + static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx) + { + struct jr_code_load rec = { + .p.id = JIT_CODE_LOAD, + .p.total_size = sizeof(rec) + sz, + .p.timestamp = rdtsc(), + .pid = getpid(), + .tid = gettid(), + .vma = (unsigned long)addr, + .code_addr = (unsigned long)addr, + .code_size = sz, + .code_index = ++*idx, + }; + + if (fwrite(&rec,sizeof(rec),1,f) != 1 || + fwrite(dat, sz, 1, f) != 1) + return -1; + return 0; + } + + static void close_jitdump(FILE *f) + { + fclose(f); + } + + int main() + { + /* Get a memory page to store executable code */ + void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + /* Code to execute: mov CHK_BYTE, %eax ; ret */ + uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3}; + FILE *f = open_jitdump(); + uint64_t idx = 0; + int ret = 1; + + if (!f) + return 1; + /* Copy executable code to executable memory page */ + memcpy(addr, dat, sizeof(dat)); + /* Record it in the jitdump file */ + if (write_jitdump(f, addr, dat, sizeof(dat), &idx)) + goto out_close; + /* Call it */ + ret = ((int (*)(void))addr)() - CHK_BYTE; + out_close: + close_jitdump(f); + return ret; + } + _end_of_file_ + fi + + if ! $have_jitdump_workload ; then + echo "SKIP: No jitdump workload" + return 2 + fi + + # Change to temp_dir so jitdump collateral files go there + cd "${temp_dir}" + perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}" + perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit + decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l) + # Note that overflow and lost errors are suppressed for the error count + decode_err_cnt=$(perf script -i "${perfdatafile}" --itrace=e-o-l | grep -ci error) + cd - + # Should be thousands of branches + if [ "${decode_br_cnt}" -lt 1000 ] ; then + echo "Decode failed, only ${decode_br_cnt} branches" + return 1 + fi + # Should be no errors + if [ "${decode_err_cnt}" -ne 0 ] ; then + echo "Decode failed, ${decode_err_cnt} errors" + perf script -i "${perfdatafile}" --itrace=e-o-l + return 1 + fi + + echo OK + return 0 +} + count_result() { if [ "$1" -eq 2 ] ; then @@ -286,6 +447,7 @@ ret=0 test_system_wide_side_band || ret=$? ; count_result $ret ; ret=0 test_per_thread "" "" || ret=$? ; count_result $ret ; ret=0 test_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0 +test_jitdump || ret=$? ; count_result $ret ; ret=0 cleanup