From patchwork Fri Feb 16 00:08:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201849 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201298dyb; Thu, 15 Feb 2024 16:09:12 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXUWdifw3iXl0MGg/9CiFeeyj0TDHJbU/Xzy/UooqsSu8sqhTsR3VZOfTNzrSz+66ieNThHPj3Pk6+wGtABVeT+oE6AKA== X-Google-Smtp-Source: AGHT+IGLyzxKlz/9ZGksZjAcFV409vWB4OYaDP7gdyLstdgUhdXKqCMcHiwNN3xiASron+wk8yio X-Received: by 2002:a50:ef0c:0:b0:55f:fc6f:835a with SMTP id m12-20020a50ef0c000000b0055ffc6f835amr2476546eds.31.1708042152556; Thu, 15 Feb 2024 16:09:12 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042152; cv=pass; d=google.com; s=arc-20160816; b=Nt3AiDm5b77vdcJYp4SB5vLjEIrq9gKzgclsSijzmF83J+F1+gdpK5NvRgtAhpH/8/ BP811estMjJF98gT1ZfVWyGWbIncdB+g4qMgZiiomOHrL52w2t0FXIPt7d8Nr08hzOv+ EEjpfqj72sc32GMIh+cH1vB60XY153xwdKyHJcyF0qt6zC8E0Jp7VqwU8qinpLfy1frK 4PtvUtCXDuXy2kGmSpI0C5EBX0Y3eBuylVpq2Z8zq0EFaysDgsCDQHbLgiMThS+/Yw4J 0GfCw/gj4oePsMUNcQDfPFh0VnWMwH0qINNqlD4IMqJLlfHQj5vTdmoXbQ5nqEPSbbvh X28Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=oULp81TNDm6rtXJp1+1NlVw8kUN7N6Lx6G6xlg9BNVs=; fh=JPQLSNQRZ7gouaNZAHa0NGpROorXJnrbOx0eSl+VuMk=; b=0YCpTEC0R2UxGSj7wzN0cTL7N2GBJ4/gOi+WSPk4KQf07G2LCc1pePvcepuW+gdPw7 spYqZUmE2NCAjWD8Y9RYj3qe+p/tkpsfYB6tRrTHd4iYBC7REesispDyX04fC7eOpafI nI+XccWWHYJErOtanaH6A9NZ/Cp2R/XtVXCgPnoQtXM0lptD/fB1+m4gk/CmwLI/+T6J btRlS72ORWSXOGHDovHKoSKR3DAZuF5yhsLw/odSMvNlp8tEV3uM3IFhGckxF3tEzBsi gt24c4PKlCD4hmkiQ4+PGQFSy3Xeh14ngYxeUqXPk3vwKDClDFXh51yNNzKzN4G/vloy obwA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=DxDCxmkx; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67874-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67874-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id a35-20020a509ea6000000b0055eba1df579si1066071edf.571.2024.02.15.16.09.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:09:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67874-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=DxDCxmkx; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67874-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67874-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id B89B81F2545F for ; Fri, 16 Feb 2024 00:09:11 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A5CED8F48; Fri, 16 Feb 2024 00:08:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="DxDCxmkx" Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC5E17F9 for ; Fri, 16 Feb 2024 00:08:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042125; cv=none; b=AIQFySvJ2gHjBV/sLl70sA2tulY1t5Bs+1I4W4UIF6JGiWZ6AEXH4CbWUYTOi11NqTN/+I/AqRZhzq7LCbLJ4GoZTEZZEffIJDnqbHPyhTwdUCPuNC42qh/Rj4xR54LoHuThGzFMPxitwYQBuFKrFvvhBFfifU3oCInkfgzH5qs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042125; c=relaxed/simple; bh=+ztwmbEweby5bHFMBlDPRY9F7IaAz7efgcfvXOjOMFo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BtINdjCUmCoaFUENDLYxNqIizMisAou6ZZSS68l0gbF2MG4ki4fR6XmH3QNknndp1cgxn9Qx6IHRcbuS0Wq6uCVGWlBAcTZ0Mr+BJ+jKefWEPvw6qjx7ei/XDHP1mSsKLnfeoj5MsZwZKiZlg4+NZgTm6N8rU3vMO/NZeoxZDiw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=DxDCxmkx; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-1d7881b1843so13147205ad.3 for ; Thu, 15 Feb 2024 16:08:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042122; x=1708646922; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oULp81TNDm6rtXJp1+1NlVw8kUN7N6Lx6G6xlg9BNVs=; b=DxDCxmkxjrrukDu9xKwUBIYHc+JGcrFCNIUcqbUex3+GhYvfHY4QKNmZDYQF5bg32W 1LZf4MdOo3ae1YogH6bNjOYX4GJ+4SvREvRnZJAye+iIRMK1TIbvaA24P12yZ07A8ARA D+XPXiB3RcSHUFCBbOHGYJZs4xWSyUp8To/xxuWUNYEqftMOMwZ2SC8B8FAYPXpIOgEc zVK4q9r9rJ5s9FisZPtsryqa0sD7A4kwfk9HGJ0HF+0IgIzYHCbyCiBo2OADL1Gfiya5 iZT4vjEqE/6BX9N3/sxNegIejDaVAsqFmS9mtGQeqoLAvkPo0Tg3bGnpJc6/yxEuYeqv F2CQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042122; x=1708646922; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oULp81TNDm6rtXJp1+1NlVw8kUN7N6Lx6G6xlg9BNVs=; b=voLaDMcx7GaI+sMbLX0+aMTv0cU5PYE6q7rRUES3GOfWaCfKvtGPoU1ohTiNZYmkEk cnSnlc4FyXkYaSrQiJpi9OD/71GmaVSf2YeDSvAF2M76il5Oh0cqB1EtyO5WPR4VEJ6e OM46stEuM1kWSzVfFqieGkrJMkQFQqzSr0e9U2RkUoCMnWT4eyCM6fjb80PvQbV5rpEH xTePD4jPkc08atyz2/f+yghvvbII29Z5YssaVNqB4SabAM2cG6XxbEE7YYtC+TeVTk/3 rZfE7hRt3HJremtfG1DWtDk7YX3pMLS6AdG2i1XYwcyX9qgOi/dn+ruBxK6IF2s/j7jT Uywg== X-Forwarded-Encrypted: i=1; AJvYcCVkiiwK+4n0IEk0BtNh0+EIWBOvQ/bpn56e1oWzWEjLaNuif6NOJ7VeLe6IEGZjgE1B8Dx6V/llBFLAh5PBZ77MRpkVylJRsShQ7JcT X-Gm-Message-State: AOJu0YxXlr1zQdFiJwhiTtQp3FNGy0/d6/8RDTfE+o6YkPxiNArWjvdl HoZpm6IZSmkMZyOn7quSZ+wiNfe8qdfwQuiU7a3BVcnqR5oJy6NVFuvWgg3d2MM= X-Received: by 2002:a17:903:1212:b0:1d9:14fb:d142 with SMTP id l18-20020a170903121200b001d914fbd142mr3570668plh.32.1708042122114; Thu, 15 Feb 2024 16:08:42 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:41 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Samuel Holland Subject: [PATCH v1 1/6] dt-bindings: cache: Document the sifive,perfmon-counters property Date: Thu, 15 Feb 2024 16:08:13 -0800 Message-ID: <20240216000837.1868917-2-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012008389115740 X-GMAIL-MSGID: 1791012008389115740 The SiFive Composable Cache controller contains an optional PMU with a configurable number of event counters. Document a property which describes the number of available counters. Signed-off-by: Samuel Holland --- Documentation/devicetree/bindings/cache/sifive,ccache0.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/cache/sifive,ccache0.yaml b/Documentation/devicetree/bindings/cache/sifive,ccache0.yaml index 7e8cebe21584..100eda4345de 100644 --- a/Documentation/devicetree/bindings/cache/sifive,ccache0.yaml +++ b/Documentation/devicetree/bindings/cache/sifive,ccache0.yaml @@ -81,6 +81,11 @@ properties: The reference to the reserved-memory for the L2 Loosely Integrated Memory region. The reserved memory node should be defined as per the bindings in reserved-memory.txt. + sifive,perfmon-counters: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: Number of PMU counter registers + allOf: - $ref: /schemas/cache-controller.yaml# From patchwork Fri Feb 16 00:08:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201852 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201763dyb; Thu, 15 Feb 2024 16:10:21 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWNvur9knqcXonwS9D6s1OlV4UGZl9iFZ5zk13JZFCUos5Ht8pGUTsFRsAPP/0E3+HtkXJBmlfWWF1qy15lJquPN02pAA== X-Google-Smtp-Source: AGHT+IFlCJcbBa1py/Byk2TMoG9TupEtUK5ls14rHtmQ0q1kAZ0LhP8IrqjUzPHlp7ZVvF5O32BT X-Received: by 2002:a05:6871:89e:b0:219:69df:67fd with SMTP id r30-20020a056871089e00b0021969df67fdmr3686289oaq.46.1708042220857; Thu, 15 Feb 2024 16:10:20 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042220; cv=pass; d=google.com; s=arc-20160816; b=NDdRWigtNh3gIk8cOd4buFBiguiOmQjxdfnNz/W/9PtyqjTDS0MulUrt740bXhThCV 3QnCcKjt6FARl7RE8es1goJXsbDKyR+/Nl9OYkVK6n4i31j9PuIetyBr6zYqCxbfBeim oAb4mRCj96hWIhSyeBB/0m+O4qOAWh8yqTr5OtQdIpDTrryElsj/fh68pRhbmnpAZDBz jRLPJMyumKfIGzpg246AhwDDHMIjP2/yK6/S6BrT5j05vSyr3//QJVpAiHAmIz6Enewu zynWBpnFVGdhsZl/gjjX9AC4a7EqFg0xINXOqC1xHMFVEdT+SEZH8rZpqFfP2Gxnx1L4 zQew== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=7qRMAv7CAh5HOzYBpQQNwIWdxPMEEkXjRDW/Hnn3LFw=; fh=mjwq4TDTDxMGxCZc+TWwotfBzIkagZBxJips9Smtivc=; b=ENopYM+OUykx61PN/JRQBRDE72N01OqJn5ugr6wVu1TcOC2gzsU4Bv9c6DJirGOZF5 Tr0H0ux94mIskjxexRVogAPPwhC43R9tAE5Dnv1cQrgDSbbEITX7bNNv9Y+kb/P5fHiL Hcc968I8pY/NAC93yog8EyvyZBA3J03lLd4a0IS1vbjAzgL3xeTqbPPqiyTlvSIOQTu7 LvMUo3t7J/FWJY+oNdKucS87SkcFrCU9a6kpBSeRl2DDuvV4dFsjZWv7Us9JwIE+NCHM lz2PS20xKfRDuNnY05ddjpZvYVmn5TFCQ7leKcokZ9GzzQMxziGBGjL5OduELuiod1DK Tk+g==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=AR7xh9ge; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67875-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67875-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id x64-20020a638643000000b005d8b61b753csi1882687pgd.186.2024.02.15.16.10.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:10:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67875-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=AR7xh9ge; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67875-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67875-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 213F928281A for ; Fri, 16 Feb 2024 00:09:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A3BD3DDA1; Fri, 16 Feb 2024 00:08:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="AR7xh9ge" Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FFF446B1 for ; Fri, 16 Feb 2024 00:08:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042128; cv=none; b=g9uAZxpLeDuZj/Sr4H5xsXN/09/F6yGbSX/4Z0Rrze5n9/hh/ZC5gUxJ2f+xuHKEyXS3VabVteTsT64ogln+JzXxVd4M45CWtOB135ir61kslUJq99Ov1kEV2bf0ApciY/CoK45puohHOSk3UEE7ffAFpW14xW8Cqj5RrHOjrCY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042128; c=relaxed/simple; bh=ZJBswraJW/qrj4dSIAF5uC568lbLLJSd36ev4jEQf9Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H+RTwLsyEOyMuw359LdOgLFsf5qTsfcFAi4glgIicKq7PEzSZjHDim0vgXi37nrqc1v5IthEuu4mbrvSGBRze7A7f0XhAMKpeXg1s1jyug9TkntviTJKllVBWYxh2ifwtOuAioLTsXcqEfvywzAEJkz2twUgx2KfPq/ip0yIelM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=AR7xh9ge; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-1d953fa3286so1040685ad.2 for ; Thu, 15 Feb 2024 16:08:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042124; x=1708646924; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7qRMAv7CAh5HOzYBpQQNwIWdxPMEEkXjRDW/Hnn3LFw=; b=AR7xh9geis2pn8cxNVmTX+viuMZdgYmY8GDiq9Ks1J6UrC+zRbWuXWijCmmNPU/7z+ afCktXhEdX4yEiZz3/z3uRsJ/Hl/127zQKZ7B4N4+J43IWpugG86H0Kz7pEk8ECYOYk6 n3VwDFD73xQmYg4KwMWISETOPPdsaM3bYR82oyJpNeaWVGjTvmhuguJxLoNKSRBEKsi4 HeX54DfIHOSDXjJmlICusXVmNueApsXfEPjp+6a4BuWQNr9BDZj7kMdIenNE9KqdNtFp nqYUGtt6qXNK+bQRX8FCkVNJxBTngj0oy7llBDi5CJNjFFp3gL+pbEofB0vx6iXOkjV6 U0hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042124; x=1708646924; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7qRMAv7CAh5HOzYBpQQNwIWdxPMEEkXjRDW/Hnn3LFw=; b=PBD8eK+3JDY5+bF3/+dRHJ4imb0YqKBKMjHy3HpzwzeTlFbx4uasJYQirPtgNXuocm K8I1JMZr/LUch5QpZxGQovEKebz+/XMwnvy72GZmLrzMLOrllsQvU3V5qPvE7htr3K0S 5ZuCJG2MQs5PV5l3sMec86A1SpAHlZc3HhKQgY1KHIZLjfr2NO1UrgNVpPewbcqTS8Iw Bq1gCkzl/YO456X0iZuW0H6rSWBnTtP4U3rZ8SQ+jcmVUPyQtriNlpIeI+/QVgkxwrxL wlv7B2Qz1zwRBvRwewKgf9/XFqFbB1kjSyFkAZL6Z5QIAtPeOgf5LXX2vyDXHljXhnJP x3rw== X-Forwarded-Encrypted: i=1; AJvYcCUxwuF5Y0XeLfp/5AwT3jz2z7Co1TV3/NXyRjNaMMfu4C05YTkCaEtQKvgdpAr+tGBN+XhECMf24umws/jPNkyE7YFVfLtBdsex2OBr X-Gm-Message-State: AOJu0Yzdu7RLGSeZjovYHYd0NZtjfd91y+X+A6KJ6kSg/hCdDptv8BT+ exTw9Yp+QyPkCrVFkYG6NPkYoORR7hKKwscDjl73qoaqF//7jtRR7DUlTHvGmQM= X-Received: by 2002:a17:903:904:b0:1db:a6b8:6b23 with SMTP id ll4-20020a170903090400b001dba6b86b23mr683294plb.27.1708042124375; Thu, 15 Feb 2024 16:08:44 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:43 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Samuel Holland Subject: [PATCH v1 2/6] drivers/perf: Add SiFive Composable Cache PMU driver Date: Thu, 15 Feb 2024 16:08:14 -0800 Message-ID: <20240216000837.1868917-3-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012079930275038 X-GMAIL-MSGID: 1791012079930275038 From: Eric Lin Add a driver for the PMU found in the SiFive Composable Cache controller. This PMU provides a configurable number of counters and a variety of events. Events are grouped into sets. Each counter can count events from only one set at a time; however, it can count any number of events within that set simultaneously. The PMU hardware does not provide an overflow interrupt or a way to atomically control groups of counters. Some events can be filtered further by client ID (e.g. CPU or external DMA master). That functionality is not supported by this driver. This driver further assumes that a single Composable Cache instance is shared by all CPUs in the system. Example usage: $ perf stat -a -e sifive_ccache_pmu/inner_acquire_block_btot/, sifive_ccache_pmu/inner_acquire_block_hit/, sifive_ccache_pmu/inner_acquire_block_ntob/ ls Performance counter stats for 'system wide': 542 sifive_ccache_pmu/inner_acquire_block_btot/ 22081 sifive_ccache_pmu/inner_acquire_block_hit/ 22006 sifive_ccache_pmu/inner_acquire_block_ntob/ 0.064672432 seconds time elapsed Example using numeric event selectors: $ perf stat -a -e sifive_ccache_pmu/event=0x10001/, sifive_ccache_pmu/event=0x2002/, sifive_ccache_pmu/event=0x4001/ ls Performance counter stats for 'system wide': 478 sifive_ccache_pmu/event=0x10001/ 4717 sifive_ccache_pmu/event=0x2002/ 44966 sifive_ccache_pmu/event=0x4001/ 0.111027326 seconds time elapsed Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- drivers/perf/Kconfig | 9 + drivers/perf/Makefile | 1 + drivers/perf/sifive_ccache_pmu.c | 577 +++++++++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 4 files changed, 588 insertions(+) create mode 100644 drivers/perf/sifive_ccache_pmu.c diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index ec6e0d9194a1..b4e4db7424b4 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -155,6 +155,15 @@ config QCOM_L3_PMU Adds the L3 cache PMU into the perf events subsystem for monitoring L3 cache events. +config SIFIVE_CCACHE_PMU + tristate "SiFive Composable Cache PMU" + depends on RISCV || COMPILE_TEST + help + Support for the Composable Cache performance monitoring unit (PMU) on + SiFive platforms. The Composable Cache PMU provides up to 64 counters + for measuring whole-system L2/L3 cache performance using the perf + events subsystem. + config THUNDERX2_PMU tristate "Cavium ThunderX2 SoC PMU UNCORE" depends on ARCH_THUNDER2 || COMPILE_TEST diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index a06338e3401c..51ef5f50ace4 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o obj-$(CONFIG_RISCV_PMU) += riscv_pmu.o obj-$(CONFIG_RISCV_PMU_LEGACY) += riscv_pmu_legacy.o obj-$(CONFIG_RISCV_PMU_SBI) += riscv_pmu_sbi.o +obj-$(CONFIG_SIFIVE_CCACHE_PMU) += sifive_ccache_pmu.o obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o diff --git a/drivers/perf/sifive_ccache_pmu.c b/drivers/perf/sifive_ccache_pmu.c new file mode 100644 index 000000000000..8c9ef0d09f48 --- /dev/null +++ b/drivers/perf/sifive_ccache_pmu.c @@ -0,0 +1,577 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SiFive Composable Cache PMU driver + * + * Copyright (C) 2022-2024 SiFive, Inc. + * Copyright (C) Eric Lin + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CCACHE_SELECT_OFFSET 0x2000 +#define CCACHE_CLIENT_FILTER_OFFSET 0x2800 +#define CCACHE_COUNTER_OFFSET 0x3000 + +#define CCACHE_PMU_MAX_COUNTERS 64 + +struct sifive_ccache_pmu { + struct pmu pmu; + struct hlist_node node; + struct notifier_block cpu_pm_nb; + void __iomem *base; + DECLARE_BITMAP(used_mask, CCACHE_PMU_MAX_COUNTERS); + unsigned int cpu; + int n_counters; + struct perf_event *events[] __counted_by(n_counters); +}; + +#define to_ccache_pmu(p) (container_of(p, struct sifive_ccache_pmu, pmu)) + +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64)readl(addr + 4)) << 32); +} +#endif + +#ifndef writeq +static inline void writeq(u64 v, void __iomem *addr) +{ + writel(lower_32_bits(v), addr); + writel(upper_32_bits(v), addr + 4); +} +#endif + +/* + * sysfs attributes + * + * We export: + * - cpumask, used by perf user space and other tools to know on which CPUs to create events + * - events, used by perf user space and other tools to create events symbolically, e.g.: + * perf stat -a -e sifive_ccache_pmu/event=inner_put_partial_data_hit/ ls + * perf stat -a -e sifive_ccache_pmu/event=0x101/ ls + * - formats, used by perf user space and other tools to configure events + */ + +/* cpumask */ +static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sifive_ccache_pmu *ccache_pmu = dev_get_drvdata(dev); + + if (ccache_pmu->cpu >= nr_cpu_ids) + return 0; + + return sysfs_emit(buf, "%d\n", ccache_pmu->cpu); +}; + +static DEVICE_ATTR_RO(cpumask); + +static struct attribute *sifive_ccache_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL, +}; + +static const struct attribute_group sifive_ccache_pmu_cpumask_group = { + .attrs = sifive_ccache_pmu_cpumask_attrs, +}; + +/* events */ +static ssize_t sifive_ccache_pmu_event_show(struct device *dev, struct device_attribute *attr, + char *page) +{ + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); + return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id); +} + +#define SET_EVENT_SELECT(_event, _set) (BIT_ULL((_event) + 8) | (_set)) +#define CCACHE_PMU_EVENT_ATTR(_name, _event, _set) \ + PMU_EVENT_ATTR_ID(_name, sifive_ccache_pmu_event_show, SET_EVENT_SELECT(_event, _set)) + +enum ccache_pmu_event_set1 { + INNER_PUT_FULL_DATA = 0, + INNER_PUT_PARTIAL_DATA, + INNER_ATOMIC_DATA, + INNER_GET, + INNER_PREFETCH_READ, + INNER_PREFETCH_WRITE, + INNER_ACQUIRE_BLOCK_NTOB, + INNER_ACQUIRE_BLOCK_NTOT, + INNER_ACQUIRE_BLOCK_BTOT, + INNER_ACQUIRE_PERM_NTOT, + INNER_ACQUIRE_PERM_BTOT, + INNER_RELEASE_TTOB, + INNER_RELEASE_TTON, + INNER_RELEASE_BTON, + INNER_RELEASE_DATA_TTOB, + INNER_RELEASE_DATA_TTON, + INNER_RELEASE_DATA_BTON, + OUTER_PROBE_BLOCK_TOT, + OUTER_PROBE_BLOCK_TOB, + OUTER_PROBE_BLOCK_TON, + CCACHE_PMU_MAX_EVENT1_IDX +}; + +enum ccache_pmu_event_set2 { + INNER_PUT_FULL_DATA_HIT = 0, + INNER_PUT_PARTIAL_DATA_HIT, + INNER_ATOMIC_DATA_HIT, + INNER_GET_HIT, + INNER_PREFETCH_HIT, + INNER_ACQUIRE_BLOCK_HIT, + INNER_ACQUIRE_PERM_HIT, + INNER_RELEASE_HIT, + INNER_RELEASE_DATA_HIT, + OUTER_PROBE_HIT, + INNER_PUT_FULL_DATA_HIT_SHARED, + INNER_PUT_PARTIAL_DATA_HIT_SHARED, + INNER_ATOMIC_DATA_HIT_SHARED, + INNER_GET_HIT_SHARED, + INNER_PREFETCH_HIT_SHARED, + INNER_ACQUIRE_BLOCK_HIT_SHARED, + INNER_ACQUIRE_PERM_HIT_SHARED, + OUTER_PROBE_HIT_SHARED, + OUTER_PROBE_HIT_DIRTY, + CCACHE_PMU_MAX_EVENT2_IDX +}; + +enum ccache_pmu_event_set3 { + OUTER_ACQUIRE_BLOCK_NTOB_MISS = 0, + OUTER_ACQUIRE_BLOCK_NTOT_MISS, + OUTER_ACQUIRE_BLOCK_BTOT_MISS, + OUTER_ACQUIRE_PERM_NTOT_MISS, + OUTER_ACQUIRE_PERM_BTOT_MISS, + OUTER_RELEASE_TTOB_EVICTION, + OUTER_RELEASE_TTON_EVICTION, + OUTER_RELEASE_BTON_EVICTION, + OUTER_RELEASE_DATA_TTOB_NOT_APPLICABLE, + OUTER_RELEASE_DATA_TTON_DIRTY_EVICTION, + OUTER_RELEASE_DATA_BTON_NOT_APPLICABLE, + INNER_PROBE_BLOCK_TOT_CODE_MISS_HITS_OTHER_HARTS, + INNER_PROBE_BLOCK_TOB_LOAD_MISS_HITS_OTHER_HARTS, + INNER_PROBE_BLOCK_TON_STORE_MISS_HITS_OTHER_HARTS, + CCACHE_PMU_MAX_EVENT3_IDX +}; + +enum ccache_pmu_event_set4 { + INNER_HINT_HITS_INFLIGHT_MISS = 0, + CCACHE_PMU_MAX_EVENT4_IDX +}; + +static struct attribute *sifive_ccache_pmu_events[] = { + /* pmEventSelect1 */ + CCACHE_PMU_EVENT_ATTR(inner_put_full_data, INNER_PUT_FULL_DATA, 1), + CCACHE_PMU_EVENT_ATTR(inner_put_partial_data, INNER_PUT_PARTIAL_DATA, 1), + CCACHE_PMU_EVENT_ATTR(inner_atomic_data, INNER_ATOMIC_DATA, 1), + CCACHE_PMU_EVENT_ATTR(inner_get, INNER_GET, 1), + CCACHE_PMU_EVENT_ATTR(inner_prefetch_read, INNER_PREFETCH_READ, 1), + CCACHE_PMU_EVENT_ATTR(inner_prefetch_write, INNER_PREFETCH_WRITE, 1), + CCACHE_PMU_EVENT_ATTR(inner_acquire_block_ntob, INNER_ACQUIRE_BLOCK_NTOB, 1), + CCACHE_PMU_EVENT_ATTR(inner_acquire_block_ntot, INNER_ACQUIRE_BLOCK_NTOT, 1), + CCACHE_PMU_EVENT_ATTR(inner_acquire_block_btot, INNER_ACQUIRE_BLOCK_BTOT, 1), + CCACHE_PMU_EVENT_ATTR(inner_acquire_perm_ntot, INNER_ACQUIRE_PERM_NTOT, 1), + CCACHE_PMU_EVENT_ATTR(inner_acquire_perm_btot, INNER_ACQUIRE_PERM_BTOT, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_ttob, INNER_RELEASE_TTOB, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_tton, INNER_RELEASE_TTON, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_bton, INNER_RELEASE_BTON, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_data_ttob, INNER_RELEASE_DATA_TTOB, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_data_tton, INNER_RELEASE_DATA_TTON, 1), + CCACHE_PMU_EVENT_ATTR(inner_release_data_bton, INNER_RELEASE_DATA_BTON, 1), + CCACHE_PMU_EVENT_ATTR(outer_probe_block_tot, OUTER_PROBE_BLOCK_TOT, 1), + CCACHE_PMU_EVENT_ATTR(outer_probe_block_tob, OUTER_PROBE_BLOCK_TOB, 1), + CCACHE_PMU_EVENT_ATTR(outer_probe_block_ton, OUTER_PROBE_BLOCK_TON, 1), + + /* pmEventSelect2 */ + CCACHE_PMU_EVENT_ATTR(inner_put_full_data_hit, INNER_PUT_FULL_DATA_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_put_partial_data_hit, INNER_PUT_PARTIAL_DATA_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_atomic_data_hit, INNER_ATOMIC_DATA_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_get_hit, INNER_GET_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_prefetch_hit, INNER_PREFETCH_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_acquire_block_hit, INNER_ACQUIRE_BLOCK_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_acquire_perm_hit, INNER_ACQUIRE_PERM_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_release_hit, INNER_RELEASE_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_release_data_hit, INNER_RELEASE_DATA_HIT, 2), + CCACHE_PMU_EVENT_ATTR(outer_probe_hit, OUTER_PROBE_HIT, 2), + CCACHE_PMU_EVENT_ATTR(inner_put_full_data_hit_shared, INNER_PUT_FULL_DATA_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_put_partial_data_hit_shared, + INNER_PUT_PARTIAL_DATA_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_atomic_data_hit_shared, INNER_ATOMIC_DATA_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_get_hit_shared, INNER_GET_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_prefetch_hit_shared, INNER_PREFETCH_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_acquire_block_hit_shared, INNER_ACQUIRE_BLOCK_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(inner_acquire_perm_hit_shared, INNER_ACQUIRE_PERM_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(outer_probe_hit_shared, OUTER_PROBE_HIT_SHARED, 2), + CCACHE_PMU_EVENT_ATTR(outer_probe_hit_dirty, OUTER_PROBE_HIT_DIRTY, 2), + + /* pmEventSelect3 */ + CCACHE_PMU_EVENT_ATTR(outer_acquire_block_ntob_miss, OUTER_ACQUIRE_BLOCK_NTOB_MISS, 3), + CCACHE_PMU_EVENT_ATTR(outer_acquire_block_ntot_miss, OUTER_ACQUIRE_BLOCK_NTOT_MISS, 3), + CCACHE_PMU_EVENT_ATTR(outer_acquire_block_btot_miss, OUTER_ACQUIRE_BLOCK_BTOT_MISS, 3), + CCACHE_PMU_EVENT_ATTR(outer_acquire_perm_ntot_miss, OUTER_ACQUIRE_PERM_NTOT_MISS, 3), + CCACHE_PMU_EVENT_ATTR(outer_acquire_perm_btot_miss, OUTER_ACQUIRE_PERM_BTOT_MISS, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_ttob_eviction, OUTER_RELEASE_TTOB_EVICTION, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_tton_eviction, OUTER_RELEASE_TTON_EVICTION, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_bton_eviction, OUTER_RELEASE_BTON_EVICTION, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_data_ttob_not_applicable, + OUTER_RELEASE_DATA_TTOB_NOT_APPLICABLE, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_data_tton_dirty_eviction, + OUTER_RELEASE_DATA_TTON_DIRTY_EVICTION, 3), + CCACHE_PMU_EVENT_ATTR(outer_release_data_bton_not_applicable, + OUTER_RELEASE_DATA_BTON_NOT_APPLICABLE, 3), + CCACHE_PMU_EVENT_ATTR(inner_probe_block_tot_code_miss_hits_other_harts, + INNER_PROBE_BLOCK_TOT_CODE_MISS_HITS_OTHER_HARTS, 3), + CCACHE_PMU_EVENT_ATTR(inner_probe_block_tob_load_miss_hits_other_harts, + INNER_PROBE_BLOCK_TOB_LOAD_MISS_HITS_OTHER_HARTS, 3), + CCACHE_PMU_EVENT_ATTR(inner_probe_block_ton_store_miss_hits_other_harts, + INNER_PROBE_BLOCK_TON_STORE_MISS_HITS_OTHER_HARTS, 3), + + /* pm_event_select4 */ + CCACHE_PMU_EVENT_ATTR(inner_hint_hits_inflight_miss, INNER_HINT_HITS_INFLIGHT_MISS, 4), + NULL +}; + +static struct attribute_group sifive_ccache_pmu_events_group = { + .name = "events", + .attrs = sifive_ccache_pmu_events, +}; + +/* formats */ +PMU_FORMAT_ATTR(event, "config:0-63"); + +static struct attribute *sifive_ccache_pmu_formats[] = { + &format_attr_event.attr, + NULL, +}; + +static struct attribute_group sifive_ccache_pmu_format_group = { + .name = "format", + .attrs = sifive_ccache_pmu_formats, +}; + +/* + * Per PMU device attribute groups + */ + +static const struct attribute_group *sifive_ccache_pmu_attr_grps[] = { + &sifive_ccache_pmu_cpumask_group, + &sifive_ccache_pmu_events_group, + &sifive_ccache_pmu_format_group, + NULL, +}; + +/* + * Event Initialization + */ + +static int sifive_ccache_pmu_event_init(struct perf_event *event) +{ + struct sifive_ccache_pmu *ccache_pmu = to_ccache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 config = event->attr.config; + u64 ev_type = config >> 8; + u64 set = config & 0xff; + + /* Check if this is a valid set and event */ + switch (set) { + case 1: + if (ev_type >= BIT_ULL(CCACHE_PMU_MAX_EVENT1_IDX)) + return -ENOENT; + break; + case 2: + if (ev_type >= BIT_ULL(CCACHE_PMU_MAX_EVENT2_IDX)) + return -ENOENT; + break; + case 3: + if (ev_type >= BIT_ULL(CCACHE_PMU_MAX_EVENT3_IDX)) + return -ENOENT; + break; + case 4: + if (ev_type >= BIT_ULL(CCACHE_PMU_MAX_EVENT4_IDX)) + return -ENOENT; + break; + default: + return -ENOENT; + } + + /* Do not allocate the hardware counter yet */ + hwc->idx = -1; + hwc->config = config; + + event->cpu = ccache_pmu->cpu; + + return 0; +} + +/* + * pmu->read: read and update the counter + */ +static void sifive_ccache_pmu_read(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 prev_raw_count, new_raw_count; + u64 oldval; + + do { + prev_raw_count = local64_read(&hwc->prev_count); + new_raw_count = readq((void *)hwc->event_base); + + oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count); + } while (oldval != prev_raw_count); + + local64_add(new_raw_count - prev_raw_count, &event->count); +} + +/* + * State transition functions: + * + * start()/stop() & add()/del() + */ + +/* + * pmu->start: start the event + */ +static void sifive_ccache_pmu_start(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + hwc->state = 0; + + /* Set initial value to 0 */ + local64_set(&hwc->prev_count, 0); + writeq(0, (void *)hwc->event_base); + + /* Enable this counter to count events */ + writeq(hwc->config, (void *)hwc->config_base); +} + +/* + * pmu->stop: stop the counter + */ +static void sifive_ccache_pmu_stop(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (hwc->state & PERF_HES_STOPPED) + return; + + /* Disable this counter to count events */ + writeq(0, (void *)hwc->config_base); + sifive_ccache_pmu_read(event); + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; +} + +/* + * pmu->add: add the event to the PMU + */ +static int sifive_ccache_pmu_add(struct perf_event *event, int flags) +{ + struct sifive_ccache_pmu *ccache_pmu = to_ccache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx; + + /* Find an available counter idx to use for this event */ + do { + idx = find_first_zero_bit(ccache_pmu->used_mask, ccache_pmu->n_counters); + if (idx >= ccache_pmu->n_counters) + return -EAGAIN; + } while (test_and_set_bit(idx, ccache_pmu->used_mask)); + + hwc->config_base = (unsigned long)ccache_pmu->base + CCACHE_SELECT_OFFSET + 8 * idx; + hwc->event_base = (unsigned long)ccache_pmu->base + CCACHE_COUNTER_OFFSET + 8 * idx; + hwc->idx = idx; + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + ccache_pmu->events[idx] = event; + + if (flags & PERF_EF_START) + sifive_ccache_pmu_start(event, PERF_EF_RELOAD); + + perf_event_update_userpage(event); + + return 0; +} + +/* + * pmu->del: delete the event from the PMU + */ +static void sifive_ccache_pmu_del(struct perf_event *event, int flags) +{ + struct sifive_ccache_pmu *ccache_pmu = to_ccache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + /* Stop and release this counter */ + sifive_ccache_pmu_stop(event, PERF_EF_UPDATE); + + ccache_pmu->events[idx] = NULL; + clear_bit(idx, ccache_pmu->used_mask); + + perf_event_update_userpage(event); +} + +/* + * Driver initialization + */ + +static void sifive_ccache_pmu_hw_init(const struct sifive_ccache_pmu *ccache_pmu) +{ + /* Disable the client filter (not supported by this driver) */ + writeq(0, ccache_pmu->base + CCACHE_CLIENT_FILTER_OFFSET); +} + +static int sifive_ccache_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct sifive_ccache_pmu *ccache_pmu = + hlist_entry_safe(node, struct sifive_ccache_pmu, node); + + if (ccache_pmu->cpu >= nr_cpu_ids) + ccache_pmu->cpu = cpu; + + return 0; +} + +static int sifive_ccache_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct sifive_ccache_pmu *ccache_pmu = + hlist_entry_safe(node, struct sifive_ccache_pmu, node); + + /* Do nothing if this CPU does not own the events */ + if (cpu != ccache_pmu->cpu) + return 0; + + /* Pick a random online CPU */ + ccache_pmu->cpu = cpumask_any_but(cpu_online_mask, cpu); + if (ccache_pmu->cpu >= nr_cpu_ids) + return 0; + + /* Migrate PMU events from this CPU to the target CPU */ + perf_pmu_migrate_context(&ccache_pmu->pmu, cpu, ccache_pmu->cpu); + + return 0; +} + +static int sifive_ccache_pmu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sifive_ccache_pmu *ccache_pmu; + u32 n_counters; + int ret; + + /* Instances without a sifive,perfmon-counters property do not contain a PMU */ + ret = device_property_read_u32(dev, "sifive,perfmon-counters", &n_counters); + if (ret || !n_counters) + return -ENODEV; + + ccache_pmu = devm_kzalloc(dev, struct_size(ccache_pmu, events, n_counters), GFP_KERNEL); + if (!ccache_pmu) + return -ENOMEM; + + platform_set_drvdata(pdev, ccache_pmu); + + ccache_pmu->pmu = (struct pmu) { + .parent = dev, + .attr_groups = sifive_ccache_pmu_attr_grps, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, + .task_ctx_nr = perf_invalid_context, + .event_init = sifive_ccache_pmu_event_init, + .add = sifive_ccache_pmu_add, + .del = sifive_ccache_pmu_del, + .start = sifive_ccache_pmu_start, + .stop = sifive_ccache_pmu_stop, + .read = sifive_ccache_pmu_read, + }; + ccache_pmu->cpu = nr_cpu_ids; + ccache_pmu->n_counters = n_counters; + + ccache_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ccache_pmu->base)) + return PTR_ERR(ccache_pmu->base); + + sifive_ccache_pmu_hw_init(ccache_pmu); + + ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, &ccache_pmu->node); + if (ret) + return dev_err_probe(dev, ret, "Failed to add CPU hotplug instance\n"); + + ret = perf_pmu_register(&ccache_pmu->pmu, "sifive_ccache_pmu", -1); + if (ret) { + dev_err_probe(dev, ret, "Failed to register PMU\n"); + goto err_remove_instance; + } + + return 0; + +err_remove_instance: + cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, &ccache_pmu->node); + + return ret; +} + +static void sifive_ccache_pmu_remove(struct platform_device *pdev) +{ + struct sifive_ccache_pmu *ccache_pmu = platform_get_drvdata(pdev); + + perf_pmu_unregister(&ccache_pmu->pmu); + cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, &ccache_pmu->node); +} + +static const struct of_device_id sifive_ccache_pmu_of_match[] = { + { .compatible = "sifive,ccache0" }, + {} +}; +MODULE_DEVICE_TABLE(of, sifive_ccache_pmu_of_match); + +static struct platform_driver sifive_ccache_pmu_driver = { + .probe = sifive_ccache_pmu_probe, + .remove_new = sifive_ccache_pmu_remove, + .driver = { + .name = "sifive_ccache_pmu", + .of_match_table = sifive_ccache_pmu_of_match, + }, +}; + +static void __exit sifive_ccache_pmu_exit(void) +{ + platform_driver_unregister(&sifive_ccache_pmu_driver); + cpuhp_remove_multi_state(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE); +} +module_exit(sifive_ccache_pmu_exit); + +static int __init sifive_ccache_pmu_init(void) +{ + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, + "perf/sifive/ccache:online", + sifive_ccache_pmu_online_cpu, + sifive_ccache_pmu_offline_cpu); + if (ret) + return ret; + + ret = platform_driver_register(&sifive_ccache_pmu_driver); + if (ret) + goto err_remove_state; + + return 0; + +err_remove_state: + cpuhp_remove_multi_state(CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE); + + return ret; +} +module_init(sifive_ccache_pmu_init); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 172d0a743e5d..be6361fdc8ba 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -230,6 +230,7 @@ enum cpuhp_state { CPUHP_AP_PERF_POWERPC_TRACE_IMC_ONLINE, CPUHP_AP_PERF_POWERPC_HV_24x7_ONLINE, CPUHP_AP_PERF_POWERPC_HV_GPCI_ONLINE, + CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, CPUHP_AP_PERF_CSKY_ONLINE, CPUHP_AP_WATCHDOG_ONLINE, CPUHP_AP_WORKQUEUE_ONLINE, From patchwork Fri Feb 16 00:08:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201850 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201447dyb; Thu, 15 Feb 2024 16:09:33 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCV4SPoKOIPM4roC9esJ7fgJcygzXWr2RW+g7XUf4Bat8iM76tw9BE0zq+OXKcDX/betFGc0l9vSU0BfW1fHaS9G2k9RIQ== X-Google-Smtp-Source: AGHT+IFu/i1yKuWFJZjrsF3VIZqGylZzlAmuXJb9nPIZn0PtK+vOmuZPLOi8lWy9Fjr4SMYhHXX6 X-Received: by 2002:a05:6102:2f4:b0:46d:498b:b66a with SMTP id j20-20020a05610202f400b0046d498bb66amr3876197vsj.20.1708042172906; Thu, 15 Feb 2024 16:09:32 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042172; cv=pass; d=google.com; s=arc-20160816; b=iiHkebQxP5ARPZSPUQQNz2Teq/CI6/h26acvq7chQK5xo6znxEi0pAMprx9SAWCmOu UKSa6pfjmz8e2XhMbBiv3pnmTfyT2rSti8se/fTJcKAHBLWPfSyvTXmULAsyec7KAz+o 2jV6BM47LLs5Uz1gJOKXPk0dG0JorDgFky++4H83hBDPUCKnC75bW6/PHbQLxxFSLyV1 ju/mKK+ud12InN37hH4ez44FjrxgXKoKf5c2TkAkyfVu/xWNVNMjEtyUrFQ09R0S/fWR pkVw3UZqUh4IQad3M6fUCDUVVbs3R2yG4cz/vO21jKnjtZ2vZvzKUnnfVcuNeUyidtmb 8b/A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=bVhGY5w5frFGTLRRHW7GA0aZ7SPA+FA1JdXFhjNvDZY=; fh=SOZa9derrRQVZCIF8oNW/gTts6JxxSbmS11wBl9lmKU=; b=sG2bRiOGm6iMVTEc07cAUajDDeAKN33eCk8SHfgREQoVmI8R88vgfLt934VFoFpJEB MlsGN+FkXmmISzN2O427MTftSyZHohaqZCsekYVUN78Qffpby2KYs7j06EuToTBxPHTJ XZOAce3gR1E3iP1m1eRrs7ya7ROiS2eGg5Zd7FCJMBWm29UF7qtLqxo55i3XK6GV51yE ryFIm4HYWs01V7LptbtoPtE7fIYBKsbsVrsAsNZcd8Jxo+jqNm/w+ChNNQrgQ89EGB90 t41Ikl+g6c+OVOd+p5x/xL+gIGv+jvRzEWbi2mZsd+9lF5K5WXyYNpL8fxNeACd++Nw8 jKFg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=hzvLQAKa; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67876-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67876-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id q9-20020ac87349000000b0042c7c6f098asi2513680qtp.658.2024.02.15.16.09.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:09:32 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67876-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=hzvLQAKa; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67876-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67876-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id A2BED1C2335E for ; Fri, 16 Feb 2024 00:09:32 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BE028149DED; Fri, 16 Feb 2024 00:08:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="hzvLQAKa" Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D102E8F5B for ; Fri, 16 Feb 2024 00:08:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042129; cv=none; b=DGPRwHAvC5MzVHbtoGA2kWbx4Dn6xRI9iuXX3BRovrlv0C+F4h+roj/ftuC8VcJwTSAGUt9vWdw3ySam7ptvXwnxrcCWcdxGzKX859S8PTdqpAVdk3Q70HSJTxKHle0KHGEIPCUHV1MEV/sGi91CYQTuvYDGBHYGu/oEoRo/FPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042129; c=relaxed/simple; bh=dtTFKiZ7Yo5CM4o5MTgSlED094NZOrlqY9/8Q2KAKdU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=clkhwu+0f/xukbf9mR4DXZ07L21jPaYMzOa3HAZQFu4iIclayASlrI4PmsKZ2EjC6YPzC7DDzTGCdrHrYePacx8dGQmWhYs5ab3tAWKXWpdsr6WKzBEnE+Q4sKqc9KtV7UIOPX22filsGF36STeX3KpYq0Ov9YgHqmE3SGjYQbo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=hzvLQAKa; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-1db4cafbbebso9662365ad.3 for ; Thu, 15 Feb 2024 16:08:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042127; x=1708646927; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bVhGY5w5frFGTLRRHW7GA0aZ7SPA+FA1JdXFhjNvDZY=; b=hzvLQAKaAL12zH/UzEK/PV0mlkXwLfLjUfcmn5cGHF5L9J5T03vWh+Tzm05zDorGua SeRqsvrVaubJE6xO6uM/SSDuIAcva2cvZaKgs4TT1nHcLPohNvbVTPL+SBqoVk+wr9Fi vnPRpy742ErwPlmjxmQQ7IL4XYRtnJ9gsyvqWZemhUo+i7dyS9TLZtODiARq/tagkOyB TvPQyD32nC9vbi6rGpQ0V6fG15EgAxrDyHw+dT3s5W6AuQcLrdH6VtA5h0xhgj2nlD0O 0xWjk+nYm2R8cJYErkk7IXNw+5/m9jKq02gpuztkqu8mt7lR+NH+5ru+L5TSbZ2eOkl3 PIug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042127; x=1708646927; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bVhGY5w5frFGTLRRHW7GA0aZ7SPA+FA1JdXFhjNvDZY=; b=Bq89J2/uXqM4biJtO5x1tw/iERU3cTkagAAFQBpDzWOlktAIRmqbEhs9SHvdz1BVg3 t954CH0bmvCzwFTT4KzYYasxBd0Fd1yU0xxqv3EzJS8ESfjq5VkuUWBCPFRKstjCHxcm JTgu3CnTLS1FDtVrE9+97QVxJiDQCYz5Zma1MDZT/y+3NeonuNgWbTV8iV4IqyVRDVRY 8N5A28QGqSszoiJAODUrLX7hb78L2O+qSoPru99shBi/m6cOf/KWPvD/IefOxUb+8+te 6b3TA5s+NRcDd3ldByuDONZyp3ks9LpbJNRUVcdiXZtLPtazDrelmaL74zSzo+tQ7d1U U9IA== X-Forwarded-Encrypted: i=1; AJvYcCWGzC6rqYo9+VAtpu0888D7EYqOU1R9db5FfdQi3C9DOs5aCKPccHL1rpjJVsC9heqx14ty500x5jp7uTsEumfxLhLvLFvdf4gG9K5X X-Gm-Message-State: AOJu0YxTqFkiy5Nr1WWDOgVHuS9EfeSNtmKdF+OJ3rKAbIWdknT5nsBg bQ7O4wM3FdUcfnro7cYVNYBHjrUe3O7JAW62zw7cN8oGefF8Wja6o0/SaKil7OI= X-Received: by 2002:a17:902:d48b:b0:1db:8181:9d04 with SMTP id c11-20020a170902d48b00b001db81819d04mr3724031plg.38.1708042127232; Thu, 15 Feb 2024 16:08:47 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:45 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Samuel Holland Subject: [PATCH v1 3/6] dt-bindings: cache: Add SiFive Extensible Cache controller Date: Thu, 15 Feb 2024 16:08:15 -0800 Message-ID: <20240216000837.1868917-4-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012029091980405 X-GMAIL-MSGID: 1791012029091980405 From: Eric Lin Add YAML DT binding documentation for the SiFive Extensible Cache controller. The Extensible Cache controller interleaves cache blocks across a number of heterogeneous independently-programmed slices. Each slice contains an MMIO interface for configuration, cache maintenance, error reporting, and performance monitoring. Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- .../cache/sifive,extensiblecache0.yaml | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Documentation/devicetree/bindings/cache/sifive,extensiblecache0.yaml diff --git a/Documentation/devicetree/bindings/cache/sifive,extensiblecache0.yaml b/Documentation/devicetree/bindings/cache/sifive,extensiblecache0.yaml new file mode 100644 index 000000000000..d027114dbdba --- /dev/null +++ b/Documentation/devicetree/bindings/cache/sifive,extensiblecache0.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (C) 2023-2024 SiFive, Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/cache/sifive,extensiblecache0.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SiFive Extensible Cache Controller + +maintainers: + - Eric Lin + +description: + The SiFive Extensible Cache Controller provides a high-performance extensible + system (L2 or L3) cache. It is divided into several independent heterogeneous + slices, enabling a flexible topology and physical design. + +allOf: + - $ref: /schemas/cache-controller.yaml# + +select: + properties: + compatible: + contains: + enum: + - sifive,extensiblecache0 + + required: + - compatible + +properties: + compatible: + items: + - const: sifive,extensiblecache0 + - const: cache + + "#address-cells": true + "#size-cells": true + ranges: true + + interrupts: + maxItems: 1 + + cache-block-size: + const: 64 + + cache-level: true + cache-sets: true + cache-size: true + cache-unified: true + +patternProperties: + "^cache-controller@[0-9a-f]+$": + type: object + additionalProperties: false + properties: + reg: + maxItems: 1 + + cache-block-size: + const: 64 + + cache-sets: true + cache-size: true + cache-unified: true + + sifive,bm-event-counters: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: Number of bucket monitor registers in this slice + + sifive,cache-ways: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Number of ways in this slice (independent of cache size) + + sifive,perfmon-counters: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: Number of PMU counter registers in this slice + + required: + - reg + - cache-block-size + - cache-sets + - cache-size + - cache-unified + - sifive,cache-ways + +required: + - compatible + - ranges + - interrupts + - cache-block-size + - cache-level + - cache-sets + - cache-size + - cache-unified + +additionalProperties: false + +examples: + - | + cache-controller@30040000 { + compatible = "sifive,extensiblecache0", "cache"; + ranges = <0x30040000 0x30040000 0x10000>; + interrupts = <0x4>; + cache-block-size = <0x40>; + cache-level = <3>; + cache-sets = <0x800>; + cache-size = <0x100000>; + cache-unified; + #address-cells = <1>; + #size-cells = <1>; + + cache-controller@30040000 { + reg = <0x30040000 0x4000>; + cache-block-size = <0x40>; + cache-sets = <0x400>; + cache-size = <0x80000>; + cache-unified; + sifive,bm-event-counters = <8>; + sifive,cache-ways = <9>; + sifive,perfmon-counters = <8>; + }; + + cache-controller@30044000 { + reg = <0x30044000 0x4000>; + cache-block-size = <0x40>; + cache-sets = <0x400>; + cache-size = <0x80000>; + cache-unified; + sifive,bm-event-counters = <8>; + sifive,cache-ways = <9>; + sifive,perfmon-counters = <8>; + }; + }; From patchwork Fri Feb 16 00:08:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201854 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201903dyb; Thu, 15 Feb 2024 16:10:40 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWpQTDKrLRLqaMTe2zhN+Szl/wsRls9Yt4FmRhzObTFPOuY/d56fewze7mbsOApbh5rRAjEJL4QMN8Dya87tYyxZT2DNw== X-Google-Smtp-Source: AGHT+IE0iVhrw1wm27dA5Jd+Pmta5eQ9OLV0duTEW1GZhHoBVOaJWmURrXISTMKusHuN2g7653P/ X-Received: by 2002:a05:6a20:9f98:b0:19e:ca3a:612b with SMTP id mm24-20020a056a209f9800b0019eca3a612bmr4040089pzb.54.1708042240632; Thu, 15 Feb 2024 16:10:40 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042240; cv=pass; d=google.com; s=arc-20160816; b=xSr7+aoRKoPgO05FxW24nYBzHblRtBJ1/WHVT979/9R6kihVILaMrq1bdiEiIyMgWV v7jcy47A7A+sE0fg7iasq1KUU2+RKBvJViyHIo2kdkQcqeG1zJWuqWi+UkwS/n0fykqM CQLz1HPNFYE7NOxh55S2PElcsx9tDUvbCupgCkh4h+76MWmVjX2o1q/5eacsfKFC6fLD 8cmcPEma7UE2lULIPZ7yteYN0Vv3bjRCq0xjGjffaQyVYrK7sfhWVH2vrYL03FOPpyOM gHlYVFKX527DzjmXO0PIQJ4z6m9QaLeAlsHJcjKEvZ60VlrILh+tJ5wIkUx6sjH7XIZB ji1A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=97Vl//GERs+wHDqqFSQvA7qG8VAex8iXqN6MPz7a8Ck=; fh=iVremFqbMWqTrrdQjJJuX+U73tSpq+Q60sCRbLDZdCg=; b=vHpVg7OzMCrEps9NsNvHN19pomIHojYsgcfb6c016g7XVCVWOG/3WtuwLp+4hEeE41 t6U0bDtMhoGJ5PXfjxk0sVrRRGfkJxXAvRE1jCd4Ux9En41+1XCrqAqEoa+nRfPUcsYB gJlGDqtPTS9hOIY+MSIb+U47lrRMfuPJwEDzIOoCW5XG6+gvUomyrEduAWBRy4e4vKEQ b+oIypmpIHD4E81A42RjdtynmUlb1e3QO0QYHyVGx+1HOOr1+XTx2uKhT+nHmuHwd49g 9j3ILI+/YxAiRASbqUPwVhEUmZZCC8no7BaJn27zAVia+aOpXzdYcdye9jkvnjEWJWy0 rYhw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=bak94Cr+; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67877-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67877-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id b6-20020a170903228600b001d8edfe3a27si1938320plh.163.2024.02.15.16.10.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:10:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67877-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=bak94Cr+; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67877-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67877-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id BCCC028772B for ; Fri, 16 Feb 2024 00:10:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B1A0CEEAC; Fri, 16 Feb 2024 00:09:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="bak94Cr+" Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A27F1946F for ; Fri, 16 Feb 2024 00:08:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042133; cv=none; b=P/T722mCxLLalc5x7JdlS8C97cyPNUkjVwFkFt7+PKX4dJN0xvvkouL8NhH9ZnlT44Z5MUB2F9AwlK8TlCp7FYX3T6+YnA/UvWMGA8zqU0VQGH+86UgGUJqrx9B0bWLausYrlt7zTbh+WAjH6UA1M8NAxMVYLiaLeO3X5hyoZW8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042133; c=relaxed/simple; bh=8VSz8YhXCzbdmH6lcJ0g9fYzRT+znl2jSP343uwb5Vg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=alObSoSScStqyjtd/h/vTVqR6J8ma6u7XWT8zxMzv0vFxcv9jb6Mn8/PzbZCAFMwIsLYu4hRqbOJZ1SGNnqUyKV6upBawRWofxqBYOfro5+wz0S5RM3ugshjpEu7AwZVnDXvIVjW9tkGNJR66OzsqD8V4cNoOHj8KYViq3ej5xM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=bak94Cr+; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-1d780a392fdso1301725ad.3 for ; Thu, 15 Feb 2024 16:08:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042130; x=1708646930; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=97Vl//GERs+wHDqqFSQvA7qG8VAex8iXqN6MPz7a8Ck=; b=bak94Cr+9m27sXnJFE7F8kwdW2D69B0F2dlY1FdiKsGZsVY8OQFMBHbwrfU5tSWHf+ RY/ZNCR1M431Sq6pFZntOAhUHHKtQO2vZrC5ESOe5Iq+xZtVCZiboHH9oz3W+lqtjjg9 e1TylvH0ZzqaosfpkVsBtDdmsNEiPbZd6AIqgxApcTfiKDArMfxUiDUGaUGLtv+tBe5f fUAGoRXvVmASOy5MKjXx4WaPEKSjDv7qCVc/wBal9gA0m3zEaxhyEPlwvVcxuU5yOdy4 QdRiMuyOgBlqMRooJs5s8/5Y6mJSUYdgFAaEV8WXRKt+KXwur1i/m5vJIimmFjfpoRzs zYEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042130; x=1708646930; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=97Vl//GERs+wHDqqFSQvA7qG8VAex8iXqN6MPz7a8Ck=; b=O0EUjHNYVNjO3hn4P0EokwBHKWRv6HQZsfDQkn+RehriKyWQ4lUIC9XfdC9o1Wwe0z WoR8bizcK4u8+zDpktgAkzEdN7yY6mBHIOm6sjEIlLuBtJ/aduLh+/mejA4Yg+vXXekg cgyX4Ng0MTpmDjl0CY388LaVGYF06YkoyE6N+ov+og96jk+KjUM0JLUoW7G9RL5qy3Wf NdbizHPD3I3vnwG+obYtN1Cwpx3kasbJ362bvNgPWw+9eBeRpg0sEnsDY5qi27f+9Ya5 LrSA32N6TmPmTE1Rv0OMvoulcekfTmmFFUZ6W6Sg7jOCJ7BeBUq7m3F3DydQBq/rlHSK XTlw== X-Forwarded-Encrypted: i=1; AJvYcCVX1vC/ZSgk5N9ImOuzOihAPWwDvRfZgOFdPZwfTFgn6BDHNogXuyVyOm/3W3FqZH2jICd43Ypiadhkav8OgqdTVrAS+SGAFyLC3pZh X-Gm-Message-State: AOJu0YyaBcUrUcChgdDS2FV4McnUjB6UiVfPsLxCeV7VSyl1zsW4CAIQ GFq+8VKHZqCyJ4fBgFuZSJpWaVeK71kz78it/VT5j9jCPGUTbYgkPocfZNtldEg= X-Received: by 2002:a17:903:443:b0:1db:a54b:acaf with SMTP id iw3-20020a170903044300b001dba54bacafmr558755plb.39.1708042129975; Thu, 15 Feb 2024 16:08:49 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:48 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Samuel Holland Subject: [PATCH v1 4/6] drivers/perf: Add SiFive Extensible Cache PMU driver Date: Thu, 15 Feb 2024 16:08:16 -0800 Message-ID: <20240216000837.1868917-5-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012100549734177 X-GMAIL-MSGID: 1791012100549734177 From: Eric Lin Add a driver for the PMU found in the SiFive Extensible Cache controller. This PMU provides a configurable number of counters and a variety of events. Events are grouped into sets. Each counter can count events from only one set at a time; however, it can count any number of events within that set simultaneously. The PMU hardware does not provide an overflow interrupt. The counter inhibit register is used to atomically start/stop/read a group of counters so their values can be usefully compared. Some events can be filtered further by client ID (e.g. CPU or external DMA master). That functionality is not supported by this driver. This driver further assumes that a single Extensible Cache instance is shared by all CPUs in the system. Example usage: $ perf stat -e sifive_ecache_pmu/inner_rd_request/, sifive_ecache_pmu/inner_wr_request/, sifive_ecache_pmu/inner_rd_request_hit/, sifive_ecache_pmu/inner_wr_request_hit/ ls Performance counter stats for 'system wide': 148001 sifive_ecache_pmu/inner_rd_request/ 121064 sifive_ecache_pmu/inner_wr_request/ 113124 sifive_ecache_pmu/inner_rd_request_hit/ 120860 sifive_ecache_pmu/inner_wr_request_hit/ 0.010643962 seconds time elapsed Example combining the read/write events together within each counter: $ perf stat -e sifive_ecache_pmu/event=0x601/, sifive_ecache_pmu/event=0xc001/ ls Performance counter stats for 'system wide': 262619 sifive_ecache_pmu/event=0x601/ 224533 sifive_ecache_pmu/event=0xc001/ 0.009794808 seconds time elapsed Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- drivers/perf/Kconfig | 10 + drivers/perf/Makefile | 1 + drivers/perf/sifive_ecache_pmu.c | 675 +++++++++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 4 files changed, 687 insertions(+) create mode 100644 drivers/perf/sifive_ecache_pmu.c diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index b4e4db7424b4..8a3b2b88d8b5 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -164,6 +164,16 @@ config SIFIVE_CCACHE_PMU for measuring whole-system L2/L3 cache performance using the perf events subsystem. +config SIFIVE_ECACHE_PMU + tristate "SiFive Extensible Cache PMU" + depends on RISCV || COMPILE_TEST + depends on OF + help + Support for the Extensible Cache performance monitoring unit (PMU) on + SiFive platforms. The Composable Cache PMU provides up to 8 counters + for measuring whole-system L2/L3 cache performance using the perf + events subsystem. + config THUNDERX2_PMU tristate "Cavium ThunderX2 SoC PMU UNCORE" depends on ARCH_THUNDER2 || COMPILE_TEST diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index 51ef5f50ace4..a51686b413f2 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_RISCV_PMU) += riscv_pmu.o obj-$(CONFIG_RISCV_PMU_LEGACY) += riscv_pmu_legacy.o obj-$(CONFIG_RISCV_PMU_SBI) += riscv_pmu_sbi.o obj-$(CONFIG_SIFIVE_CCACHE_PMU) += sifive_ccache_pmu.o +obj-$(CONFIG_SIFIVE_ECACHE_PMU) += sifive_ecache_pmu.o obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o diff --git a/drivers/perf/sifive_ecache_pmu.c b/drivers/perf/sifive_ecache_pmu.c new file mode 100644 index 000000000000..51b2fa3781c9 --- /dev/null +++ b/drivers/perf/sifive_ecache_pmu.c @@ -0,0 +1,675 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SiFive EC (Extensible Cache) PMU driver + * + * Copyright (C) 2023-2024 SiFive, Inc. + * Copyright (C) Eric Lin + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ECACHE_SELECT_OFFSET 0x2000 +#define ECACHE_CLIENT_FILTER_OFFSET 0x2200 +#define ECACHE_COUNTER_INHIBIT_OFFSET 0x2800 +#define ECACHE_COUNTER_OFFSET 0x3000 + +#define ECACHE_PMU_MAX_COUNTERS 8 + +struct sifive_ecache_pmu_slice { + void __iomem *base; +}; + +struct sifive_ecache_pmu { + struct pmu pmu; + struct hlist_node node; + struct notifier_block cpu_pm_nb; + struct perf_event *events[ECACHE_PMU_MAX_COUNTERS]; + DECLARE_BITMAP(used_mask, ECACHE_PMU_MAX_COUNTERS); + unsigned int cpu; + unsigned int txn_flags; + int n_counters; + int n_slices; + struct sifive_ecache_pmu_slice slice[] __counted_by(n_slices); +}; + +#define to_ecache_pmu(p) (container_of(p, struct sifive_ecache_pmu, pmu)) + +/* Store the counter mask for a group in the leader's extra_reg */ +#define event_group_mask(event) (event->group_leader->hw.extra_reg.config) + +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64)readl(addr + 4)) << 32); +} +#endif + +#ifndef writeq +static inline void writeq(u64 v, void __iomem *addr) +{ + writel(lower_32_bits(v), addr); + writel(upper_32_bits(v), addr + 4); +} +#endif + +/* + * sysfs attributes + * + * We export: + * - cpumask, used by perf user space and other tools to know on which CPUs to create events + * - events, used by perf user space and other tools to create events symbolically, e.g.: + * perf stat -a -e sifive_ecache_pmu/event=inner_put_partial_data_hit/ ls + * perf stat -a -e sifive_ecache_pmu/event=0x101/ ls + * - formats, used by perf user space and other tools to configure events + */ + +/* cpumask */ +static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sifive_ecache_pmu *ecache_pmu = dev_get_drvdata(dev); + + if (ecache_pmu->cpu >= nr_cpu_ids) + return 0; + + return sysfs_emit(buf, "%d\n", ecache_pmu->cpu); +}; + +static DEVICE_ATTR_RO(cpumask); + +static struct attribute *sifive_ecache_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL, +}; + +static const struct attribute_group sifive_ecache_pmu_cpumask_group = { + .attrs = sifive_ecache_pmu_cpumask_attrs, +}; + +/* events */ +static ssize_t sifive_ecache_pmu_event_show(struct device *dev, struct device_attribute *attr, + char *page) +{ + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); + return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id); +} + +#define SET_EVENT_SELECT(_event, _set) (BIT_ULL((_event) + 8) | (_set)) +#define ECACHE_PMU_EVENT_ATTR(_name, _event, _set) \ + PMU_EVENT_ATTR_ID(_name, sifive_ecache_pmu_event_show, SET_EVENT_SELECT(_event, _set)) + +enum ecache_pmu_event_set1 { + INNER_REQUEST = 0, + INNER_RD_REQUEST, + INNER_WR_REQUEST, + INNER_PF_REQUEST, + OUTER_PRB_REQUEST, + INNER_REQUEST_HIT, + INNER_RD_REQUEST_HIT, + INNER_WR_REQUEST_HIT, + INNER_PF_REQUEST_HIT, + OUTER_PRB_REQUEST_HIT, + INNER_REQUEST_HITPF, + INNER_RD_REQUEST_HITPF, + INNER_WR_REQUEST_HITPF, + INNER_PF_REQUEST_HITPF, + OUTER_PRB_REQUEST_HITPF, + INNER_REQUEST_MISS, + INNER_RD_REQUEST_MISS, + INNER_WR_REQUEST_MISS, + INNER_PF_REQUEST_MISS, + OUTER_PRB_REQUEST_MISS, + ECACHE_PMU_MAX_EVENT1_IDX +}; + +enum ecache_pmu_event_set2 { + OUTER_REQUEST = 0, + OUTER_RD_REQUEST, + OUTER_PUT_REQUEST, + OUTER_EV_REQUEST, + OUTER_PF_REQUEST, + INNER_PRB_REQUEST, + INNER_REQUEST_WCYC, + INNER_RD_REQUEST_WCYC, + INNER_WR_REQUEST_WCYC, + INNER_PF_REQUEST_WCYC, + OUTER_PRB_REQUEST_WCYC, + OUTER_REQUEST_WCYC, + OUTER_RD_REQUEST_WCYC, + OUTER_PUT_REQUEST_WCYC, + OUTER_EV_REQUEST_WCYC, + OUTER_PF_REQUEST_WCYC, + INNER_PRB_REQUEST_WCYC, + INNER_AG_WCYC, + INNER_AP_WCYC, + INNER_AH_WCYC, + INNER_BP_WCYC, + INNER_CP_WCYC, + INNER_CX_WCYC, + INNER_DG_WCYC, + INNER_DP_WCYC, + INNER_DX_WCYC, + INNER_EG_WCYC, + OUTER_AG_WCYC, + OUTER_AP_WCYC, + OUTER_AH_WCYC, + OUTER_BP_WCYC, + OUTER_CP_WCYC, + OUTER_CX_WCYC, + OUTER_DG_WCYC, + OUTER_DP_WCYC, + OUTER_DX_WCYC, + OUTER_EG_WCYC, + ECACHE_PMU_MAX_EVENT2_IDX +}; + +static struct attribute *sifive_ecache_pmu_events[] = { + /* pmEventSelect1 */ + ECACHE_PMU_EVENT_ATTR(inner_request, INNER_REQUEST, 1), + ECACHE_PMU_EVENT_ATTR(inner_rd_request, INNER_RD_REQUEST, 1), + ECACHE_PMU_EVENT_ATTR(inner_wr_request, INNER_WR_REQUEST, 1), + ECACHE_PMU_EVENT_ATTR(inner_pf_request, INNER_PF_REQUEST, 1), + ECACHE_PMU_EVENT_ATTR(outer_prb_request, OUTER_PRB_REQUEST, 1), + ECACHE_PMU_EVENT_ATTR(inner_request_hit, INNER_REQUEST_HIT, 1), + ECACHE_PMU_EVENT_ATTR(inner_rd_request_hit, INNER_RD_REQUEST_HIT, 1), + ECACHE_PMU_EVENT_ATTR(inner_wr_request_hit, INNER_WR_REQUEST_HIT, 1), + ECACHE_PMU_EVENT_ATTR(inner_pf_request_hit, INNER_PF_REQUEST_HIT, 1), + ECACHE_PMU_EVENT_ATTR(outer_prb_request_hit, OUTER_PRB_REQUEST_HIT, 1), + ECACHE_PMU_EVENT_ATTR(inner_request_hitpf, INNER_REQUEST_HITPF, 1), + ECACHE_PMU_EVENT_ATTR(inner_rd_request_hitpf, INNER_RD_REQUEST_HITPF, 1), + ECACHE_PMU_EVENT_ATTR(inner_wr_request_hitpf, INNER_WR_REQUEST_HITPF, 1), + ECACHE_PMU_EVENT_ATTR(inner_pf_request_hitpf, INNER_PF_REQUEST_HITPF, 1), + ECACHE_PMU_EVENT_ATTR(outer_prb_request_hitpf, OUTER_PRB_REQUEST_HITPF, 1), + ECACHE_PMU_EVENT_ATTR(inner_request_miss, INNER_REQUEST_MISS, 1), + ECACHE_PMU_EVENT_ATTR(inner_rd_request_miss, INNER_RD_REQUEST_MISS, 1), + ECACHE_PMU_EVENT_ATTR(inner_wr_request_miss, INNER_WR_REQUEST_MISS, 1), + ECACHE_PMU_EVENT_ATTR(inner_pf_request_miss, INNER_PF_REQUEST_MISS, 1), + ECACHE_PMU_EVENT_ATTR(outer_prb_request_miss, OUTER_PRB_REQUEST_MISS, 1), + + /* pmEventSelect2 */ + ECACHE_PMU_EVENT_ATTR(outer_request, OUTER_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(outer_rd_request, OUTER_RD_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(outer_put_request, OUTER_PUT_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(outer_ev_request, OUTER_EV_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(outer_pf_request, OUTER_PF_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(inner_prb_request, INNER_PRB_REQUEST, 2), + ECACHE_PMU_EVENT_ATTR(inner_request_wcyc, INNER_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_rd_request_wcyc, INNER_RD_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_wr_request_wcyc, INNER_WR_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_pf_request_wcyc, INNER_PF_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_prb_request_wcyc, OUTER_PRB_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_request_wcyc, OUTER_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_rd_request_wcyc, OUTER_RD_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_put_request_wcyc, OUTER_PUT_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_ev_request_wcyc, OUTER_EV_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_pf_request_wcyc, OUTER_PF_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_prb_request_wcyc, INNER_PRB_REQUEST_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_ag_wcyc, INNER_AG_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_ap_wcyc, INNER_AP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_ah_wcyc, INNER_AH_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_bp_wcyc, INNER_BP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_cp_wcyc, INNER_CP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_cx_wcyc, INNER_CX_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_dg_wcyc, INNER_DG_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_dp_wcyc, INNER_DP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_dx_wcyc, INNER_DX_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(inner_eg_wcyc, INNER_EG_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_ag_wcyc, OUTER_AG_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_ap_wcyc, OUTER_AP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_ah_wcyc, OUTER_AH_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_bp_wcyc, OUTER_BP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_cp_wcyc, OUTER_CP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_cx_wcyc, OUTER_CX_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_dg_wcyc, OUTER_DG_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_dp_wcyc, OUTER_DP_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_dx_wcyc, OUTER_DX_WCYC, 2), + ECACHE_PMU_EVENT_ATTR(outer_eg_wcyc, OUTER_EG_WCYC, 2), + NULL +}; + +static struct attribute_group sifive_ecache_pmu_events_group = { + .name = "events", + .attrs = sifive_ecache_pmu_events, +}; + +/* formats */ +PMU_FORMAT_ATTR(event, "config:0-63"); + +static struct attribute *sifive_ecache_pmu_formats[] = { + &format_attr_event.attr, + NULL, +}; + +static struct attribute_group sifive_ecache_pmu_format_group = { + .name = "format", + .attrs = sifive_ecache_pmu_formats, +}; + +/* + * Per PMU device attribute groups + */ + +static const struct attribute_group *sifive_ecache_pmu_attr_grps[] = { + &sifive_ecache_pmu_cpumask_group, + &sifive_ecache_pmu_events_group, + &sifive_ecache_pmu_format_group, + NULL, +}; + +/* + * Event Initialization + */ + +static int sifive_ecache_pmu_event_init(struct perf_event *event) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 config = event->attr.config; + u64 ev_type = config >> 8; + u64 set = config & 0xff; + + /* Check if this is a valid set and event */ + switch (set) { + case 1: + if (ev_type >= BIT_ULL(ECACHE_PMU_MAX_EVENT1_IDX)) + return -ENOENT; + break; + case 2: + if (ev_type >= BIT_ULL(ECACHE_PMU_MAX_EVENT2_IDX)) + return -ENOENT; + break; + default: + return -ENOENT; + } + + /* Do not allocate the hardware counter yet */ + hwc->idx = -1; + hwc->config = config; + + event->cpu = ecache_pmu->cpu; + + return 0; +} + +/* + * Low-level functions: reading and writing counters + */ + +static void configure_counter(const struct sifive_ecache_pmu *ecache_pmu, + const struct hw_perf_event *hwc, u64 config) +{ + for (int i = 0; i < ecache_pmu->n_slices; i++) { + void __iomem *base = ecache_pmu->slice[i].base; + + if (config) + writeq(0, base + hwc->event_base); + writeq(config, base + hwc->config_base); + } +} + +static u64 read_counter(const struct sifive_ecache_pmu *ecache_pmu, const struct hw_perf_event *hwc) +{ + u64 value = 0; + + for (int i = 0; i < ecache_pmu->n_slices; i++) { + void __iomem *base = ecache_pmu->slice[i].base; + + value += readq(base + hwc->event_base); + } + + return value; +} + +static void write_inhibit(const struct sifive_ecache_pmu *ecache_pmu, u64 mask) +{ + u64 used_mask; + + /* Inhibit all unused counters in addition to the provided mask */ + bitmap_to_arr64(&used_mask, ecache_pmu->used_mask, ECACHE_PMU_MAX_COUNTERS); + mask |= ~used_mask; + + for (int i = 0; i < ecache_pmu->n_slices; i++) { + void __iomem *base = ecache_pmu->slice[i].base; + + writeq(mask, base + ECACHE_COUNTER_INHIBIT_OFFSET); + } +} + +/* + * pmu->read: read and update the counter + */ +static void sifive_ecache_pmu_read(struct perf_event *event) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 prev_raw_count, new_raw_count; + u64 oldval; + + /* Inhibit the entire group during a read transaction for atomicity */ + if (ecache_pmu->txn_flags == PERF_PMU_TXN_READ && event->group_leader == event) + write_inhibit(ecache_pmu, event_group_mask(event)); + + do { + prev_raw_count = local64_read(&hwc->prev_count); + new_raw_count = read_counter(ecache_pmu, hwc); + + oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count); + } while (oldval != prev_raw_count); + + local64_add(new_raw_count - prev_raw_count, &event->count); +} + +/* + * State transition functions: + * + * start()/stop() & add()/del() + */ + +/* + * pmu->start: start the event + */ +static void sifive_ecache_pmu_start(struct perf_event *event, int flags) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + hwc->state = 0; + + /* Set initial value to 0 */ + local64_set(&hwc->prev_count, 0); + + /* Enable this counter to count events */ + configure_counter(ecache_pmu, hwc, hwc->config); +} + +/* + * pmu->stop: stop the counter + */ +static void sifive_ecache_pmu_stop(struct perf_event *event, int flags) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + if (hwc->state & PERF_HES_STOPPED) + return; + + /* Disable this counter to count events */ + configure_counter(ecache_pmu, hwc, 0); + sifive_ecache_pmu_read(event); + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; +} + +/* + * pmu->add: add the event to the PMU + */ +static int sifive_ecache_pmu_add(struct perf_event *event, int flags) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx; + + /* Find an available counter idx to use for this event */ + do { + idx = find_first_zero_bit(ecache_pmu->used_mask, ecache_pmu->n_counters); + if (idx >= ecache_pmu->n_counters) + return -EAGAIN; + } while (test_and_set_bit(idx, ecache_pmu->used_mask)); + + event_group_mask(event) |= BIT_ULL(idx); + hwc->config_base = ECACHE_SELECT_OFFSET + 8 * idx; + hwc->event_base = ECACHE_COUNTER_OFFSET + 8 * idx; + hwc->idx = idx; + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + ecache_pmu->events[idx] = event; + + if (flags & PERF_EF_START) + sifive_ecache_pmu_start(event, PERF_EF_RELOAD); + + perf_event_update_userpage(event); + + return 0; +} + +/* + * pmu->del: delete the event from the PMU + */ +static void sifive_ecache_pmu_del(struct perf_event *event, int flags) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + /* Stop and release this counter */ + sifive_ecache_pmu_stop(event, PERF_EF_UPDATE); + + ecache_pmu->events[idx] = NULL; + clear_bit(idx, ecache_pmu->used_mask); + + perf_event_update_userpage(event); +} + +/* + * Transaction synchronization + */ + +static void sifive_ecache_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(pmu); + + ecache_pmu->txn_flags = txn_flags; + + /* Inhibit any counters that were deleted since the last transaction */ + if (txn_flags == PERF_PMU_TXN_ADD) + write_inhibit(ecache_pmu, 0); +} + +static int sifive_ecache_pmu_commit_txn(struct pmu *pmu) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(pmu); + + ecache_pmu->txn_flags = 0; + + /* Successful transaction: atomically uninhibit the counters in this group */ + write_inhibit(ecache_pmu, 0); + + return 0; +} + +static void sifive_ecache_pmu_cancel_txn(struct pmu *pmu) +{ + struct sifive_ecache_pmu *ecache_pmu = to_ecache_pmu(pmu); + + ecache_pmu->txn_flags = 0; + + /* Failed transaction: leave the counters in this group inhibited */ +} + +/* + * Driver initialization + */ + +static void sifive_ecache_pmu_hw_init(const struct sifive_ecache_pmu *ecache_pmu) +{ + for (int i = 0; i < ecache_pmu->n_slices; i++) { + void __iomem *base = ecache_pmu->slice[i].base; + + /* Disable the client filter (not supported by this driver) */ + writeq(0, base + ECACHE_CLIENT_FILTER_OFFSET); + } +} + +static int sifive_ecache_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct sifive_ecache_pmu *ecache_pmu = + hlist_entry_safe(node, struct sifive_ecache_pmu, node); + + if (ecache_pmu->cpu >= nr_cpu_ids) + ecache_pmu->cpu = cpu; + + return 0; +} + +static int sifive_ecache_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct sifive_ecache_pmu *ecache_pmu = + hlist_entry_safe(node, struct sifive_ecache_pmu, node); + + /* Do nothing if this CPU does not own the events */ + if (cpu != ecache_pmu->cpu) + return 0; + + /* Pick a random online CPU */ + ecache_pmu->cpu = cpumask_any_but(cpu_online_mask, cpu); + if (ecache_pmu->cpu >= nr_cpu_ids) + return 0; + + /* Migrate PMU events from this CPU to the target CPU */ + perf_pmu_migrate_context(&ecache_pmu->pmu, cpu, ecache_pmu->cpu); + + return 0; +} + +static int sifive_ecache_pmu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *ecache_node = dev_of_node(dev); + struct sifive_ecache_pmu *ecache_pmu; + struct device_node *slice_node; + u32 slice_counters; + int n_slices, ret; + int i = 0; + + n_slices = of_get_available_child_count(ecache_node); + if (!n_slices) + return -ENODEV; + + ecache_pmu = devm_kzalloc(dev, struct_size(ecache_pmu, slice, n_slices), GFP_KERNEL); + if (!ecache_pmu) + return -ENOMEM; + + platform_set_drvdata(pdev, ecache_pmu); + + ecache_pmu->pmu = (struct pmu) { + .parent = dev, + .attr_groups = sifive_ecache_pmu_attr_grps, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, + .task_ctx_nr = perf_invalid_context, + .event_init = sifive_ecache_pmu_event_init, + .add = sifive_ecache_pmu_add, + .del = sifive_ecache_pmu_del, + .start = sifive_ecache_pmu_start, + .stop = sifive_ecache_pmu_stop, + .read = sifive_ecache_pmu_read, + .start_txn = sifive_ecache_pmu_start_txn, + .commit_txn = sifive_ecache_pmu_commit_txn, + .cancel_txn = sifive_ecache_pmu_cancel_txn, + }; + ecache_pmu->cpu = nr_cpu_ids; + ecache_pmu->n_counters = ECACHE_PMU_MAX_COUNTERS; + ecache_pmu->n_slices = n_slices; + + for_each_available_child_of_node(ecache_node, slice_node) { + struct sifive_ecache_pmu_slice *slice = &ecache_pmu->slice[i++]; + + slice->base = devm_of_iomap(dev, slice_node, 0, NULL); + if (IS_ERR(slice->base)) + return PTR_ERR(slice->base); + + /* Get number of counters from slice node */ + ret = of_property_read_u32(slice_node, "sifive,perfmon-counters", &slice_counters); + if (ret) + return dev_err_probe(dev, ret, + "Slice %pOF missing sifive,perfmon-counters property\n", + slice_node); + + ecache_pmu->n_counters = min_t(u32, slice_counters, ecache_pmu->n_counters); + } + + sifive_ecache_pmu_hw_init(ecache_pmu); + + ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE, &ecache_pmu->node); + if (ret) + return dev_err_probe(dev, ret, "Failed to add CPU hotplug instance\n"); + + ret = perf_pmu_register(&ecache_pmu->pmu, "sifive_ecache_pmu", -1); + if (ret) { + dev_err_probe(dev, ret, "Failed to register PMU\n"); + goto err_remove_instance; + } + + return 0; + +err_remove_instance: + cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE, &ecache_pmu->node); + + return ret; +} + +static void sifive_ecache_pmu_remove(struct platform_device *pdev) +{ + struct sifive_ecache_pmu *ecache_pmu = platform_get_drvdata(pdev); + + perf_pmu_unregister(&ecache_pmu->pmu); + cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE, &ecache_pmu->node); +} + +static const struct of_device_id sifive_ecache_pmu_of_match[] = { + { .compatible = "sifive,extensiblecache0" }, + {} +}; +MODULE_DEVICE_TABLE(of, sifive_ecache_pmu_of_match); + +static struct platform_driver sifive_ecache_pmu_driver = { + .probe = sifive_ecache_pmu_probe, + .remove_new = sifive_ecache_pmu_remove, + .driver = { + .name = "sifive_ecache_pmu", + .of_match_table = sifive_ecache_pmu_of_match, + }, +}; + +static void __exit sifive_ecache_pmu_exit(void) +{ + platform_driver_unregister(&sifive_ecache_pmu_driver); + cpuhp_remove_multi_state(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE); +} +module_exit(sifive_ecache_pmu_exit); + +static int __init sifive_ecache_pmu_init(void) +{ + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE, + "perf/sifive/ecache:online", + sifive_ecache_pmu_online_cpu, + sifive_ecache_pmu_offline_cpu); + if (ret) + return ret; + + ret = platform_driver_register(&sifive_ecache_pmu_driver); + if (ret) + goto err_remove_state; + + return 0; + +err_remove_state: + cpuhp_remove_multi_state(CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE); + + return ret; +} +module_init(sifive_ecache_pmu_init); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index be6361fdc8ba..55bd3a5e0033 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -231,6 +231,7 @@ enum cpuhp_state { CPUHP_AP_PERF_POWERPC_HV_24x7_ONLINE, CPUHP_AP_PERF_POWERPC_HV_GPCI_ONLINE, CPUHP_AP_PERF_RISCV_SIFIVE_CCACHE_ONLINE, + CPUHP_AP_PERF_RISCV_SIFIVE_ECACHE_ONLINE, CPUHP_AP_PERF_CSKY_ONLINE, CPUHP_AP_WATCHDOG_ONLINE, CPUHP_AP_WORKQUEUE_ONLINE, From patchwork Fri Feb 16 00:08:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201851 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201609dyb; Thu, 15 Feb 2024 16:10:01 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUAudUCjvu0ZSBPMzKK1cc/9y56gabBdvRFzdFlvN9MqpRP4VXLsjqg93GNS9VORPR9caiw1vVmjN3eH8aJ35tH+irmwA== X-Google-Smtp-Source: AGHT+IGEI4Ikf4CpH7YM6vNFFvtmDI7U8ZIBvYnSI9YsKjC5zqQRVMc0WBgeYm1JtdhWS+ug8A6c X-Received: by 2002:a05:6512:945:b0:511:4175:8d16 with SMTP id u5-20020a056512094500b0051141758d16mr2056284lft.55.1708042201309; Thu, 15 Feb 2024 16:10:01 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042201; cv=pass; d=google.com; s=arc-20160816; b=nbFaGY3O2WtiP6rcXVYCm+w1DxTbhbwcK9dCo764e6iIjEuu6R823pqMVDRLQ/dvmJ 8/AEJJyqnfDmdmq5Ibz0YUjteqiqL7ETnAjM62KnUC3CivMrBb1RNyJFeAVvvnOFhla+ dVNLoMkK9gtu2HmJ367jLduBsqa/Yi18rYi5ARN64sPCxFirAOjE+ja4LFQ/BKfhst0/ C4kIWujhJ2Xh6ahGQXv2GzMVi2hd7CQyQNlT8sVVSuqzJJv4hcJeflz2ipPyQV6M6NAK 743eju8IUMO3RMhXwzCsxepC+zP9GcGNmO0j3bqfv7IUTnlu7iATCr427umUkT2/CeXq 5wUg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=pGHwuS0ENdmLMLz6bWQqaQXZhO2uE/iwucpykSfpWsk=; fh=VW0LScFv25iPiCNVbdY8i4XCBJE/j4V5yoN90ljnHDE=; b=ov6KiCZhpipz65fZD8TB0S5axSOjbYXdFyDZhO0ZCTiCmuZFWVRVLtkJ+XtL20kAXW rYYarmXD31YQ6fdem2aDsG6/rOsXsLvHd5lH7MI1Vy9+rn/DYQMToR3i3gZiB8LnRGwN UcLnCAmpkSLPT1yQR8IWZQywxJy2jCcIPNMulecS9w+1zWgjBs5fU08N0SEwcPKgL72A UhHleUjRcwXGKaiOmXdG/jnMBz+QrGl8SdUkqJVlNXivV5jcDvD2GqawII//ePjB7Vn2 CWz3bheLE71owvvRdCkDY4ppRbO2NIvhXOeY2Tw2Shovhd8G19fwWyFJTLxdvh5qfpY5 Fz9A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=LbOeZ3Cx; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67878-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67878-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id g8-20020a17090669c800b00a3d4c3d2f33si1105331ejs.454.2024.02.15.16.10.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:10:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67878-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=LbOeZ3Cx; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67878-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67878-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id A31321F254D4 for ; Fri, 16 Feb 2024 00:10:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F2988E556; Fri, 16 Feb 2024 00:08:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="LbOeZ3Cx" Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AB769461 for ; Fri, 16 Feb 2024 00:08:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042135; cv=none; b=aWecMDEYybSLBkSBk4F9+x9Z9YvUIsQ6Kx9t9QIZMrB+iKRUfRiMr+pXNuOYuZwDNux+4TvRhRa4ReElOkyiUl9QaG46EoItqqjYn0RUwIMbgqTB0l5UU7pw4p7DAtlaUdCRgZ43ZRpTuW5DxsorMUHdTh52mHHRCpHGnyOoXo4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042135; c=relaxed/simple; bh=MiXxLFVa9bJKB4WuCSu/Z1PDr8YPzEWCNGu5OpaGMgg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S5te4sndPyPV+AgOt1iq1pQgPAOxCIK/LG8DD9O22atH0BPwGDE8vTSR4Ee/o32l/IjnohNl9nTSvL5aCM4g9CdHN3x3xBRh59DytyuR/eV804BGFH0sdRw59XsWI0gxKQClXom9wEWicDjOwDB6UbyGn0eHiXIYbF/RsAMQuiI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=LbOeZ3Cx; arc=none smtp.client-ip=209.85.214.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f177.google.com with SMTP id d9443c01a7336-1db562438e0so13114715ad.3 for ; Thu, 15 Feb 2024 16:08:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042133; x=1708646933; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pGHwuS0ENdmLMLz6bWQqaQXZhO2uE/iwucpykSfpWsk=; b=LbOeZ3CxNKBqBrV+XbT/0DBKTuMEXqFDH3fdG046O1Rw1fQCF9bOnRyz3bq0AsrF7m B2UudWF4ZelRFpbP657UtDj/6/kDYDJUiT9wF7LA2mY3xuVyuFjBCs2R51t+Iiwea6LZ GauilCH6RmSflFZBX5KcegxkDU3o4AjZ+tuE4vdl6gFWoWghRDbBqbaAJBDd6tkawO0l ejlBT0ea8asItlbXZCDo1K36PMD0Q/xACaLPCnjLE1VSjBEz7xgtlPa/7R5AwnhdL5F+ jPXg8aGfJoRo4t1CmrWmFXirkHWJeoRinJTyrT7l6es2fOa0JtoSOEBH76fmFZOd0itq UaQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042133; x=1708646933; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pGHwuS0ENdmLMLz6bWQqaQXZhO2uE/iwucpykSfpWsk=; b=V6B8nGUdC43Me+aqcXh4LgTjC5v46+KimNxlS5n9cRaHgQOPE+0i/5yWZ71zJ6j/+r kkWDZgqPA03lpDCMiEKCSkLL5lhlsUrwd2cMckv8PmoB59mS3ot4XXExtdb1TbGuXaTn UprH9G/Rwein9n9tXtp6oE/XKvi9EvtMB9cOg3MOmzY+aXJSDoKOM2kh9T+ULNkb3Js3 QbxQa2P9uvqImxT17nSTafa/eSJVn4G0O6xZyz8xpTwYvsGJUdL09KMY6Lxod62JVDA5 FFNlu5DKx1j6i6BDlnrf8uADkoOWR0koItc2PraatFWln344sVQ5+SisFexrgQwwTW9N sdEA== X-Forwarded-Encrypted: i=1; AJvYcCXABmzN6Al0/UqIzsKNwjNsUHyCUWSk+1D3CqE+HTpPkyn8l5JPt6+MGQ6vwWpmacjIY30U6aaC6GnhAR4tDv3Ap811sXXLPNr0WhVz X-Gm-Message-State: AOJu0YwcChxxBXqrr/mCHActM0uq5NHWnJHDhyI0MqQ93ZXLfugMSo9V 3YWekSxMUu0Hyjp4gK4HiVjqsVwHnHRoFGiRNEOKWotDvtnHVnm2WfuxNdJTzMo= X-Received: by 2002:a17:902:784e:b0:1d9:ba26:effc with SMTP id e14-20020a170902784e00b001d9ba26effcmr3177476pln.51.1708042132885; Thu, 15 Feb 2024 16:08:52 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:51 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Samuel Holland Subject: [PATCH v1 5/6] dt-bindings: cache: Add SiFive Private L2 Cache controller Date: Thu, 15 Feb 2024 16:08:17 -0800 Message-ID: <20240216000837.1868917-6-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012059480598567 X-GMAIL-MSGID: 1791012059480598567 From: Eric Lin Add YAML DT binding documentation for the SiFive Private L2 Cache controller. Some functionality and the corresponding register bits were removed in the sifive,pl2cache1 version of the hardware, which creates the unusual situation where the newer hardware's compatible string is the fallback for the older one. Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- Changes in v1: - Add back select: clause to binding - Make sifive,pl2cache1 the fallback for sifive,pl2cache0 - Fix the order of the reg property declaration - Document the sifive,perfmon-counters property .../bindings/cache/sifive,pl2cache0.yaml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Documentation/devicetree/bindings/cache/sifive,pl2cache0.yaml diff --git a/Documentation/devicetree/bindings/cache/sifive,pl2cache0.yaml b/Documentation/devicetree/bindings/cache/sifive,pl2cache0.yaml new file mode 100644 index 000000000000..d89e2e5d0a97 --- /dev/null +++ b/Documentation/devicetree/bindings/cache/sifive,pl2cache0.yaml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (C) 2023-2024 SiFive, Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/cache/sifive,pl2cache0.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SiFive Private L2 Cache Controller + +maintainers: + - Eric Lin + +description: + The SiFive Private L2 Cache Controller is a per-core cache which communicates + with both the upstream L1 caches and downstream L3 cache or memory, enabling a + high-performance cache subsystem. + +allOf: + - $ref: /schemas/cache-controller.yaml# + +select: + properties: + compatible: + contains: + enum: + - sifive,pl2cache1 + + required: + - compatible + +properties: + compatible: + oneOf: + - items: + - const: sifive,pl2cache0 + - const: sifive,pl2cache1 + - const: cache + - items: + - const: sifive,pl2cache1 + - const: cache + + reg: + maxItems: 1 + + cache-block-size: true + cache-level: true + cache-sets: true + cache-size: true + cache-unified: true + + next-level-cache: true + + sifive,perfmon-counters: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: Number of PMU counter registers + +required: + - compatible + - reg + - cache-block-size + - cache-level + - cache-sets + - cache-size + - cache-unified + +additionalProperties: false + +examples: + - | + cache-controller@10104000 { + compatible = "sifive,pl2cache1", "cache"; + reg = <0x10104000 0x4000>; + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <512>; + cache-size = <262144>; + cache-unified; + next-level-cache = <&L4>; + sifive,perfmon-counters = <6>; + }; From patchwork Fri Feb 16 00:08:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 201853 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:c619:b0:108:e6aa:91d0 with SMTP id hn25csp201869dyb; Thu, 15 Feb 2024 16:10:36 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCX+5nUQdqfeifMT3AkGGF845ihVCd9apCetbgfyrd6QAvJnFxkcgJP8/AEwzXsSPSWjBQ6d+l32ZprOOlyZeobF50PobQ== X-Google-Smtp-Source: AGHT+IHsD+uowDcgi/c0hlJSxHxulwosKTaLLGV1v8+Bi6EqhNCjB4qilBNkYP+zP/VQAR/Np8Qt X-Received: by 2002:a05:620a:21dc:b0:785:a288:8c74 with SMTP id h28-20020a05620a21dc00b00785a2888c74mr3662966qka.49.1708042236680; Thu, 15 Feb 2024 16:10:36 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708042236; cv=pass; d=google.com; s=arc-20160816; b=OIO4hF92Ms5KAzbhfjnwST/4fPwrZDNS+UHukn8VyME9d3Bq2Ebfh68TWrhuOE97PD hgozQBrwoWPEfuh9C5j1sd2gXwd4mB+345wOgTDfZnTeKxtnSIaq8M9jAJ7MKuDdnqKP jDadNmh2qUAZKVj9d6njx/j+kYmpj+BqvVFmBHe9n+SBfoqFO0QCK9Szy7VIE5qKBqye a3e6liCVMjgbTbnP1gpDQg1otCkYty992AKuPRV+1Hl2EqChWVZoYKUaqejcNopu6jK/ Eart5uq4QSjdcvCSbvwkwAQBbXmLoWnmcOc5AITh0ddTsUXFCiDH9Wm45YsNVQsXPPjW +pRA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=p/acc0KNWqEiBrI2bUhG9VfOZxykMoq55GvaWo8V2Yc=; fh=aaEZe2dtwWVDeaQbxtvh2EUIr6ZN1/41weaf9mG3oIk=; b=PTvG6MKgkdVmdnCA2/jxnvXvxMVn4U8XUzGAkrBP7RE2pZRDzoTRZhuoIKSYwDRcQt dKN8YHn9W8p43UUujhoC8rrxB/VirgM44EYH9idwRHluyr70/8Bklrbp1lDrlHsgzOtK a/B3U4hRykCAEoJVMDP0y2vbAMIWpMAinhkboH2NPIydtAa75Ir7zUSrch+8kcsvMSc2 N57jXxgb3RaMHdDmaAe5oZoNjoDXjLrfj1dcaCs4QmhKiB/NiMOEHJmm4OKXhn8w3cvp sXFqHqWaaj+Zitdx5LhDyA9FZsUwcopPp95l6H3WiXlDaa6EvDE6B4aawVWNSsjkJ7f4 +6+A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=S6Y5JR1w; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67879-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67879-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id x11-20020a05620a0b4b00b007873af4a4e7si1825495qkg.764.2024.02.15.16.10.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:10:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-67879-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=S6Y5JR1w; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-67879-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-67879-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 508861C236E8 for ; Fri, 16 Feb 2024 00:10:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 771BFF9EF; Fri, 16 Feb 2024 00:09:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="S6Y5JR1w" Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC760DDCA for ; Fri, 16 Feb 2024 00:08:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042139; cv=none; b=j54iWof2BUwkj7/pxGlHCzLHP5NVSrP6fBKiWi0+ZpT15QtAT7aCwJV3Mhkd5AUNekdD0zO2juT0EN+jj++oEKSdC8j06kwAHM7pIPdhsb/9bSDFfUJeLuC0pG6+puZLc4i5Xh8Ap14EHAP84XYZ0WSqB8rwfAQjkPikYixuk+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708042139; c=relaxed/simple; bh=JkAv4hlLlinDg6WO1Ei4HQwcmM/jZtqgc/bSglhHsww=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KaaxG/x/hlIDsvZj2k+rycV/wCG3by5xEls5/NSkTBGEIConLaaAY4JodlEJHpDQMmlKEij9Yyb+PNEc++h9AnzCcHbscJ2ycQt8/fwMsnruHySALRaQFpuQ7bJ4PNnT641oo6NEsFAEAldugi2VbX0AogFDWRnY1zeucfVU9qQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=S6Y5JR1w; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-1d93edfa76dso1264925ad.1 for ; Thu, 15 Feb 2024 16:08:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1708042136; x=1708646936; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=p/acc0KNWqEiBrI2bUhG9VfOZxykMoq55GvaWo8V2Yc=; b=S6Y5JR1w3TP0drTyAZGnJwJacp5+a+bICH80W8ZiRiRzeQ6eVW4km8dbVHFSpXeCOc K3TqdDSVQLPlKuUMygKZw6DsQsBXjAZ1i7XBsVzddTelE1Lx2Bd3RULAvVh9IMufj7ti jNYBx2G43Jbc3Zc7muX0X9pBd6aCPIichTxJpOVSkBCXeYKPl+ENebSJEFYBw++d6Jkm ocP7RaUkwiW23wZb482Zj9MzzIKCysCwb63uGe2sISP2DGu3tpAeUW91XFCk9kC4zUTO haQ7NdzywK4jzWMinCq//YVnLX2ocPmRgVhDeEUJMaBlFKyQxqCYoL+RRX4DmQuE9a+7 eTgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708042136; x=1708646936; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=p/acc0KNWqEiBrI2bUhG9VfOZxykMoq55GvaWo8V2Yc=; b=hsHKCFNx4m9EWVqgMAZ076U8W7v8rwPVIHiUi4rWdYsl15wFpYRJw1bw+V9fLTZM/N FLihkZuH6UmSo0nVDTdehircsmi4oj797tFuIymbIniACyfTf56hLmbFyx6HMzCHY8Nw KoHl8YpCzAKyA7KcvdVwz7vLGlgcMdWz39fl0ZNyy/j7QerpWFRLKvwejic1iMbxBaQm 3plkDi3b3ZuWjGEwUSdJSvoTlC4dRq3wfdEbv1wh23pmnLyNPk6hls7yxkQPgDoWpZ2W XmguGjsCWlLF0b34MIytsYh0Fyqee6NRMqIGQ7C15c5AcbHkGCCxnGx4Yd4IiluV3DFX LpjA== X-Forwarded-Encrypted: i=1; AJvYcCUdgfWIZUk/JtuEVjyQB22S7z9S9h2JW4G17AVCwtJF63H2imFbH+GenL8cl4ivEmoU2AR3CYQ6rwhbG3NTKIMAmGfB82MYZTVHvDu8 X-Gm-Message-State: AOJu0YxEJMobjB1uDZzTRUzcbExX0VlsdHhYfcJ37NYNtNERry2LOmrZ gcQq15Y/otrG1ssSgeGd2fA6d/JbGYO4jIoWnNJOJNygiC0umPi97g08nR4lkwU= X-Received: by 2002:a17:902:ec89:b0:1db:aa46:4923 with SMTP id x9-20020a170902ec8900b001dbaa464923mr46470plg.40.1708042136146; Thu, 15 Feb 2024 16:08:56 -0800 (PST) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id bb6-20020a170902bc8600b001db3d365082sm1789486plb.265.2024.02.15.16.08.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 16:08:54 -0800 (PST) From: Samuel Holland To: Will Deacon , Mark Rutland , Eric Lin , Conor Dooley Cc: Palmer Dabbelt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Walmsley , linux-riscv@lists.infradead.org, Rob Herring , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org, Greentime Hu , Samuel Holland Subject: [PATCH v1 6/6] drivers/perf: Add SiFive Private L2 Cache PMU driver Date: Thu, 15 Feb 2024 16:08:18 -0800 Message-ID: <20240216000837.1868917-7-samuel.holland@sifive.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240216000837.1868917-1-samuel.holland@sifive.com> References: <20240216000837.1868917-1-samuel.holland@sifive.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791012096384628966 X-GMAIL-MSGID: 1791012096384628966 From: Greentime Hu Add a driver for the PMU found in the SiFive Private L2 Cache controller. This PMU provides a configurable number of counters and a variety of events. Events are grouped into sets. Each counter can count events from only one set at a time; however, it can count any number of events within that set simultaneously. The PMU hardware does not provide an overflow interrupt or a way to atomically control groups of counters. A separate Private L2 Cache instance exists for each core, so this driver supports per-core and per-task profiling. Some events can be filtered further by client ID (e.g. CPU or external DMA master). That functionality is not supported by this driver. Example usage: $ perf stat -e sifive_pl2_pmu/inner_get/,sifive_pl2_pmu/outer_get/ ls Performance counter stats for 'ls': 95041 sifive_pl2_pmu/inner_get/ 3 sifive_pl2_pmu/outer_get/ 0.003971538 seconds time elapsed 0.000000000 seconds user 0.006315000 seconds sys Example combining multiple events together within each counter: $ perf stat -e sifive_pl2_pmu/event=0x301/, # inner_put_*_data sifive_pl2_pmu/event=0x303/ ls # outer_put_*_data Performance counter stats for 'ls': 6828 sifive_pl2_pmu/event=0x301/ 11 sifive_pl2_pmu/event=0x303/ 0.005696538 seconds time elapsed 0.000000000 seconds user 0.006337000 seconds sys Signed-off-by: Greentime Hu Co-developed-by: Eric Lin Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- Changes in v1: - Add missing events to PL2 sets 2, 4, and 5 - Use event_base and config_base to precompute register addresses - Check event validity earlier, in the .event_init hook - Implement .filter for systems where only some CPUs have a PL2 - Only allocate percpu data when probing each PL2 instance - Reference count the `struct pmu` to fix unbind/bind crashes - Probe via DT since the PMU driver is now the only PL2 driver - Allow the driver to be built as a module drivers/perf/Kconfig | 10 + drivers/perf/Makefile | 1 + drivers/perf/sifive_pl2_pmu.c | 748 ++++++++++++++++++++++++++++++++++ 3 files changed, 759 insertions(+) create mode 100644 drivers/perf/sifive_pl2_pmu.c diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index 8a3b2b88d8b5..bd5ebed8630b 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -174,6 +174,16 @@ config SIFIVE_ECACHE_PMU for measuring whole-system L2/L3 cache performance using the perf events subsystem. +config SIFIVE_PL2_PMU + tristate "SiFive Private L2 Cache PMU" + depends on RISCV || COMPILE_TEST + depends on OF + help + Support for the Private L2 Cache performance monitoring unit (PMU) on + SiFive platforms. The Private L2 Cache PMU provides up to 64 counters + for measuring per-program or per-hart L2 cache performance using the + perf events subsystem. + config THUNDERX2_PMU tristate "Cavium ThunderX2 SoC PMU UNCORE" depends on ARCH_THUNDER2 || COMPILE_TEST diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index a51686b413f2..d5501196dcd8 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_RISCV_PMU_LEGACY) += riscv_pmu_legacy.o obj-$(CONFIG_RISCV_PMU_SBI) += riscv_pmu_sbi.o obj-$(CONFIG_SIFIVE_CCACHE_PMU) += sifive_ccache_pmu.o obj-$(CONFIG_SIFIVE_ECACHE_PMU) += sifive_ecache_pmu.o +obj-$(CONFIG_SIFIVE_PL2_PMU) += sifive_pl2_pmu.o obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o diff --git a/drivers/perf/sifive_pl2_pmu.c b/drivers/perf/sifive_pl2_pmu.c new file mode 100644 index 000000000000..d0bbac0dec06 --- /dev/null +++ b/drivers/perf/sifive_pl2_pmu.c @@ -0,0 +1,748 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SiFive Private L2 Cache PMU driver + * + * Copyright (C) 2018-2024 SiFive, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PL2_SELECT_OFFSET 0x2000 +#define PL2_CLIENT_FILTER_OFFSET 0x2800 +#define PL2_COUNTER_OFFSET 0x3000 + +#define PL2_PMU_MAX_COUNTERS 64 + +struct sifive_pl2_pmu_event { + void __iomem *base; + DECLARE_BITMAP(used_mask, PL2_PMU_MAX_COUNTERS); + unsigned int cpu; + int n_counters; + struct perf_event *events[] __counted_by(n_counters); +}; + +struct sifive_pl2_pmu { + struct pmu pmu; + struct notifier_block cpu_pm_nb; + refcount_t refcount; + struct sifive_pl2_pmu_event *__percpu *event; +}; + +#define to_pl2_pmu(p) (container_of(p, struct sifive_pl2_pmu, pmu)) + +static DEFINE_MUTEX(g_mutex); +static struct sifive_pl2_pmu *g_pl2_pmu; + +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64)readl(addr + 4)) << 32); +} +#endif + +#ifndef writeq +static inline void writeq(u64 v, void __iomem *addr) +{ + writel(lower_32_bits(v), addr); + writel(upper_32_bits(v), addr + 4); +} +#endif + +/* + * sysfs attributes + * + * We export: + * - events, used by perf user space and other tools to create events symbolically, e.g.: + * perf stat -a -e sifive_pl2_pmu/event=inner_put_partial_data_hit/ ls + * perf stat -a -e sifive_pl2_pmu/event=0x101/ ls + * - formats, used by perf user space and other tools to configure events + */ + +/* events */ +static ssize_t sifive_pl2_pmu_event_show(struct device *dev, struct device_attribute *attr, + char *page) +{ + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); + return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id); +} + +#define SET_EVENT_SELECT(_event, _set) (BIT_ULL((_event) + 8) | (_set)) +#define PL2_PMU_EVENT_ATTR(_name, _event, _set) \ + PMU_EVENT_ATTR_ID(_name, sifive_pl2_pmu_event_show, SET_EVENT_SELECT(_event, _set)) + +enum pl2_pmu_event_set1 { + INNER_PUT_FULL_DATA = 0, + INNER_PUT_PARTIAL_DATA, + INNER_ATOMIC_DATA, + INNER_GET, + INNER_PREFETCH_READ, + INNER_PREFETCH_WRITE, + INNER_ACQUIRE_BLOCK_NTOB, + INNER_ACQUIRE_BLOCK_NTOT, + INNER_ACQUIRE_BLOCK_BTOT, + INNER_ACQUIRE_PERM_NTOT, + INNER_ACQUIRE_PERM_BTOT, + INNER_RELEASE_TTOB, + INNER_RELEASE_TTON, + INNER_RELEASE_BTON, + INNER_RELEASE_DATA_TTOB, + INNER_RELEASE_DATA_TTON, + INNER_RELEASE_DATA_BTON, + INNER_RELEASE_DATA_TTOT, + INNER_PROBE_BLOCK_TOT, + INNER_PROBE_BLOCK_TOB, + INNER_PROBE_BLOCK_TON, + INNER_PROBE_PERM_TON, + INNER_PROBE_ACK_TTOB, + INNER_PROBE_ACK_TTON, + INNER_PROBE_ACK_BTON, + INNER_PROBE_ACK_TTOT, + INNER_PROBE_ACK_BTOB, + INNER_PROBE_ACK_NTON, + INNER_PROBE_ACK_DATA_TTOB, + INNER_PROBE_ACK_DATA_TTON, + INNER_PROBE_ACK_DATA_TTOT, + PL2_PMU_MAX_EVENT1_IDX +}; + +enum pl2_pmu_event_set2 { + INNER_PUT_FULL_DATA_HIT = 0, + INNER_PUT_PARTIAL_DATA_HIT, + INNER_ATOMIC_DATA_HIT, + INNER_GET_HIT, + INNER_PREFETCH_READ_HIT, + INNER_ACQUIRE_BLOCK_NTOB_HIT, + INNER_ACQUIRE_PERM_NTOT_HIT, + INNER_RELEASE_TTOB_HIT, + INNER_RELEASE_DATA_TTOB_HIT, + OUTER_PROBE_BLOCK_TOT_HIT, + INNER_PUT_FULL_DATA_HIT_SHARED, + INNER_PUT_PARTIAL_DATA_HIT_SHARED, + INNER_ATOMIC_DATA_HIT_SHARED, + INNER_GET_HIT_SHARED, + INNER_PREFETCH_READ_HIT_SHARED, + INNER_ACQUIRE_BLOCK_NTOB_HIT_SHARED, + INNER_ACQUIRE_PERM_NTOT_HIT_SHARED, + INNER_RELEASE_TTOB_HIT_SHARED, + INNER_RELEASE_DATA_TTOB_HIT_SHARED, + OUTER_PROBE_BLOCK_TOT_HIT_SHARED, + OUTER_PROBE_BLOCK_TOT_HIT_DIRTY, + PL2_PMU_MAX_EVENT2_IDX +}; + +enum pl2_pmu_event_set3 { + OUTER_PUT_FULL_DATA = 0, + OUTER_PUT_PARTIAL_DATA, + OUTER_ATOMIC_DATA, + OUTER_GET, + OUTER_PREFETCH_READ, + OUTER_PREFETCH_WRITE, + OUTER_ACQUIRE_BLOCK_NTOB, + OUTER_ACQUIRE_BLOCK_NTOT, + OUTER_ACQUIRE_BLOCK_BTOT, + OUTER_ACQUIRE_PERM_NTOT, + OUTER_ACQUIRE_PERM_BTOT, + OUTER_RELEARE_TTOB, + OUTER_RELEARE_TTON, + OUTER_RELEARE_BTON, + OUTER_RELEARE_DATA_TTOB, + OUTER_RELEARE_DATA_TTON, + OUTER_RELEARE_DATA_BTON, + OUTER_RELEARE_DATA_TTOT, + OUTER_PROBE_BLOCK_TOT, + OUTER_PROBE_BLOCK_TOB, + OUTER_PROBE_BLOCK_TON, + OUTER_PROBE_PERM_TON, + OUTER_PROBE_ACK_TTOB, + OUTER_PROBE_ACK_TTON, + OUTER_PROBE_ACK_BTON, + OUTER_PROBE_ACK_TTOT, + OUTER_PROBE_ACK_BTOB, + OUTER_PROBE_ACK_NTON, + OUTER_PROBE_ACK_DATA_TTOB, + OUTER_PROBE_ACK_DATA_TTON, + OUTER_PROBE_ACK_DATA_TTOT, + PL2_PMU_MAX_EVENT3_IDX +}; + +enum pl2_pmu_event_set4 { + INNER_HINT_HITS_MSHR = 0, + INNER_READ_HITS_MSHR, + INNER_WRITE_HITS_MSHR, + INNER_READ_REPLAY, + INNER_WRITE_REPLAY, + OUTER_PROBE_REPLAY, + REPLAY, + SLEEP_BY_MISS_QUEUE, + SLEEP_BY_EVICT_QUEUE, + SLEEP_FOR_BACK_PROBE, + SLEEP, + PL2_PMU_MAX_EVENT4_IDX +}; + +enum pl2_pmu_event_set5 { + READ_SLEEP_TIMER_EXPIRE = 0, + READ_OLDEST_TIMER_EXPIRE, + WRITE_SLEEP_TIMER_EXPIRE, + WRITE_OLDEST_TIMER_EXPIRE, + READ_SLEEP, + READ_DIR_UPDATE_WAKEUP, + READ_MISS_QUEUE_WAKEUP, + READ_EVICT_QUEUE_WAKEUP, + READ_SLEEP_TIMER_WAKEUP, + WRITE_SLEEP, + WRITE_DIR_UPDATE_WAKEUP, + WRITE_MISS_QUEUE_WAKEUP, + WRITE_EVICT_QUEUE_WAKEUP, + WRITE_SLEEP_TIMER_WAKEUP, + PL2_PMU_MAX_EVENT5_IDX +}; + +static struct attribute *sifive_pl2_pmu_events[] = { + PL2_PMU_EVENT_ATTR(inner_put_full_data, INNER_PUT_FULL_DATA, 1), + PL2_PMU_EVENT_ATTR(inner_put_partial_data, INNER_PUT_PARTIAL_DATA, 1), + PL2_PMU_EVENT_ATTR(inner_atomic_data, INNER_ATOMIC_DATA, 1), + PL2_PMU_EVENT_ATTR(inner_get, INNER_GET, 1), + PL2_PMU_EVENT_ATTR(inner_prefetch_read, INNER_PREFETCH_READ, 1), + PL2_PMU_EVENT_ATTR(inner_prefetch_write, INNER_PREFETCH_WRITE, 1), + PL2_PMU_EVENT_ATTR(inner_acquire_block_ntob, INNER_ACQUIRE_BLOCK_NTOB, 1), + PL2_PMU_EVENT_ATTR(inner_acquire_block_ntot, INNER_ACQUIRE_BLOCK_NTOT, 1), + PL2_PMU_EVENT_ATTR(inner_acquire_block_btot, INNER_ACQUIRE_BLOCK_BTOT, 1), + PL2_PMU_EVENT_ATTR(inner_acquire_perm_ntot, INNER_ACQUIRE_PERM_NTOT, 1), + PL2_PMU_EVENT_ATTR(inner_acquire_perm_btot, INNER_ACQUIRE_PERM_BTOT, 1), + PL2_PMU_EVENT_ATTR(inner_release_ttob, INNER_RELEASE_TTOB, 1), + PL2_PMU_EVENT_ATTR(inner_release_tton, INNER_RELEASE_TTON, 1), + PL2_PMU_EVENT_ATTR(inner_release_bton, INNER_RELEASE_BTON, 1), + PL2_PMU_EVENT_ATTR(inner_release_data_ttob, INNER_RELEASE_DATA_TTOB, 1), + PL2_PMU_EVENT_ATTR(inner_release_data_tton, INNER_RELEASE_DATA_TTON, 1), + PL2_PMU_EVENT_ATTR(inner_release_data_bton, INNER_RELEASE_DATA_BTON, 1), + PL2_PMU_EVENT_ATTR(inner_release_data_ttot, INNER_RELEASE_DATA_TTOT, 1), + PL2_PMU_EVENT_ATTR(inner_probe_block_tot, INNER_PROBE_BLOCK_TOT, 1), + PL2_PMU_EVENT_ATTR(inner_probe_block_tob, INNER_PROBE_BLOCK_TOB, 1), + PL2_PMU_EVENT_ATTR(inner_probe_block_ton, INNER_PROBE_BLOCK_TON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_perm_ton, INNER_PROBE_PERM_TON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_ttob, INNER_PROBE_ACK_TTOB, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_tton, INNER_PROBE_ACK_TTON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_bton, INNER_PROBE_ACK_BTON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_ttot, INNER_PROBE_ACK_TTOT, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_btob, INNER_PROBE_ACK_BTOB, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_nton, INNER_PROBE_ACK_NTON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_data_ttob, INNER_PROBE_ACK_DATA_TTOB, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_data_tton, INNER_PROBE_ACK_DATA_TTON, 1), + PL2_PMU_EVENT_ATTR(inner_probe_ack_data_ttot, INNER_PROBE_ACK_DATA_TTOT, 1), + + PL2_PMU_EVENT_ATTR(inner_put_full_data_hit, INNER_PUT_FULL_DATA_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_put_partial_data_hit, INNER_PUT_PARTIAL_DATA_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_atomic_data_hit, INNER_ATOMIC_DATA_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_get_hit, INNER_GET_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_prefetch_read_hit, INNER_PREFETCH_READ_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_acquire_block_ntob_hit, INNER_ACQUIRE_BLOCK_NTOB_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_acquire_perm_ntot_hit, INNER_ACQUIRE_PERM_NTOT_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_release_ttob_hit, INNER_RELEASE_TTOB_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_release_data_ttob_hit, INNER_RELEASE_DATA_TTOB_HIT, 2), + PL2_PMU_EVENT_ATTR(outer_probe_block_tot_hit, OUTER_PROBE_BLOCK_TOT_HIT, 2), + PL2_PMU_EVENT_ATTR(inner_put_full_data_hit_shared, INNER_PUT_FULL_DATA_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_put_partial_data_hit_shared, INNER_PUT_PARTIAL_DATA_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_atomic_data_hit_shared, INNER_ATOMIC_DATA_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_get_hit_shared, INNER_GET_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_prefetch_read_hit_shared, INNER_PREFETCH_READ_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_acquire_block_ntob_hit_shared, + INNER_ACQUIRE_BLOCK_NTOB_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_acquire_perm_ntot_hit_shared, + INNER_ACQUIRE_PERM_NTOT_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_release_ttob_hit_shared, INNER_RELEASE_TTOB_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(inner_release_data_ttob_hit_shared, + INNER_RELEASE_DATA_TTOB_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(outer_probe_block_tot_hit_shared, OUTER_PROBE_BLOCK_TOT_HIT_SHARED, 2), + PL2_PMU_EVENT_ATTR(outer_probe_block_tot_hit_dirty, OUTER_PROBE_BLOCK_TOT_HIT_DIRTY, 2), + + PL2_PMU_EVENT_ATTR(outer_put_full_data, OUTER_PUT_FULL_DATA, 3), + PL2_PMU_EVENT_ATTR(outer_put_partial_data, OUTER_PUT_PARTIAL_DATA, 3), + PL2_PMU_EVENT_ATTR(outer_atomic_data, OUTER_ATOMIC_DATA, 3), + PL2_PMU_EVENT_ATTR(outer_get, OUTER_GET, 3), + PL2_PMU_EVENT_ATTR(outer_prefetch_read, OUTER_PREFETCH_READ, 3), + PL2_PMU_EVENT_ATTR(outer_prefetch_write, OUTER_PREFETCH_WRITE, 3), + PL2_PMU_EVENT_ATTR(outer_acquire_block_ntob, OUTER_ACQUIRE_BLOCK_NTOB, 3), + PL2_PMU_EVENT_ATTR(outer_acquire_block_ntot, OUTER_ACQUIRE_BLOCK_NTOT, 3), + PL2_PMU_EVENT_ATTR(outer_acquire_block_btot, OUTER_ACQUIRE_BLOCK_BTOT, 3), + PL2_PMU_EVENT_ATTR(outer_acquire_perm_ntot, OUTER_ACQUIRE_PERM_NTOT, 3), + PL2_PMU_EVENT_ATTR(outer_acquire_perm_btot, OUTER_ACQUIRE_PERM_BTOT, 3), + PL2_PMU_EVENT_ATTR(outer_release_ttob, OUTER_RELEARE_TTOB, 3), + PL2_PMU_EVENT_ATTR(outer_release_tton, OUTER_RELEARE_TTON, 3), + PL2_PMU_EVENT_ATTR(outer_release_bton, OUTER_RELEARE_BTON, 3), + PL2_PMU_EVENT_ATTR(outer_release_data_ttob, OUTER_RELEARE_DATA_TTOB, 3), + PL2_PMU_EVENT_ATTR(outer_release_data_tton, OUTER_RELEARE_DATA_TTON, 3), + PL2_PMU_EVENT_ATTR(outer_release_data_bton, OUTER_RELEARE_DATA_BTON, 3), + PL2_PMU_EVENT_ATTR(outer_release_data_ttot, OUTER_RELEARE_DATA_TTOT, 3), + PL2_PMU_EVENT_ATTR(outer_probe_block_tot, OUTER_PROBE_BLOCK_TOT, 3), + PL2_PMU_EVENT_ATTR(outer_probe_block_tob, OUTER_PROBE_BLOCK_TOB, 3), + PL2_PMU_EVENT_ATTR(outer_probe_block_ton, OUTER_PROBE_BLOCK_TON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_perm_ton, OUTER_PROBE_PERM_TON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_ttob, OUTER_PROBE_ACK_TTOB, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_tton, OUTER_PROBE_ACK_TTON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_bton, OUTER_PROBE_ACK_BTON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_ttot, OUTER_PROBE_ACK_TTOT, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_btob, OUTER_PROBE_ACK_BTOB, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_nton, OUTER_PROBE_ACK_NTON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_data_ttob, OUTER_PROBE_ACK_DATA_TTOB, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_data_tton, OUTER_PROBE_ACK_DATA_TTON, 3), + PL2_PMU_EVENT_ATTR(outer_probe_ack_data_ttot, OUTER_PROBE_ACK_DATA_TTOT, 3), + + PL2_PMU_EVENT_ATTR(inner_hint_hits_mshr, INNER_HINT_HITS_MSHR, 4), + PL2_PMU_EVENT_ATTR(inner_read_hits_mshr, INNER_READ_HITS_MSHR, 4), + PL2_PMU_EVENT_ATTR(inner_write_hits_mshr, INNER_WRITE_HITS_MSHR, 4), + PL2_PMU_EVENT_ATTR(inner_read_replay, INNER_READ_REPLAY, 4), + PL2_PMU_EVENT_ATTR(inner_write_replay, INNER_WRITE_REPLAY, 4), + PL2_PMU_EVENT_ATTR(outer_probe_replay, OUTER_PROBE_REPLAY, 4), + PL2_PMU_EVENT_ATTR(replay, REPLAY, 4), + PL2_PMU_EVENT_ATTR(sleep_by_miss_queue, SLEEP_BY_MISS_QUEUE, 4), + PL2_PMU_EVENT_ATTR(sleep_by_evict_queue, SLEEP_BY_EVICT_QUEUE, 4), + PL2_PMU_EVENT_ATTR(sleep_for_back_probe, SLEEP_FOR_BACK_PROBE, 4), + PL2_PMU_EVENT_ATTR(sleep, SLEEP, 4), + + PL2_PMU_EVENT_ATTR(read_sleep_timer_expire, READ_SLEEP_TIMER_EXPIRE, 5), + PL2_PMU_EVENT_ATTR(read_oldest_timer_expire, READ_OLDEST_TIMER_EXPIRE, 5), + PL2_PMU_EVENT_ATTR(write_sleep_timer_expire, WRITE_SLEEP_TIMER_EXPIRE, 5), + PL2_PMU_EVENT_ATTR(write_oldest_timer_expire, WRITE_OLDEST_TIMER_EXPIRE, 5), + PL2_PMU_EVENT_ATTR(read_sleep, READ_SLEEP, 5), + PL2_PMU_EVENT_ATTR(read_dir_update_wakeup, READ_DIR_UPDATE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(read_miss_queue_wakeup, READ_MISS_QUEUE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(read_evict_queue_wakeup, READ_EVICT_QUEUE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(read_sleep_timer_wakeup, READ_SLEEP_TIMER_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(write_sleep, WRITE_SLEEP, 5), + PL2_PMU_EVENT_ATTR(write_dir_update_wakeup, WRITE_DIR_UPDATE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(write_miss_queue_wakeup, WRITE_MISS_QUEUE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(write_evict_queue_wakeup, WRITE_EVICT_QUEUE_WAKEUP, 5), + PL2_PMU_EVENT_ATTR(write_sleep_timer_wakeup, WRITE_SLEEP_TIMER_WAKEUP, 5), + NULL +}; + +static struct attribute_group sifive_pl2_pmu_events_group = { + .name = "events", + .attrs = sifive_pl2_pmu_events, +}; + +/* formats */ +PMU_FORMAT_ATTR(event, "config:0-63"); + +static struct attribute *sifive_pl2_pmu_formats[] = { + &format_attr_event.attr, + NULL, +}; + +static struct attribute_group sifive_pl2_pmu_format_group = { + .name = "format", + .attrs = sifive_pl2_pmu_formats, +}; + +/* + * Per PMU device attribute groups + */ + +static const struct attribute_group *sifive_pl2_pmu_attr_grps[] = { + &sifive_pl2_pmu_events_group, + &sifive_pl2_pmu_format_group, + NULL, +}; + +/* + * Event Initialization + */ + +static int sifive_pl2_pmu_event_init(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 config = event->attr.config; + u64 ev_type = config >> 8; + u64 set = config & 0xff; + + /* Check if this is a valid set and event */ + switch (set) { + case 1: + if (ev_type >= BIT_ULL(PL2_PMU_MAX_EVENT1_IDX)) + return -ENOENT; + break; + case 2: + if (ev_type >= BIT_ULL(PL2_PMU_MAX_EVENT2_IDX)) + return -ENOENT; + break; + case 3: + if (ev_type >= BIT_ULL(PL2_PMU_MAX_EVENT3_IDX)) + return -ENOENT; + break; + case 4: + if (ev_type >= BIT_ULL(PL2_PMU_MAX_EVENT4_IDX)) + return -ENOENT; + break; + case 5: + if (ev_type >= BIT_ULL(PL2_PMU_MAX_EVENT5_IDX)) + return -ENOENT; + break; + default: + return -ENOENT; + } + + /* Do not allocate the hardware counter yet */ + hwc->idx = -1; + hwc->config = config; + + return 0; +} + +/* + * pmu->read: read and update the counter + */ +static void sifive_pl2_pmu_read(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 prev_raw_count, new_raw_count; + u64 oldval; + + do { + prev_raw_count = local64_read(&hwc->prev_count); + new_raw_count = readq((void *)hwc->event_base); + + oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count, new_raw_count); + } while (oldval != prev_raw_count); + + local64_add(new_raw_count - prev_raw_count, &event->count); +} + +/* + * State transition functions: + * + * start()/stop() & add()/del() + */ + +/* + * pmu->start: start the event + */ +static void sifive_pl2_pmu_start(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + hwc->state = 0; + + /* Set initial value to 0 */ + local64_set(&hwc->prev_count, 0); + writeq(0, (void *)hwc->event_base); + + /* Enable this counter to count events */ + writeq(hwc->config, (void *)hwc->config_base); +} + +/* + * pmu->stop: stop the counter + */ +static void sifive_pl2_pmu_stop(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (hwc->state & PERF_HES_STOPPED) + return; + + /* Disable this counter to count events */ + writeq(0, (void *)hwc->config_base); + sifive_pl2_pmu_read(event); + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; +} + +/* + * pmu->add: add the event to the PMU + */ +static int sifive_pl2_pmu_add(struct perf_event *event, int flags) +{ + struct sifive_pl2_pmu *pl2_pmu = to_pl2_pmu(event->pmu); + struct sifive_pl2_pmu_event *ptr = *this_cpu_ptr(pl2_pmu->event); + struct hw_perf_event *hwc = &event->hw; + int idx; + + /* Find an available counter idx to use for this event */ + do { + idx = find_first_zero_bit(ptr->used_mask, ptr->n_counters); + if (idx >= ptr->n_counters) + return -EAGAIN; + } while (test_and_set_bit(idx, ptr->used_mask)); + + hwc->config_base = (unsigned long)ptr->base + PL2_SELECT_OFFSET + 8 * idx; + hwc->event_base = (unsigned long)ptr->base + PL2_COUNTER_OFFSET + 8 * idx; + hwc->idx = idx; + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + ptr->events[idx] = event; + + if (flags & PERF_EF_START) + sifive_pl2_pmu_start(event, PERF_EF_RELOAD); + + perf_event_update_userpage(event); + + return 0; +} + +/* + * pmu->del: delete the event from the PMU + */ +static void sifive_pl2_pmu_del(struct perf_event *event, int flags) +{ + struct sifive_pl2_pmu *pl2_pmu = to_pl2_pmu(event->pmu); + struct sifive_pl2_pmu_event *ptr = *this_cpu_ptr(pl2_pmu->event); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; + + /* Stop and release this counter */ + sifive_pl2_pmu_stop(event, PERF_EF_UPDATE); + + ptr->events[idx] = NULL; + clear_bit(idx, ptr->used_mask); + + perf_event_update_userpage(event); +} + +/* + * pmu->filter: check if the PMU can be used with a CPU + */ +static bool sifive_pl2_pmu_filter(struct pmu *pmu, int cpu) +{ + struct sifive_pl2_pmu *pl2_pmu = to_pl2_pmu(pmu); + struct sifive_pl2_pmu_event *ptr = *this_cpu_ptr(pl2_pmu->event); + + /* Filter out CPUs with no PL2 instance (no percpu data allocated) */ + return !ptr; +} + +/* + * Driver initialization + */ + +static void sifive_pl2_pmu_hw_init(const struct sifive_pl2_pmu_event *ptr) +{ + /* Disable the client filter (not supported by this driver) */ + writeq(0, ptr->base + PL2_CLIENT_FILTER_OFFSET); +} + +static int sifive_pl2_pmu_pm_notify(struct notifier_block *nb, unsigned long cmd, void *v) +{ + struct sifive_pl2_pmu *pl2_pmu = container_of(nb, struct sifive_pl2_pmu, cpu_pm_nb); + struct sifive_pl2_pmu_event *ptr = *this_cpu_ptr(pl2_pmu->event); + struct perf_event *event; + + if (!ptr || bitmap_empty(ptr->used_mask, PL2_PMU_MAX_COUNTERS)) + return NOTIFY_OK; + + for (int idx = 0; idx < ptr->n_counters; idx++) { + event = ptr->events[idx]; + if (!event) + continue; + + switch (cmd) { + case CPU_PM_ENTER: + /* Stop and update the counter */ + sifive_pl2_pmu_stop(event, PERF_EF_UPDATE); + break; + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + /* Restore and enable the counter */ + sifive_pl2_pmu_start(event, PERF_EF_RELOAD); + break; + default: + break; + } + } + + return NOTIFY_OK; +} + +static int sifive_pl2_pmu_pm_register(struct sifive_pl2_pmu *pl2_pmu) +{ + if (!IS_ENABLED(CONFIG_CPU_PM)) + return 0; + + pl2_pmu->cpu_pm_nb.notifier_call = sifive_pl2_pmu_pm_notify; + return cpu_pm_register_notifier(&pl2_pmu->cpu_pm_nb); +} + +static void sifive_pl2_pmu_pm_unregister(struct sifive_pl2_pmu *pl2_pmu) +{ + if (!IS_ENABLED(CONFIG_CPU_PM)) + return; + + cpu_pm_unregister_notifier(&pl2_pmu->cpu_pm_nb); +} + +static struct sifive_pl2_pmu *sifive_pl2_pmu_get(void) +{ + struct sifive_pl2_pmu *pl2_pmu; + int ret; + + guard(mutex)(&g_mutex); + + pl2_pmu = g_pl2_pmu; + if (pl2_pmu) { + refcount_inc(&pl2_pmu->refcount); + return pl2_pmu; + } + + pl2_pmu = kzalloc(sizeof(*pl2_pmu), GFP_KERNEL); + if (!pl2_pmu) + return ERR_PTR(-ENOMEM); + + pl2_pmu->pmu = (struct pmu) { + .attr_groups = sifive_pl2_pmu_attr_grps, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, + .task_ctx_nr = perf_sw_context, + .event_init = sifive_pl2_pmu_event_init, + .add = sifive_pl2_pmu_add, + .del = sifive_pl2_pmu_del, + .start = sifive_pl2_pmu_start, + .stop = sifive_pl2_pmu_stop, + .read = sifive_pl2_pmu_read, + .filter = sifive_pl2_pmu_filter, + }; + + refcount_set(&pl2_pmu->refcount, 1); + + pl2_pmu->event = alloc_percpu(typeof(*pl2_pmu->event)); + if (!pl2_pmu->event) { + ret = -ENOMEM; + goto err_free; + } + + ret = sifive_pl2_pmu_pm_register(pl2_pmu); + if (ret) + goto err_free_percpu; + + ret = perf_pmu_register(&pl2_pmu->pmu, "sifive_pl2_pmu", -1); + if (ret) { + pr_err("%s: Failed to register PMU: %d\n", __func__, ret); + goto err_unregister_pm; + } + + g_pl2_pmu = pl2_pmu; + + return pl2_pmu; + +err_unregister_pm: + sifive_pl2_pmu_pm_unregister(pl2_pmu); +err_free_percpu: + free_percpu(pl2_pmu->event); +err_free: + kfree(pl2_pmu); + + return ERR_PTR(ret); +} + +static void sifive_pl2_pmu_put(void) +{ + struct sifive_pl2_pmu *pl2_pmu; + + guard(mutex)(&g_mutex); + + pl2_pmu = g_pl2_pmu; + if (!refcount_dec_and_test(&pl2_pmu->refcount)) + return; + + g_pl2_pmu = NULL; + perf_pmu_unregister(&pl2_pmu->pmu); + sifive_pl2_pmu_pm_unregister(pl2_pmu); + free_percpu(pl2_pmu->event); + kfree(pl2_pmu); +} + +static int sifive_pl2_pmu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev_of_node(dev); + struct sifive_pl2_pmu_event *ptr; + struct sifive_pl2_pmu *pl2_pmu; + unsigned int cpu; + u32 n_counters; + int ret; + + /* Instances without a sifive,perfmon-counters property do not contain a PMU */ + ret = of_property_read_u32(np, "sifive,perfmon-counters", &n_counters); + if (ret || !n_counters) + return -ENODEV; + + /* Determine the CPU affinity of this PL2 instance */ + for_each_possible_cpu(cpu) { + struct device_node *cache_node, *cpu_node; + + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + continue; + + cache_node = of_parse_phandle(cpu_node, "next-level-cache", 0); + of_node_put(cpu_node); + if (!cache_node) + continue; + + of_node_put(cache_node); + if (cache_node == np) + break; + } + if (cpu >= nr_cpu_ids) + return -ENODEV; + + ptr = devm_kzalloc(dev, struct_size(ptr, events, n_counters), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + platform_set_drvdata(pdev, ptr); + + ptr->cpu = cpu; + ptr->n_counters = n_counters; + + ptr->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ptr->base)) + return PTR_ERR(ptr->base); + + sifive_pl2_pmu_hw_init(ptr); + + pl2_pmu = sifive_pl2_pmu_get(); + if (IS_ERR(pl2_pmu)) + return PTR_ERR(pl2_pmu); + + *per_cpu_ptr(pl2_pmu->event, cpu) = ptr; + + return 0; +} + +static void sifive_pl2_pmu_remove(struct platform_device *pdev) +{ + struct sifive_pl2_pmu_event *ptr = platform_get_drvdata(pdev); + + *per_cpu_ptr(g_pl2_pmu->event, ptr->cpu) = NULL; + sifive_pl2_pmu_put(); +} + +static const struct of_device_id sifve_pl2_pmu_of_match[] = { + { .compatible = "sifive,pl2cache1" }, + {} +}; +MODULE_DEVICE_TABLE(of, sifve_pl2_pmu_of_match); + +static struct platform_driver sifive_pl2_pmu_driver = { + .probe = sifive_pl2_pmu_probe, + .remove_new = sifive_pl2_pmu_remove, + .driver = { + .name = "sifive_pl2_pmu", + .of_match_table = sifve_pl2_pmu_of_match, + }, +}; +module_platform_driver(sifive_pl2_pmu_driver); + +MODULE_LICENSE("GPL");