Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp5753130rwd; Wed, 24 May 2023 06:24:44 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7IbXLonUH/IdTX2UEryYRL7Sz28nEC4ZXIN5isHAlROAkVM5oLI1VmxBicrUTbj4zpdFph X-Received: by 2002:a17:90a:e557:b0:253:45ce:fad7 with SMTP id ei23-20020a17090ae55700b0025345cefad7mr16846431pjb.31.1684934684293; Wed, 24 May 2023 06:24:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684934684; cv=none; d=google.com; s=arc-20160816; b=xFL4Z5owlAiu/rFJ7x3+UvpZQcon2/akYIWzHnmjqvRvs1aBwrXV58GpLVN/dt4Gkc 6IrUKYHolMWiUVbQyq+Ynko3SjLv2zm6tmZlX7Za4y2diFEa1fMZnTBw8iFvGHr0bS8d NNir8C/6Wkh/AV2kS26OyqmAof/XsJeJy9rcCvZLaHarP7zhiT3k4tLWfbCaviWvnLcH St8nat95826QjMvrGpdWaL2xk2DJEy+ljAsjZ05uBbgNB/nCvLoNb6J9zqbpk2IyQSWo B/OJz/6sjzxcjVHi5bxnqqHL8TK0C36T7KDI7mwCkYvu+PoVq/wEiN6+RCuY+1Lvblth qLAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=WNRyT/yRgkabq6Hd4Yxi9BYcIFwkB2wfWw79KcPu358=; b=bBguzY4fYRp3h/KsFJ8VmcyL7ryw8KMBIy/acUPYkDZEEHLUtgH4JDeatR6PI6KECr bk+Lvo0IcgKLySSM2kAd4MGERiCBohH4tIc4Taw26NPLT0Qu0RjD4ctVTXJybHUER3vZ 0n/BWhxk8GgLbcA1D+uAhBsYxTNSy+JDgfg35e2NW6pzOUjhUkj+PqG7IehCcdXrFOwE QhQH+hW310U2K3dOD4g6GuwFki4zXoKp0EewKsXESdNC6r4FgXY00eClM69VI7HFhhR+ VkRyTXnnGmSjFMvavfkcF3RVAFmMMiPBqCp7DpSSGOry7Y/tanQUxmX5GmO0HkkMi9Yl xOjg== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gz21-20020a17090b0ed500b0024e140702efsi184151pjb.118.2023.05.24.06.24.29; Wed, 24 May 2023 06:24:44 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235166AbjEXNUf (ORCPT + 99 others); Wed, 24 May 2023 09:20:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232630AbjEXNUX (ORCPT ); Wed, 24 May 2023 09:20:23 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 38D1BA9; Wed, 24 May 2023 06:20:22 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0B54A1042; Wed, 24 May 2023 06:21:07 -0700 (PDT) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6204C3F840; Wed, 24 May 2023 06:20:19 -0700 (PDT) From: James Clark To: coresight@lists.linaro.org, denik@chromium.org Cc: James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Ian Rogers , Adrian Hunter , John Garry , Will Deacon , linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] perf cs-etm: Track exception level Date: Wed, 24 May 2023 14:19:57 +0100 Message-Id: <20230524131958.2139331-4-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230524131958.2139331-1-james.clark@arm.com> References: <20230524131958.2139331-1-james.clark@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE 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 Currently we assume all trace belongs to the host machine so when the decoder should be looking at the guest kernel maps it can crash because it looks at the host ones instead. Avoid one scenario (guest kernel running at EL1) by assigning the default guest machine to this trace. For userspace trace it's still not possible to determine guest vs host, but the PIDs should help in this case. Signed-off-by: James Clark --- .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 7 +- tools/perf/util/cs-etm.c | 64 ++++++++++++++----- tools/perf/util/cs-etm.h | 5 +- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index 82a27ab90c8b..ac227cd03eb0 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -573,12 +573,13 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, break; } + if (cs_etm__etmq_set_tid_el(etmq, tid, trace_chan_id, + elem->context.exception_level)) + return OCSD_RESP_FATAL_SYS_ERR; + if (tid == -1) return OCSD_RESP_CONT; - if (cs_etm__etmq_set_tid(etmq, tid, trace_chan_id)) - return OCSD_RESP_FATAL_SYS_ERR; - /* * A timestamp is generated after a PE_CONTEXT element so make sure * to rely on that coming one. diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index a997fe79d458..b9ba19327f26 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -14,7 +14,6 @@ #include #include -#include #include #include "auxtrace.h" @@ -87,6 +86,8 @@ struct cs_etm_traceid_queue { union perf_event *event_buf; struct thread *thread; struct thread *prev_thread; + ocsd_ex_level prev_el; + ocsd_ex_level el; struct branch_stack *last_branch; struct branch_stack *last_branch_rb; struct cs_etm_packet *prev_packet; @@ -479,6 +480,7 @@ static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq, queue = &etmq->etm->queues.queue_array[etmq->queue_nr]; tidq->trace_chan_id = trace_chan_id; + tidq->el = tidq->prev_el = ocsd_EL_unknown; tidq->thread = machine__findnew_thread(&etm->session->machines.host, -1, queue->tid); tidq->prev_thread = machine__idle_thread(&etm->session->machines.host); @@ -618,6 +620,7 @@ static void cs_etm__packet_swap(struct cs_etm_auxtrace *etm, tmp = tidq->packet; tidq->packet = tidq->prev_packet; tidq->prev_packet = tmp; + tidq->prev_el = tidq->el; thread__put(tidq->prev_thread); tidq->prev_thread = thread__get(tidq->thread); } @@ -879,11 +882,34 @@ static bool cs_etm__evsel_is_auxtrace(struct perf_session *session, return evsel->core.attr.type == aux->pmu_type; } -static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address) +static struct machine *cs_etm__get_machine(struct cs_etm_auxtrace *etm, + ocsd_ex_level el) { - struct machine *machine; + /* + * Not perfect, but assume anything in EL1 is the default guest, and + * everything else is the host. nHVE and pKVM may not work with this + * assumption. And distinguishing between guest and host userspaces + * isn't currently supported either. Neither is multiple guest support. + * All this does is reduce the likeliness of decode errors where we look + * into the host kernel maps when it should have been the guest maps. + */ + switch (el) { + case ocsd_EL1: + return machines__find_guest(&etm->session->machines, + DEFAULT_GUEST_KERNEL_ID); + case ocsd_EL3: + case ocsd_EL2: + case ocsd_EL0: + case ocsd_EL_unknown: + default: + return &etm->session->machines.host; + } +} - machine = &etmq->etm->session->machines.host; +static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address, + ocsd_ex_level el) +{ + struct machine *machine = cs_etm__get_machine(etmq->etm, el); if (address >= machine__kernel_start(machine)) { if (machine__is_host(machine)) @@ -893,10 +919,14 @@ static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address) } else { if (machine__is_host(machine)) return PERF_RECORD_MISC_USER; - else if (perf_guest) + else { + /* + * Can't really happen at the moment because + * cs_etm__get_machine() will always return + * machines.host for any non EL1 trace. + */ return PERF_RECORD_MISC_GUEST_USER; - else - return PERF_RECORD_MISC_HYPERVISOR; + } } } @@ -913,11 +943,12 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, if (!etmq) return 0; - cpumode = cs_etm__cpu_mode(etmq, address); tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id); if (!tidq) return 0; + cpumode = cs_etm__cpu_mode(etmq, address, tidq->el); + if (!thread__find_map(tidq->thread, cpumode, address, &al)) return 0; @@ -1296,9 +1327,10 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) } static void cs_etm__set_thread(struct cs_etm_auxtrace *etm, - struct cs_etm_traceid_queue *tidq, pid_t tid) + struct cs_etm_traceid_queue *tidq, pid_t tid, + ocsd_ex_level el) { - struct machine *machine = &etm->session->machines.host; + struct machine *machine = cs_etm__get_machine(etm, el); if (tid != -1) { thread__zput(tidq->thread); @@ -1308,10 +1340,12 @@ static void cs_etm__set_thread(struct cs_etm_auxtrace *etm, /* Couldn't find a known thread */ if (!tidq->thread) tidq->thread = machine__idle_thread(machine); + + tidq->el = el; } -int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq, - pid_t tid, u8 trace_chan_id) +int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid, u8 trace_chan_id, + ocsd_ex_level el) { struct cs_etm_traceid_queue *tidq; @@ -1319,7 +1353,7 @@ int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq, if (!tidq) return -EINVAL; - cs_etm__set_thread(etmq->etm, tidq, tid); + cs_etm__set_thread(etmq->etm, tidq, tid, el); return 0; } @@ -1389,7 +1423,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, struct perf_sample sample = {.ip = 0,}; event->sample.header.type = PERF_RECORD_SAMPLE; - event->sample.header.misc = cs_etm__cpu_mode(etmq, addr); + event->sample.header.misc = cs_etm__cpu_mode(etmq, addr, tidq->el); event->sample.header.size = sizeof(struct perf_event_header); /* Set time field based on etm auxtrace config. */ @@ -1448,7 +1482,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, ip = cs_etm__last_executed_instr(tidq->prev_packet); event->sample.header.type = PERF_RECORD_SAMPLE; - event->sample.header.misc = cs_etm__cpu_mode(etmq, ip); + event->sample.header.misc = cs_etm__cpu_mode(etmq, ip, tidq->prev_el); event->sample.header.size = sizeof(struct perf_event_header); /* Set time field based on etm auxtrace config. */ diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 70cac0375b34..88e9b25a8a9f 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -232,10 +232,11 @@ int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_event_attr *cs_etm_get_default_config(struct perf_pmu *pmu); #ifdef HAVE_CSTRACE_SUPPORT +#include int cs_etm__get_cpu(u8 trace_chan_id, int *cpu); int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt); -int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq, - pid_t tid, u8 trace_chan_id); +int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid, u8 trace_chan_id, + ocsd_ex_level el); bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq); void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq, u8 trace_chan_id); -- 2.34.1