Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp5535411pxb; Wed, 26 Jan 2022 14:24:13 -0800 (PST) X-Google-Smtp-Source: ABdhPJwDhh87d0CB1ewR0uyW0Jl1ts0GxyzamJMzvzh7z79PgCThjVTjClMQFQGESpx19HcYdzCz X-Received: by 2002:a17:907:97d0:: with SMTP id js16mr605896ejc.345.1643235853385; Wed, 26 Jan 2022 14:24:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643235853; cv=none; d=google.com; s=arc-20160816; b=EL5xDGdpGvjB+pp9hhD1+7X8wgQTL5d8AoI39gO9D8jQvsQvUBRzmtZaJYoOWZiHNT fncVQlqgd4GbVI4iOMAmaU4YKcGaDqpYK7mT7Qv6dhfJ4d4FNRoQGYAo0McJjSzEcK5o s8LyEyepd4p4CNsRpmT+NohGjJxVQgB6N8bevTpAil+/7dTJ5GTvAz2Grb/wMCcUGNj/ phAdo+ABJHIxmN4/u4GQK5y1QS10eXcZCEilWzOfPRGScQETVtkj2XnQvxjsCOyRfxzk aOPpEWUkMR1YT5+TKoDhYPWa2+DGNMbWIZthZGEvlMqEuaf0PriyaRO553FaRsKiAIVU XKRA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:content-language :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject; bh=J5oO17sWFzC1PUgHUVL7fU+5zgoCs2MPGawmptH2THI=; b=G7HDKvcjyj/W5G0b1qNeRk/WCYisx/a+Pb5f+Z5yVkgkRXYECnKwORXypPYo6NmKkj GEcJHixjlU6BMl4CY6rakqpmrtaJVFoBfx6bHrhzkC97ZAQyEkJ6xZ4VUXSs+OzYIlAd a4JOyCe+OWrmBWziVQzszH5z5GL1DBqSb2dznzxGi6KjwEmyxkERla/Y1s8J8r/RRszh En1C6ukpuGtC8xbkTFn6l0mZX2KpToPbw9P8ApekMkqjJz1gDjPXRauo+MpUaCgzFL6q VV+ma5Qd7g1rjDUYjfDqZEzkx2nSuiSTe+OVn88aTNN7HQNEoiPb5RhDuP1rkqtPAvfI Cijw== 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=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ne32si299199ejc.249.2022.01.26.14.23.47; Wed, 26 Jan 2022 14:24:13 -0800 (PST) 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=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243706AbiAZR1Y (ORCPT + 99 others); Wed, 26 Jan 2022 12:27:24 -0500 Received: from foss.arm.com ([217.140.110.172]:55128 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237164AbiAZR1X (ORCPT ); Wed, 26 Jan 2022 12:27:23 -0500 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 F0DB1D6E; Wed, 26 Jan 2022 09:27:22 -0800 (PST) Received: from [10.32.33.50] (e121896.warwick.arm.com [10.32.33.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2119B3F7D8; Wed, 26 Jan 2022 09:27:21 -0800 (PST) Subject: Re: [RFC V1 11/11] perf: Capture branch privilege information To: Anshuman Khandual , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Catalin Marinas , Will Deacon , Mark Rutland , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , linux-perf-users@vger.kernel.org, Jiri Olsa , Namhyung Kim , Rob Herring , Suzuki K Poulose References: <1642998653-21377-1-git-send-email-anshuman.khandual@arm.com> <1642998653-21377-12-git-send-email-anshuman.khandual@arm.com> From: James Clark Message-ID: Date: Wed, 26 Jan 2022 17:27:19 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <1642998653-21377-12-git-send-email-anshuman.khandual@arm.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 24/01/2022 04:30, Anshuman Khandual wrote: > Platforms like arm64 could capture privilege level information for all the > branch records. Hence this adds a new element in the struct branch_entry to > record the privilege level information, which could be requested through a > new event.attr.branch_sample_type flag PERF_SAMPLE_BRANCH_PRIV_SAVE. While > here, update the BRBE driver as required. > > Cc: Will Deacon > Cc: Mark Rutland > Cc: Peter Zijlstra > Cc: Ingo Molnar > Cc: Arnaldo Carvalho de Melo > Cc: Jiri Olsa > Cc: Namhyung Kim > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-perf-users@vger.kernel.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Anshuman Khandual > --- > drivers/perf/arm_pmu_brbe.c | 28 ++++++++++++++++++++++++ > include/linux/perf_event.h | 5 +++++ > include/uapi/linux/perf_event.h | 13 ++++++++++- > tools/include/uapi/linux/perf_event.h | 13 ++++++++++- > tools/perf/Documentation/perf-record.txt | 1 + > tools/perf/util/parse-branch-options.c | 1 + > 6 files changed, 59 insertions(+), 2 deletions(-) > > diff --git a/drivers/perf/arm_pmu_brbe.c b/drivers/perf/arm_pmu_brbe.c > index 7cd1208c6c58..d4cbea74c148 100644 > --- a/drivers/perf/arm_pmu_brbe.c > +++ b/drivers/perf/arm_pmu_brbe.c > @@ -270,6 +270,25 @@ static int brbe_fetch_perf_type(u64 brbinf) > } > } > > +static int brbe_fetch_perf_priv(u64 brbinf) > +{ > + int brbe_el = brbe_fetch_el(brbinf); > + > + switch (brbe_el) { > + case BRBINF_EL_EL0: > + return PERF_BR_USER; > + case BRBINF_EL_EL1: > + return PERF_BR_KERNEL; > + case BRBINF_EL_EL2: > + if (is_kernel_in_hyp_mode()) > + return PERF_BR_KERNEL; > + return PERF_BR_HV; > + default: > + pr_warn("unknown branch privilege captured\n"); > + return -1; > + } > +} > + > static void capture_brbe_flags(struct pmu_hw_events *cpuc, struct perf_event *event, > u64 brbinf, int idx) > { > @@ -302,6 +321,15 @@ static void capture_brbe_flags(struct pmu_hw_events *cpuc, struct perf_event *ev > cpuc->brbe_entries[idx].in_tx = brbinf & BRBINF_TX; > } > } > + > + if (branch_sample_priv(event)) { > + /* > + * All these information (i.e branch privilege level) are not > + * available for source only branch records. > + */ > + if (type != BRBINF_VALID_SOURCE) > + cpuc->brbe_entries[idx].priv = brbe_fetch_perf_priv(brbinf); > + } > } > > /* > diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h > index 916ce5102b33..8021b6a30d86 100644 > --- a/include/linux/perf_event.h > +++ b/include/linux/perf_event.h > @@ -1688,4 +1688,9 @@ static inline bool branch_sample_hw_index(const struct perf_event *event) > { > return event->attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX; > } > + > +static inline bool branch_sample_priv(const struct perf_event *event) > +{ > + return event->attr.branch_sample_type & PERF_SAMPLE_BRANCH_PRIV_SAVE; > +} > #endif /* _LINUX_PERF_EVENT_H */ > diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h > index 361fdc6b87a0..4d77710f7a4e 100644 > --- a/include/uapi/linux/perf_event.h > +++ b/include/uapi/linux/perf_event.h > @@ -204,6 +204,8 @@ enum perf_branch_sample_type_shift { > > PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 17, /* save low level index of raw branch records */ > > + PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 18, /* save privillege mode */ > + > PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ > }; > > @@ -233,6 +235,8 @@ enum perf_branch_sample_type { > > PERF_SAMPLE_BRANCH_HW_INDEX = 1U << PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT, > > + PERF_SAMPLE_BRANCH_PRIV_SAVE = 1U << PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT, > + > PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, > }; > > @@ -265,6 +269,12 @@ enum { > PERF_BR_MAX, > }; > > +enum { > + PERF_BR_USER = 0, > + PERF_BR_KERNEL = 1, > + PERF_BR_HV = 2, > +}; > + Can we have 0 as "UNKNOWN". It's going to be difficult to parse files when privilege information isn't saved and get accurate results without that. For example if it's not set then presumably the field would be 0 (PERF_BR_USER), but that doesn't mean the samples are user in that case. I know you might be able to go backwards and look at what arguments were passed to the kernel but it's not guaranteed that the kernel honored the request anyway. There are also other platforms to think about etc. If you look at the branch type definitions above they start at 0 (PERF_BR_UNKNOWN) which I think works out quite nicely in the userspace code. > #define PERF_SAMPLE_BRANCH_PLM_ALL \ > (PERF_SAMPLE_BRANCH_USER|\ > PERF_SAMPLE_BRANCH_KERNEL|\ > @@ -1377,7 +1387,8 @@ struct perf_branch_entry { > abort:1, /* transaction abort */ > cycles:16, /* cycle count to last branch */ > type:6, /* branch type */ > - reserved:38; > + priv:2, /* privilege level */> + reserved:36; > }; > > union perf_sample_weight { > diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h > index 9a82b8aaed93..a2208400b0b9 100644 > --- a/tools/include/uapi/linux/perf_event.h > +++ b/tools/include/uapi/linux/perf_event.h > @@ -204,6 +204,8 @@ enum perf_branch_sample_type_shift { > > PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 17, /* save low level index of raw branch records */ > > + PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 18, /* save privillege mode */ > + > PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ > }; > > @@ -233,6 +235,8 @@ enum perf_branch_sample_type { > > PERF_SAMPLE_BRANCH_HW_INDEX = 1U << PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT, > > + PERF_SAMPLE_BRANCH_PRIV_SAVE = 1U << PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT, > + > PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, > }; > > @@ -265,6 +269,12 @@ enum { > PERF_BR_MAX, > }; > > +enum { > + PERF_BR_USER = 0, > + PERF_BR_KERNEL = 1, > + PERF_BR_HV = 2, > +}; > + > #define PERF_SAMPLE_BRANCH_PLM_ALL \ > (PERF_SAMPLE_BRANCH_USER|\ > PERF_SAMPLE_BRANCH_KERNEL|\ > @@ -1377,7 +1387,8 @@ struct perf_branch_entry { > abort:1, /* transaction abort */ > cycles:16, /* cycle count to last branch */ > type:6, /* branch type */ > - reserved:38; > + priv:2, /* privilege level */ > + reserved:36; > }; > > union perf_sample_weight { > diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt > index 9ccc75935bc5..3e33686977a1 100644 > --- a/tools/perf/Documentation/perf-record.txt > +++ b/tools/perf/Documentation/perf-record.txt > @@ -387,6 +387,7 @@ following filters are defined: > - abort_tx: only when the target is a hardware transaction abort > - cond: conditional branches > - save_type: save branch type during sampling in case binary is not available later > + - priv: save privilege state during sampling in case binary is not available later > > + > The option requires at least one branch type among any, any_call, any_ret, ind_call, cond. > diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c > index bb4aa88c50a8..00588b9db474 100644 > --- a/tools/perf/util/parse-branch-options.c > +++ b/tools/perf/util/parse-branch-options.c > @@ -32,6 +32,7 @@ static const struct branch_mode branch_modes[] = { > BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL), > BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE), > BRANCH_OPT("stack", PERF_SAMPLE_BRANCH_CALL_STACK), > + BRANCH_OPT("priv", PERF_SAMPLE_BRANCH_PRIV_SAVE), > BRANCH_END > }; > >