Received: by 2002:a05:6a10:a852:0:0:0:0 with SMTP id d18csp67722pxy; Fri, 30 Apr 2021 00:06:10 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxHXZz8I+GWnsk8EOdI50JfabNUSsM9ztxo7lkZUxyq/OzxfGOry9oCOFhUoLwIawWWsb73 X-Received: by 2002:a63:f715:: with SMTP id x21mr3284828pgh.399.1619766370257; Fri, 30 Apr 2021 00:06:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1619766370; cv=none; d=google.com; s=arc-20160816; b=E5+rJ70aATEra8ZiTPgL2zf55ijHoBX1cA0UkmG5ygSw6RALkvGcGQEfO8hkM5Tiyn etr7NwFHmpWoPcnx7XB2GxtmDZMJkUQLMr+BZ/8LCY+QYgLfzHejZ47Nlh/yJNjhXcgV 1tN9vkhC0UwShaFy72LMGzlqPCCJMQZrrnMlcNVL5F3PfaEZl4t8s2E1BFyzl7PZroeC fzepT7i/7TsBuctPxwLNoypVYWXV12zM2GgttUDoDoJ5E8oY/D3qMf3Z9mPCS7WdxYQr nt7CMtGYk0RJcVctGfnNLU6J2fzzsZ2C53VB90trXI6fyDZMWW1U7ERV7DqsRDx3zQ5n xrpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:organization:references:in-reply-to:message-id :date:subject:cc:to:from:ironport-sdr:ironport-sdr; bh=e7rFSDDhh3wA5Kl76/dh/GuHhevbxCNuijo0yJw8dTQ=; b=mpV+xQeFgKMxyMcdUvw/mH01XUDiCuxU3m4tuJTc3CSNeDhfmkHAfFHHXt4dhBxUCS a7Wd0DBbBg1J13EWSvc+2TIgGiHKuKfN0mQyBRtMzr/C68DQJpSb6roTAkNYp8XzcISk oPWbbwIAyLE/fggoVgWEJC6o4PRgeYbRqoVGHRC8jGMC9oZrbJa8HUuWD37Z5dG3W9/R MfZEtumQvUyKv6aFMal0ZkoioY3gotb3Gy4VGWggujkvRGBFSLhubbthtw7xo/vSLP9Z VIMk85hVKzhVER4S/pfwCQaX8PgPUEFHFjfBtUFLdf3Ouqa+kWvXY2dNO4hM3yTjaH/5 /H/A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e2si2633149plo.6.2021.04.30.00.05.43; Fri, 30 Apr 2021 00:06:10 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229590AbhD3HED (ORCPT + 99 others); Fri, 30 Apr 2021 03:04:03 -0400 Received: from mga09.intel.com ([134.134.136.24]:34039 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231134AbhD3HDy (ORCPT ); Fri, 30 Apr 2021 03:03:54 -0400 IronPort-SDR: Y3r978L0B33UKspL5n5H0CQeIXkROtmXBfDxTxC2TJbd1X8I6UpmCpyaKpI0STviF2rFX6nil1 VmzsZHTpffBw== X-IronPort-AV: E=McAfee;i="6200,9189,9969"; a="197312443" X-IronPort-AV: E=Sophos;i="5.82,260,1613462400"; d="scan'208";a="197312443" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Apr 2021 00:03:06 -0700 IronPort-SDR: NZMuRXPW31nJnLMZ7RUSx71y19mvDKKi+V91ZZPUvV+Xn1zCGlzPkofbFybNj9H1LaYa6clT34 ET+mFHBxjJDg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.82,260,1613462400"; d="scan'208";a="404492323" Received: from ahunter-desktop.fi.intel.com ([10.237.72.174]) by orsmga002.jf.intel.com with ESMTP; 30 Apr 2021 00:03:04 -0700 From: Adrian Hunter To: Arnaldo Carvalho de Melo , Jiri Olsa , Andi Kleen Cc: linux-kernel@vger.kernel.org Subject: [PATCH V2 08/12] perf intel-pt: Add a tree for VMCS information Date: Fri, 30 Apr 2021 10:03:05 +0300 Message-Id: <20210430070309.17624-9-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210430070309.17624-1-adrian.hunter@intel.com> References: <20210430070309.17624-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Even when VMX TSC Offset is not changing (during perf record), different virtual machines can have different TSC Offsets. There is a Virtual Machine Control Structure (VMCS) for each virtual CPU, the address of which is reported to Intel PT in the VMCS packet. We do not know which VMCS belongs to which virtual machine, so use a tree to keep track of VMCS information. Then the decoder will be able to use the current VMCS value to look up the current TSC Offset. Signed-off-by: Adrian Hunter --- .../util/intel-pt-decoder/intel-pt-decoder.c | 2 + .../util/intel-pt-decoder/intel-pt-decoder.h | 11 ++++ tools/perf/util/intel-pt.c | 66 +++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 8f916f90205e..c12e4a39b790 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -107,6 +107,7 @@ struct intel_pt_decoder { uint64_t max_insn_cnt, void *data); bool (*pgd_ip)(uint64_t ip, void *data); int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data); + struct intel_pt_vmcs_info *(*findnew_vmcs_info)(void *data, uint64_t vmcs); void *data; struct intel_pt_state state; const unsigned char *buf; @@ -258,6 +259,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) decoder->walk_insn = params->walk_insn; decoder->pgd_ip = params->pgd_ip; decoder->lookahead = params->lookahead; + decoder->findnew_vmcs_info = params->findnew_vmcs_info; decoder->data = params->data; decoder->return_compression = params->return_compression; decoder->branch_enable = params->branch_enable; diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index bebdb7d37b39..e6e782da45a4 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -11,6 +11,8 @@ #include #include +#include + #include "intel-pt-insn-decoder.h" #define INTEL_PT_IN_TX (1 << 0) @@ -199,6 +201,14 @@ struct intel_pt_blk_items { bool is_32_bit; }; +struct intel_pt_vmcs_info { + struct rb_node rb_node; + uint64_t vmcs; + uint64_t tsc_offset; + bool reliable; + bool error_printed; +}; + struct intel_pt_state { enum intel_pt_sample_type type; bool from_nr; @@ -244,6 +254,7 @@ struct intel_pt_params { uint64_t max_insn_cnt, void *data); bool (*pgd_ip)(uint64_t ip, void *data); int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data); + struct intel_pt_vmcs_info *(*findnew_vmcs_info)(void *data, uint64_t vmcs); void *data; bool return_compression; bool branch_enable; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index a494d47aa1ad..8f6df8eec9b8 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -133,6 +133,9 @@ struct intel_pt { struct ip_callchain *chain; struct branch_stack *br_stack; + + u64 dflt_tsc_offset; + struct rb_root vmcs_info; }; enum switch_state { @@ -271,6 +274,65 @@ static bool intel_pt_log_events(struct intel_pt *pt, u64 tm) return !n || !perf_time__ranges_skip_sample(range, n, tm); } +static struct intel_pt_vmcs_info *intel_pt_findnew_vmcs(struct rb_root *rb_root, + u64 vmcs, + u64 dflt_tsc_offset) +{ + struct rb_node **p = &rb_root->rb_node; + struct rb_node *parent = NULL; + struct intel_pt_vmcs_info *v; + + while (*p) { + parent = *p; + v = rb_entry(parent, struct intel_pt_vmcs_info, rb_node); + + if (v->vmcs == vmcs) + return v; + + if (vmcs < v->vmcs) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + v = zalloc(sizeof(*v)); + if (v) { + v->vmcs = vmcs; + v->tsc_offset = dflt_tsc_offset; + v->reliable = dflt_tsc_offset; + + rb_link_node(&v->rb_node, parent, p); + rb_insert_color(&v->rb_node, rb_root); + } + + return v; +} + +static struct intel_pt_vmcs_info *intel_pt_findnew_vmcs_info(void *data, uint64_t vmcs) +{ + struct intel_pt_queue *ptq = data; + struct intel_pt *pt = ptq->pt; + + if (!vmcs && !pt->dflt_tsc_offset) + return NULL; + + return intel_pt_findnew_vmcs(&pt->vmcs_info, vmcs, pt->dflt_tsc_offset); +} + +static void intel_pt_free_vmcs_info(struct intel_pt *pt) +{ + struct intel_pt_vmcs_info *v; + struct rb_node *n; + + n = rb_first(&pt->vmcs_info); + while (n) { + v = rb_entry(n, struct intel_pt_vmcs_info, rb_node); + n = rb_next(n); + rb_erase(&v->rb_node, &pt->vmcs_info); + free(v); + } +} + static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a, struct auxtrace_buffer *b) { @@ -1109,6 +1171,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, params.get_trace = intel_pt_get_trace; params.walk_insn = intel_pt_walk_next_insn; params.lookahead = intel_pt_lookahead; + params.findnew_vmcs_info = intel_pt_findnew_vmcs_info; params.data = ptq; params.return_compression = intel_pt_return_compression(pt); params.branch_enable = intel_pt_branch_enable(pt); @@ -2970,6 +3033,7 @@ static void intel_pt_free(struct perf_session *session) auxtrace_heap__free(&pt->heap); intel_pt_free_events(session); session->auxtrace = NULL; + intel_pt_free_vmcs_info(pt); thread__put(pt->unknown_thread); addr_filters__exit(&pt->filts); zfree(&pt->chain); @@ -3475,6 +3539,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event, if (!pt) return -ENOMEM; + pt->vmcs_info = RB_ROOT; + addr_filters__init(&pt->filts); err = perf_config(intel_pt_perf_config, pt); -- 2.25.1