Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp5337629rwd; Mon, 12 Jun 2023 03:45:59 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5/fB2AuK1pnhIaCl8emJMQBjTu38kcRbU+K+zs2zrNvISZwepAz1F+nBUe62qYm5ZO12ck X-Received: by 2002:a05:6808:1389:b0:39c:a986:953a with SMTP id c9-20020a056808138900b0039ca986953amr4749474oiw.34.1686566759620; Mon, 12 Jun 2023 03:45:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686566759; cv=none; d=google.com; s=arc-20160816; b=xdJSMevm9gFAAAze47D6efHRf87tIwMJMOqJn71B9MopwuhNM7Dl/J/h+XW1EowhM6 06Mrr+Ienstw7JVj82coB+yFVPM4QACXI0B9dDE3nMMkt3Qd/SSMr5Yw4VoY5D7rYMB6 X8FGkUFues4b0IzaOj2cGNJk30WIRrh1X8Ff3Ode6zdHi15VzPzhpOiL51ETeiE40Uqu AzjLzmxE4cYaxv+eG5cWOD72mQAImBxxOkiCN2u8Ts5bOcmB+5Ee1u5VwmAKkZjX9uPk BdMfskK9+rSb6WrgJXoMKBDgn35znN25Evfc9nKFlA2e3pHO4aD278UmV1Yiin6VGmuY zPyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id; bh=naHTV79FesxMuEn0TUIh8FVgSN354ZToACN3LYeMCOE=; b=AyJMtWFTC6QipRWJ6n4RjoeKbkUexGw0I//yTgOgKaLvmiYjDOINvVpx3V9DUnrzvj wNprotPn8zszSf1IEtpRkLILcgAG3/2nSDvwYTc6w8U7LiHI+Z6UhiZj4HjZSeN2J2EC EvJDmUyNztkQyPCi3UNdjBaaW4HeEcEsHF5KgXSFEHuS/xJpZWt3dv3QwbewJ3EjJnmC ofY/iPC5eLe19Hx7e5gw7cAFkDGSkHXHi5BoMkf3vDBMNo9YCJSw9GoXtCMazCPOp/7x wAWy6pR3pm4Ax57L6Sxgrme29yunAMuxVIjI2ktAwPPKMdUXzRc9Bg/T5H698/L/rdkw nbJw== 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 p24-20020a17090b011800b0025be9c5858dsi1297111pjz.88.2023.06.12.03.45.48; Mon, 12 Jun 2023 03:45:59 -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 S234888AbjFLKcw (ORCPT + 99 others); Mon, 12 Jun 2023 06:32:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231359AbjFLKcV (ORCPT ); Mon, 12 Jun 2023 06:32:21 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id F1E527AB5; Mon, 12 Jun 2023 03:13:45 -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 83B282F4; Mon, 12 Jun 2023 03:13:30 -0700 (PDT) Received: from [192.168.0.146] (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 300A13F663; Mon, 12 Jun 2023 03:12:37 -0700 (PDT) Message-ID: <65b7c83f-7fab-3f4e-bff8-9a60937dc207@arm.com> Date: Mon, 12 Jun 2023 15:42:38 +0530 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: [PATCH V11 06/10] arm64/perf: Enable branch stack events via FEAT_BRBE Content-Language: en-US To: James Clark , Mark Rutland Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, will@kernel.org, catalin.marinas@arm.com, Mark Brown , Rob Herring , Marc Zyngier , Suzuki Poulose , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , linux-perf-users@vger.kernel.org References: <20230531040428.501523-1-anshuman.khandual@arm.com> <20230531040428.501523-7-anshuman.khandual@arm.com> <510f88f2-574c-097f-7299-2842b1cf432d@arm.com> From: Anshuman Khandual In-Reply-To: <510f88f2-574c-097f-7299-2842b1cf432d@arm.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,NICE_REPLY_A, 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 On 6/9/23 19:04, James Clark wrote: > > > On 09/06/2023 13:47, Mark Rutland wrote: >> On Fri, Jun 09, 2023 at 10:52:37AM +0530, Anshuman Khandual wrote: >>> [...] >>> >>> On 6/5/23 19:13, Mark Rutland wrote: >>>>> +void armv8pmu_branch_read(struct pmu_hw_events *cpuc, struct perf_event *event) >>>>> +{ >>>>> + struct brbe_hw_attr *brbe_attr = (struct brbe_hw_attr *)cpuc->percpu_pmu->private; >>>>> + u64 brbfcr, brbcr; >>>>> + int idx, loop1_idx1, loop1_idx2, loop2_idx1, loop2_idx2, count; >>>>> + >>>>> + brbcr = read_sysreg_s(SYS_BRBCR_EL1); >>>>> + brbfcr = read_sysreg_s(SYS_BRBFCR_EL1); >>>>> + >>>>> + /* Ensure pause on PMU interrupt is enabled */ >>>>> + WARN_ON_ONCE(!(brbcr & BRBCR_EL1_FZP)); >>>>> + >>>>> + /* Pause the buffer */ >>>>> + write_sysreg_s(brbfcr | BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1); >>>>> + isb(); >>>>> + >>>>> + /* Determine the indices for each loop */ >>>>> + loop1_idx1 = BRBE_BANK0_IDX_MIN; >>>>> + if (brbe_attr->brbe_nr <= BRBE_BANK_MAX_ENTRIES) { >>>>> + loop1_idx2 = brbe_attr->brbe_nr - 1; >>>>> + loop2_idx1 = BRBE_BANK1_IDX_MIN; >>>>> + loop2_idx2 = BRBE_BANK0_IDX_MAX; >>>>> + } else { >>>>> + loop1_idx2 = BRBE_BANK0_IDX_MAX; >>>>> + loop2_idx1 = BRBE_BANK1_IDX_MIN; >>>>> + loop2_idx2 = brbe_attr->brbe_nr - 1; >>>>> + } >>>>> + >>>>> + /* Loop through bank 0 */ >>>>> + select_brbe_bank(BRBE_BANK_IDX_0); >>>>> + for (idx = 0, count = loop1_idx1; count <= loop1_idx2; idx++, count++) { >>>>> + if (!capture_branch_entry(cpuc, event, idx)) >>>>> + goto skip_bank_1; >>>>> + } >>>>> + >>>>> + /* Loop through bank 1 */ >>>>> + select_brbe_bank(BRBE_BANK_IDX_1); >>>>> + for (count = loop2_idx1; count <= loop2_idx2; idx++, count++) { >>>>> + if (!capture_branch_entry(cpuc, event, idx)) >>>>> + break; >>>>> + } >>>>> + >>>>> +skip_bank_1: >>>>> + cpuc->branches->branch_stack.nr = idx; >>>>> + cpuc->branches->branch_stack.hw_idx = -1ULL; >>>>> + process_branch_aborts(cpuc); >>>>> + >>>>> + /* Unpause the buffer */ >>>>> + write_sysreg_s(brbfcr & ~BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1); >>>>> + isb(); >>>>> + armv8pmu_branch_reset(); >>>>> +} >>>> The loop indicies are rather difficult to follow, and I think those can be made >>>> quite a lot simpler if split out, e.g. >>>> >>>> | int __armv8pmu_branch_read(struct pmu_hw_events *cpuc, struct perf_event *event) >>>> | { >>>> | struct brbe_hw_attr *brbe_attr = (struct brbe_hw_attr *)cpuc->percpu_pmu->private; >>>> | int nr_hw_entries = brbe_attr->brbe_nr; >>>> | int idx; >>> >>> I guess idx needs an init to 0. >> >> Yes, sorry, that should have been: >> >> int idx = 0; >> >>>> | >>>> | select_brbe_bank(BRBE_BANK_IDX_0); >>>> | while (idx < nr_hw_entries && idx < BRBE_BANK0_IDX_MAX) { >>>> | if (!capture_branch_entry(cpuc, event, idx)) >>>> | return idx; >>>> | idx++; >>>> | } >>>> | >>>> | select_brbe_bank(BRBE_BANK_IDX_1); >>>> | while (idx < nr_hw_entries && idx < BRBE_BANK1_IDX_MAX) { >>>> | if (!capture_branch_entry(cpuc, event, idx)) >>>> | return idx; >>>> | idx++; >>>> | } >>>> | >>>> | return idx; >>>> | } >>> >>> These loops are better than the proposed one with indices, will update. >> >> Great! >> >>>> | >>>> | void armv8pmu_branch_read(struct pmu_hw_events *cpuc, struct perf_event *event) >>>> | { >>>> | u64 brbfcr, brbcr; >>>> | int nr; >>>> | >>>> | brbcr = read_sysreg_s(SYS_BRBCR_EL1); >>>> | brbfcr = read_sysreg_s(SYS_BRBFCR_EL1); >>>> | >>>> | /* Ensure pause on PMU interrupt is enabled */ >>>> | WARN_ON_ONCE(!(brbcr & BRBCR_EL1_FZP)); >>>> | >>>> | /* Pause the buffer */ >>>> | write_sysreg_s(brbfcr | BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1); >>>> | isb(); >>>> | >>>> | nr = __armv8pmu_branch_read(cpus, event); >>>> | >>>> | cpuc->branches->branch_stack.nr = nr; >>>> | cpuc->branches->branch_stack.hw_idx = -1ULL; >>>> | process_branch_aborts(cpuc); >>>> | >>>> | /* Unpause the buffer */ >>>> | write_sysreg_s(brbfcr & ~BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1); >>>> | isb(); >>>> | armv8pmu_branch_reset(); >>>> | } >>>> >>>> Looking at I see: >>>> >>>> | /* >>>> | * branch stack layout: >>>> | * nr: number of taken branches stored in entries[] >>>> | * hw_idx: The low level index of raw branch records >>>> | * for the most recent branch. >>>> | * -1ULL means invalid/unknown. >>>> | * >>>> | * Note that nr can vary from sample to sample >>>> | * branches (to, from) are stored from most recent >>>> | * to least recent, i.e., entries[0] contains the most >>>> | * recent branch. >>>> | * The entries[] is an abstraction of raw branch records, >>>> | * which may not be stored in age order in HW, e.g. Intel LBR. >>>> | * The hw_idx is to expose the low level index of raw >>>> | * branch record for the most recent branch aka entries[0]. >>>> | * The hw_idx index is between -1 (unknown) and max depth, >>>> | * which can be retrieved in /sys/devices/cpu/caps/branches. >>>> | * For the architectures whose raw branch records are >>>> | * already stored in age order, the hw_idx should be 0. >>>> | */ >>>> | struct perf_branch_stack { >>>> | __u64 nr; >>>> | __u64 hw_idx; >>>> | struct perf_branch_entry entries[]; >>>> | }; >>>> >>>> ... which seems to indicate we should be setting hw_idx to 0, since IIUC our >>>> records are in age order. >>> Branch records are indeed in age order, sure will change hw_idx as 0. Earlier >>> figured that there was no need for hw_idx and hence marked it as -1UL similar >>> to other platforms like powerpc. >> >> That's fair enough; looking at power_pmu_bhrb_read() in >> arch/powerpc/perf/core-book3s.c, I see a comment: >> >> Branches are read most recent first (ie. mfbhrb 0 is >> the most recent branch). >> >> ... which suggests that should be 0 also, or that the documentation is wrong. >> >> Do you know how the perf tool consumes this? >> >> Thanks, >> Mark. > > It looks like it's a unique ID/last position updated in the LBR FIFO and > it's used to stitch callchains together when the stack depth exceeds the > buffer size. Perf takes the previous one that got filled to the limit > and and the new one and stitches them together if the hw_idx matches. Right. > > There are some options in perf you need to provide to make it happen, so > I think for BRBE it doesn't matter what value is assigned to it. -1 > seems to be a 'not used' value which we should probably set in case the > event is opened with PERF_SAMPLE_BRANCH_HW_INDEX -1 indeed did seem like a "not used" option rather than an "unkwown" option. > > You could also fail to open the event if PERF_SAMPLE_BRANCH_HW_INDEX is > set, and that would save writing out -1 every time for every branch > stack. Although it's not enabled by default, so maybe that's not necessary. Yeah blocking events with PERF_SAMPLE_BRANCH_HW_INDEX is not necessary IMHO.