From: Richard Cheng <icheng@nvidia.com>
To: Davidlohr Bueso <dave@stgolabs.net>
Cc: jic23@kernel.org, will@kernel.org, mark.rutland@arm.com,
harshal.t@samsung.com, linux-cxl@vger.kernel.org,
linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v2 1/2] perf/cxlpmu: Support Channel/Rank/Bank filter
Date: Thu, 9 Jul 2026 17:16:53 +0800 [thread overview]
Message-ID: <ak9lQFNDiWAr2GUE@MWDK4CY14F> (raw)
In-Reply-To: <20260630235002.253297-2-dave@stgolabs.net>
On Tue, Jun 30, 2026 at 04:50:01PM +0800, Davidlohr Bueso wrote:
> From: Harshal Thakkar <harshal.t@samsung.com>
>
> Implement CRB filtering per CXL 4.0 8.2.7.2.2, and extend the
> current filtering support beyond HDM. These filters are only for
> DDR Interface events.
>
> Placing the 32-bit CRB value at config2:32-63 leaves the
> existing HDM value at config2:0-15 untouched and avoids needing
> a new config3.
>
> Signed-off-by: Harshal Thakkar <harshal.t@samsung.com>
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
> ---
> drivers/perf/cxl_pmu.c | 47 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 44 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
> index 68a54d97d2a8..58c15680f299 100644
> --- a/drivers/perf/cxl_pmu.c
> +++ b/drivers/perf/cxl_pmu.c
> @@ -106,6 +106,7 @@ struct cxl_pmu_info {
> int on_cpu;
> struct hlist_node node;
> bool filter_hdm;
> + bool filter_chan_rank_bank;
> int irq;
> };
>
> @@ -142,6 +143,8 @@ static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info)
> info->num_event_capabilities = FIELD_GET(CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK, val) + 1;
>
> info->filter_hdm = FIELD_GET(CXL_PMU_CAP_FILTERS_SUP_MSK, val) & CXL_PMU_FILTER_HDM;
> + info->filter_chan_rank_bank = FIELD_GET(CXL_PMU_CAP_FILTERS_SUP_MSK, val) &
> + CXL_PMU_FILTER_CHAN_RANK_BANK;
> if (FIELD_GET(CXL_PMU_CAP_INT, val))
> info->irq = FIELD_GET(CXL_PMU_CAP_MSI_N_MSK, val);
> else
> @@ -225,6 +228,8 @@ enum {
> cxl_pmu_edge_attr,
> cxl_pmu_hdm_filter_en_attr,
> cxl_pmu_hdm_attr,
> + cxl_pmu_crb_filter_en_attr,
> + cxl_pmu_crb_attr,
> };
>
> static struct attribute *cxl_pmu_format_attr[] = {
> @@ -236,6 +241,8 @@ static struct attribute *cxl_pmu_format_attr[] = {
> [cxl_pmu_edge_attr] = CXL_PMU_FORMAT_ATTR(edge, "config1:17"),
> [cxl_pmu_hdm_filter_en_attr] = CXL_PMU_FORMAT_ATTR(hdm_filter_en, "config1:18"),
> [cxl_pmu_hdm_attr] = CXL_PMU_FORMAT_ATTR(hdm, "config2:0-15"),
> + [cxl_pmu_crb_filter_en_attr] = CXL_PMU_FORMAT_ATTR(crb_filter_en, "config1:19"),
> + [cxl_pmu_crb_attr] = CXL_PMU_FORMAT_ATTR(crb, "config2:32-63"),
> NULL
> };
>
> @@ -246,7 +253,9 @@ static struct attribute *cxl_pmu_format_attr[] = {
> #define CXL_PMU_ATTR_CONFIG1_INVERT_MSK BIT(16)
> #define CXL_PMU_ATTR_CONFIG1_EDGE_MSK BIT(17)
> #define CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK BIT(18)
> +#define CXL_PMU_ATTR_CONFIG1_CRB_FILTER_EN_MSK BIT(19)
> #define CXL_PMU_ATTR_CONFIG2_HDM_MSK GENMASK(15, 0)
> +#define CXL_PMU_ATTR_CONFIG2_CRB_MSK GENMASK_ULL(63, 32)
>
> static umode_t cxl_pmu_format_is_visible(struct kobject *kobj,
> struct attribute *attr, int a)
> @@ -263,6 +272,11 @@ static umode_t cxl_pmu_format_is_visible(struct kobject *kobj,
> attr == cxl_pmu_format_attr[cxl_pmu_hdm_attr]))
> return 0;
>
> + if (!info->filter_chan_rank_bank &&
> + (attr == cxl_pmu_format_attr[cxl_pmu_crb_filter_en_attr] ||
> + attr == cxl_pmu_format_attr[cxl_pmu_crb_attr]))
> + return 0;
> +
> return attr->mode;
> }
>
> @@ -319,6 +333,17 @@ static u16 cxl_pmu_config2_get_hdm_decoder(struct perf_event *event)
> return FIELD_GET(CXL_PMU_ATTR_CONFIG2_HDM_MSK, event->attr.config2);
> }
>
> +static u16 cxl_pmu_config1_crb_filter_en(struct perf_event *event)
> +{
> + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_CRB_FILTER_EN_MSK,
> + event->attr.config1);
> +}
> +
> +static u32 cxl_pmu_config2_get_crb(struct perf_event *event)
> +{
> + return FIELD_GET(CXL_PMU_ATTR_CONFIG2_CRB_MSK, event->attr.config2);
> +}
> +
> static ssize_t cxl_pmu_event_sysfs_show(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> @@ -571,6 +596,14 @@ static int cxl_pmu_event_init(struct perf_event *event)
> return -EOPNOTSUPP;
> /* TODO: Validation of any filter */
>
> + if (cxl_pmu_config1_crb_filter_en(event)) {
> + if (!info->filter_chan_rank_bank)
> + return -EINVAL;
> + /* only valid for DDR Interface events */
> + if (cxl_pmu_config_get_gid(event) != CXL_PMU_GID_DDR)
> + return -EINVAL;
> + }
> +
Hi Davidlohr,
Would this be too strict ?
In CXL 4.0, Table 13-5 "Events under CXL Vendor ID", Section 13.2 "Performance Monitoring"
Filter ID 1 is also permitted for Queue Occupancy (8001h), Queue Residency (8002h)
and Retry Events (8003h).
With this change, when we do something like
"""
perf stat -e cxl_pmu/rd_queue_occ,crb_filter_en=1,crb=0x5/
"""
It will fail with -EINVAL, even though the sepc allows Filter ID 1 for that
event group.
> /*
> * Verify that it is possible to count what was requested. Either must
> * be a fixed counter that is a precise match or a configurable counter
> @@ -627,15 +660,23 @@ static void cxl_pmu_event_start(struct perf_event *event, int flags)
> hwc->state = 0;
>
> /*
> - * Currently only hdm filter control is implemented, this code will
> - * want generalizing when more filters are added.
> + * Filter ID=0: HDM decoder filter
> + * Filter ID=1: Channel/Rank/Bank (CRB) filter
> */
> if (info->filter_hdm) {
> if (cxl_pmu_config1_hdm_filter_en(event))
> cfg = cxl_pmu_config2_get_hdm_decoder(event);
> else
> cfg = GENMASK(31, 0); /* No filtering if 0xFFFF_FFFF */
> - writeq(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 0));
> + writel(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 0));
> + }
This is a real bug fix on its own.
The old 64-bit write also wrote 0 into the Filter ID 1 register at offset+4,
and per Table 8-186 0 there means "filter to hannel/rank/bank 0", not disable.
So on hardware that supports both filters, current kernel silently undercount.
Woth splitting into its own patch so it can be backported without the new
feature.
Best regards,
Richard Cheng.
> +
> + if (info->filter_chan_rank_bank) {
> + if (cxl_pmu_config1_crb_filter_en(event))
> + cfg = cxl_pmu_config2_get_crb(event);
> + else
> + cfg = GENMASK(31, 0); /* no filtering if 0xFFFF_FFFF */
> + writel(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 1));
> }
>
> cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
> --
> 2.39.5
>
>
next prev parent reply other threads:[~2026-07-09 9:17 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 23:50 [PATCH 0/2] perf/cxlpmu: Misc updates Davidlohr Bueso
2026-06-30 23:50 ` [PATCH v2 1/2] perf/cxlpmu: Support Channel/Rank/Bank filter Davidlohr Bueso
2026-07-01 1:55 ` sashiko-bot
2026-07-09 9:16 ` Richard Cheng [this message]
2026-06-30 23:50 ` [PATCH 2/2] perf/cxlpmu: Add missing CXL 4.0 events Davidlohr Bueso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ak9lQFNDiWAr2GUE@MWDK4CY14F \
--to=icheng@nvidia.com \
--cc=dave@stgolabs.net \
--cc=harshal.t@samsung.com \
--cc=jic23@kernel.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox