From patchwork Wed May 17 02:24:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anshuman Khandual X-Patchwork-Id: 95005 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp838086vqo; Tue, 16 May 2023 19:52:12 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6AK2MP1fhuRVAfwrBMZ0fjBXK+7svarOIjhV+slfHg94AfQB0knME8AT7S5aaPFoD3PG/l X-Received: by 2002:a17:90b:fd6:b0:250:132a:5d93 with SMTP id gd22-20020a17090b0fd600b00250132a5d93mr36456368pjb.49.1684291932060; Tue, 16 May 2023 19:52:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684291932; cv=none; d=google.com; s=arc-20160816; b=Ncl9hj6v4Dpxz/hrgLvIWZpc2anYOLS6Q1yjwavN+P09+UShB3/Wh/3FaFucwZBSdZ FeQjcH8zic9Rpqx56yItorcV9itN7vV5+cgcJRZNcjCoyhOBrM2WD7Uh8Z7+tstBZLd2 20+KB8daM0kq1FDsvg6o9D1aaJ8ELmtDu0C9YLZZVnqXq+lZFh+B45Qg79CQi43FYFtd a1K09DS8dd0UeM5fhz6b6EBUwRAnslWT7TkDegejiMqP/9OsQsdadcVobNAQah65owSh ovw/+z2gMM7WDR21d7te/Cn8mP3bl2AcYprcwX3WwJbrh564+YrF6ojvJBBh/zoKOtP2 CJxQ== 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=F5K7ei5zkMOdwAqoNeD0uQeqRgecITa0mQZIL+5h9II=; b=vsTSunRxn144DM4zeo490+ZgCcc3Ou/qqKEdeGqJyv6qA7pxt6cvVLJR8WcKxxE3ap YyUclomNc21hfbK5SV2YW8vGr/YQB2gRYgPUAgYNn63mbeY0fdRtxaV0gX08CND5NOUI F64pv0OOhncmDUAPDjY3o2UnQfPlPZrW8BFEzs0y8Rqg3+cfsyRsM2V1VSYAFKzjAkLG Btr1VuYD6s0LHmvP6EpjlvXRsyBvvQJaiL8B4M59B96JEoAyEK5Azy0Y4jtz+1ifZ28u TNs2lwdF5wg3JIe1pwcwzuEcTzseo8bBnFf8k9I7E22g40JkUX5EcM9fD9Hw76LFC1hT AY0w== 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 Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id cx10-20020a17090afd8a00b0025323913ae0si642151pjb.179.2023.05.16.19.52.00; Tue, 16 May 2023 19:52:12 -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 S232083AbjEQCZy (ORCPT + 99 others); Tue, 16 May 2023 22:25:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48498 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232081AbjEQCZe (ORCPT ); Tue, 16 May 2023 22:25:34 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 997496197; Tue, 16 May 2023 19:25:09 -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 820702F4; Tue, 16 May 2023 19:25:53 -0700 (PDT) Received: from a077893.arm.com (unknown [10.163.70.237]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A46F53F793; Tue, 16 May 2023 19:25:03 -0700 (PDT) From: Anshuman Khandual To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, will@kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com Cc: Anshuman Khandual , Mark Brown , James Clark , Rob Herring , Marc Zyngier , Suzuki Poulose , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , linux-perf-users@vger.kernel.org Subject: [PATCH V10 08/10] arm64/perf: Add struct brbe_regset helper functions Date: Wed, 17 May 2023 07:54:08 +0530 Message-Id: <20230517022410.722287-9-anshuman.khandual@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230517022410.722287-1-anshuman.khandual@arm.com> References: <20230517022410.722287-1-anshuman.khandual@arm.com> MIME-Version: 1.0 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 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766108096992060960?= X-GMAIL-MSGID: =?utf-8?q?1766108096992060960?= The primary abstraction level for fetching branch records from BRBE HW has been changed as 'struct brbe_regset', which contains storage for all three BRBE registers i.e BRBSRC, BRBTGT, BRBINF. Whether branch record processing happens in the task sched out path, or in the PMU IRQ handling path, these registers need to be extracted from the HW. Afterwards both live and stored sets need to be stitched together to create final branch records set. This adds required helper functions for such operations. Cc: Catalin Marinas Cc: Will Deacon Cc: Mark Rutland Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Anshuman Khandual --- drivers/perf/arm_brbe.c | 163 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/drivers/perf/arm_brbe.c b/drivers/perf/arm_brbe.c index 484842d8cf3e..759db681d673 100644 --- a/drivers/perf/arm_brbe.c +++ b/drivers/perf/arm_brbe.c @@ -44,6 +44,169 @@ static void select_brbe_bank(int bank) isb(); } +/* + * This scans over BRBE register banks and captures individual branch reocrds + * [BRBSRC, BRBTGT, BRBINF] into a pre-allocated 'struct brbe_regset' buffer, + * until an invalid one gets encountered. The caller for this function needs + * to ensure BRBE is an appropriate state before the records can be captured. + */ +static int capture_brbe_regset(struct brbe_hw_attr *brbe_attr, struct brbe_regset *buf) +{ + int loop1_idx1, loop1_idx2, loop2_idx1, loop2_idx2; + int idx, count; + + 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; + } + + select_brbe_bank(BRBE_BANK_IDX_0); + for (idx = 0, count = loop1_idx1; count <= loop1_idx2; idx++, count++) { + buf[idx].brbinf = get_brbinf_reg(idx); + /* + * There are no valid entries anymore on the buffer. + * Abort the branch record processing to save some + * cycles and also reduce the capture/process load + * for the user space as well. + */ + if (brbe_invalid(buf[idx].brbinf)) + return idx; + + buf[idx].brbsrc = get_brbsrc_reg(idx); + buf[idx].brbtgt = get_brbtgt_reg(idx); + } + + select_brbe_bank(BRBE_BANK_IDX_1); + for (count = loop2_idx1; count <= loop2_idx2; idx++, count++) { + buf[idx].brbinf = get_brbinf_reg(idx); + /* + * There are no valid entries anymore on the buffer. + * Abort the branch record processing to save some + * cycles and also reduce the capture/process load + * for the user space as well. + */ + if (brbe_invalid(buf[idx].brbinf)) + return idx; + + buf[idx].brbsrc = get_brbsrc_reg(idx); + buf[idx].brbtgt = get_brbtgt_reg(idx); + } + return idx; +} + +static inline void copy_brbe_regset(struct brbe_regset *src, int src_idx, + struct brbe_regset *dst, int dst_idx) +{ + dst[dst_idx].brbinf = src[src_idx].brbinf; + dst[dst_idx].brbsrc = src[src_idx].brbsrc; + dst[dst_idx].brbtgt = src[src_idx].brbtgt; +} + +/* + * This function concatenates branch records from stored and live buffer + * up to maximum nr_max records and the stored buffer holds the resultant + * buffer. The concatenated buffer contains all the branch records from + * the live buffer but might contain some from stored buffer considering + * the maximum combined length does not exceed 'nr_max'. + * + * Stored records Live records + * ------------------------------------------------^ + * | S0 | L0 | Newest | + * --------------------------------- | + * | S1 | L1 | | + * --------------------------------- | + * | S2 | L2 | | + * --------------------------------- | + * | S3 | L3 | | + * --------------------------------- | + * | S4 | L4 | nr_max + * --------------------------------- | + * | | L5 | | + * --------------------------------- | + * | | L6 | | + * --------------------------------- | + * | | L7 | | + * --------------------------------- | + * | | | | + * --------------------------------- | + * | | | Oldest | + * ------------------------------------------------V + * + * + * S0 is the newest in the stored records, where as L7 is the oldest in + * the live reocords. Unless the live buffer is detetcted as being full + * thus potentially dropping off some older records, L7 and S0 records + * are contiguous in time for a user task context. The stitched buffer + * here represents maximum possible branch records, contiguous in time. + * + * Stored records Live records + * ------------------------------------------------^ + * | L0 | L0 | Newest | + * --------------------------------- | + * | L0 | L1 | | + * --------------------------------- | + * | L2 | L2 | | + * --------------------------------- | + * | L3 | L3 | | + * --------------------------------- | + * | L4 | L4 | nr_max + * --------------------------------- | + * | L5 | L5 | | + * --------------------------------- | + * | L6 | L6 | | + * --------------------------------- | + * | L7 | L7 | | + * --------------------------------- | + * | S0 | | | + * --------------------------------- | + * | S1 | | Oldest | + * ------------------------------------------------V + * | S2 | <----| + * ----------------- | + * | S3 | <----| Dropped off after nr_max + * ----------------- | + * | S4 | <----| + * ----------------- + */ +static int stitch_stored_live_entries(struct brbe_regset *stored, + struct brbe_regset *live, + int nr_stored, int nr_live, + int nr_max) +{ + int nr_total, nr_excess, nr_last, i; + + nr_total = nr_stored + nr_live; + nr_excess = nr_total - nr_max; + + /* Stored branch records in stitched buffer */ + if (nr_live == nr_max) + nr_stored = 0; + else if (nr_excess > 0) + nr_stored -= nr_excess; + + /* Stitched buffer branch records length */ + if (nr_total > nr_max) + nr_last = nr_max; + else + nr_last = nr_total; + + /* Move stored branch records */ + for (i = 0; i < nr_stored; i++) + copy_brbe_regset(stored, i, stored, nr_last - nr_stored - 1 + i); + + /* Copy live branch records */ + for (i = 0; i < nr_live; i++) + copy_brbe_regset(live, i, stored, i); + + return nr_last; +} + /* * Generic perf branch filters supported on BRBE *