* [PATCH] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5
@ 2026-05-03 15:51 Aviv Bakal
2026-05-04 13:39 ` [PATCH v2] " Aviv Bakal
0 siblings, 1 reply; 4+ messages in thread
From: Aviv Bakal @ 2026-05-03 15:51 UTC (permalink / raw)
To: robin.murphy, will, mark.rutland
Cc: linux-arm-kernel, linux-perf-users, linux-kernel, avivb, zeev,
blakgeof
Graviton5 uses a customised CMN-S3 implementation where certain
discovery registers report zeroed fields. Add the following workarounds:
- Introduce a dedicated ACPI HID to identify the Graviton5 CMN variant.
- Derive the DTC domain from the XP node ID, since the unit info
register reports it as zero.
- Set the DTC logical ID from the XP's logical ID, since the node info
register's logical ID field is also zeroed.
Signed-off-by: Aviv Bakal <avivb@amazon.com>
---
drivers/perf/arm-cmn.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index f5305c8fdca4..368fe1a86bfb 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -31,7 +31,8 @@
#define CMN_CHILD_NODE_ADDR GENMASK(29, 0)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
-#define CMN_MAX_DIMENSION 12
+/* Some implementations use a mesh larger than the architectural max of 12 */
+#define CMN_MAX_DIMENSION 14
#define CMN_MAX_XPS (CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
@@ -214,6 +215,8 @@ enum cmn_part {
PART_CMN700 = 0x43c,
PART_CI700 = 0x43a,
PART_CMN_S3 = 0x43e,
+ /* Synthetic part number, overridden to PART_CMN_S3 during discovery */
+ PART_GRAVITON5 = 0xa5,
};
/* CMN-600 r0px shouldn't exist in silicon, thankfully */
@@ -2221,6 +2224,18 @@ static unsigned int arm_cmn_dtc_domain(struct arm_cmn *cmn, void __iomem *xp_reg
return FIELD_GET(CMN_DTM_UNIT_INFO_DTC_DOMAIN, readl_relaxed(xp_region + offset));
}
+static unsigned int arm_cmn_graviton5_dtc_domain(u16 xp_id)
+{
+ unsigned int x = (xp_id >> 7) & 0xf;
+ unsigned int y = (xp_id >> 3) & 0xf;
+
+ /*
+ * The unit info register reads as zero; derive the DTC domain from
+ * the XP's mesh coordinates over the 10x14 mesh.
+ */
+ return (x / 5) + (y / 7) * 2;
+}
+
static void arm_cmn_init_node_info(struct arm_cmn *cmn, u32 offset, struct arm_cmn_node *node)
{
int level;
@@ -2266,6 +2281,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
u64 reg;
int i, j;
size_t sz;
+ bool graviton5_workaround = false;
arm_cmn_init_node_info(cmn, rgn_offset, &cfg);
if (cfg.type != CMN_TYPE_CFG)
@@ -2276,6 +2292,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
reg = readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01);
part = FIELD_GET(CMN_CFGM_PID0_PART_0, reg);
part |= FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8;
+
+ /* Graviton5 has a customised CMN-S3 which needs some fixups */
+ if (cmn->part == PART_GRAVITON5) {
+ cmn->part = PART_CMN_S3;
+ graviton5_workaround = true;
+ }
+
/* 600AE is close enough that it's not really worth more complexity */
if (part == PART_CMN600AE)
part = PART_CMN600;
@@ -2365,6 +2388,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (cmn->part == PART_CMN600)
xp->dtc = -1;
+ else if (graviton5_workaround)
+ xp->dtc = arm_cmn_graviton5_dtc_domain(xp->id);
else
xp->dtc = arm_cmn_dtc_domain(cmn, xp_region);
@@ -2443,6 +2468,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
switch (dn->type) {
case CMN_TYPE_DTC:
+ if (graviton5_workaround) {
+ /* Node info logical ID is zeroed; use the XP's */
+ dn->logid = xp->logid;
+ }
cmn->num_dtcs++;
dn++;
break;
@@ -2658,6 +2687,7 @@ static const struct acpi_device_id arm_cmn_acpi_match[] = {
{ "ARMHC650" },
{ "ARMHC700" },
{ "ARMHC003" },
+ { "AMZN0070", PART_GRAVITON5 },
{}
};
MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match);
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v2] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5
2026-05-03 15:51 [PATCH] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5 Aviv Bakal
@ 2026-05-04 13:39 ` Aviv Bakal
2026-05-05 2:31 ` kernel test robot
0 siblings, 1 reply; 4+ messages in thread
From: Aviv Bakal @ 2026-05-04 13:39 UTC (permalink / raw)
To: robin.murphy, will, mark.rutland
Cc: linux-arm-kernel, linux-perf-users, linux-kernel, zeev, blakgeof
Graviton5 uses a customised CMN-S3 implementation where certain
discovery registers report zeroed fields. Add the following workarounds:
- Introduce a dedicated ACPI HID to identify the Graviton5 CMN variant.
- Derive the DTC domain from the XP node ID, since the unit info
register reports it as zero.
- Set the DTC logical ID from the computed domain ID, since the node
info register's logical ID field is also zeroed.
Signed-off-by: Aviv Bakal <avivb@amazon.com>
---
v2:
- Use computed domain ID (xp->dtc) instead of XP logical ID for DTC
logical ID assignment.
drivers/perf/arm-cmn.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index f5305c8fdca4..8ee3f8638602 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -31,7 +31,8 @@
#define CMN_CHILD_NODE_ADDR GENMASK(29, 0)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
-#define CMN_MAX_DIMENSION 12
+/* Some implementations use a mesh larger than the architectural max of 12 */
+#define CMN_MAX_DIMENSION 14
#define CMN_MAX_XPS (CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
@@ -214,6 +215,8 @@ enum cmn_part {
PART_CMN700 = 0x43c,
PART_CI700 = 0x43a,
PART_CMN_S3 = 0x43e,
+ /* Synthetic part number, overridden to PART_CMN_S3 during discovery */
+ PART_GRAVITON5 = 0xa5,
};
/* CMN-600 r0px shouldn't exist in silicon, thankfully */
@@ -2221,6 +2224,18 @@ static unsigned int arm_cmn_dtc_domain(struct arm_cmn *cmn, void __iomem *xp_reg
return FIELD_GET(CMN_DTM_UNIT_INFO_DTC_DOMAIN, readl_relaxed(xp_region + offset));
}
+static unsigned int arm_cmn_graviton5_dtc_domain(u16 xp_id)
+{
+ unsigned int x = (xp_id >> 7) & 0xf;
+ unsigned int y = (xp_id >> 3) & 0xf;
+
+ /*
+ * The unit info register reads as zero; derive the DTC domain from
+ * the XP's mesh coordinates over the 10x14 mesh.
+ */
+ return (x / 5) + (y / 7) * 2;
+}
+
static void arm_cmn_init_node_info(struct arm_cmn *cmn, u32 offset, struct arm_cmn_node *node)
{
int level;
@@ -2266,6 +2281,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
u64 reg;
int i, j;
size_t sz;
+ bool graviton5_workaround = false;
arm_cmn_init_node_info(cmn, rgn_offset, &cfg);
if (cfg.type != CMN_TYPE_CFG)
@@ -2276,6 +2292,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
reg = readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01);
part = FIELD_GET(CMN_CFGM_PID0_PART_0, reg);
part |= FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8;
+
+ /* Graviton5 has a customised CMN-S3 which needs some fixups */
+ if (cmn->part == PART_GRAVITON5) {
+ cmn->part = PART_CMN_S3;
+ graviton5_workaround = true;
+ }
+
/* 600AE is close enough that it's not really worth more complexity */
if (part == PART_CMN600AE)
part = PART_CMN600;
@@ -2365,6 +2388,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (cmn->part == PART_CMN600)
xp->dtc = -1;
+ else if (graviton5_workaround)
+ xp->dtc = arm_cmn_graviton5_dtc_domain(xp->id);
else
xp->dtc = arm_cmn_dtc_domain(cmn, xp_region);
@@ -2443,6 +2468,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
switch (dn->type) {
case CMN_TYPE_DTC:
+ if (graviton5_workaround) {
+ /* Node info logical ID is zeroed; use the domain ID */
+ dn->logid = xp->dtc;
+ }
cmn->num_dtcs++;
dn++;
break;
@@ -2658,6 +2687,7 @@ static const struct acpi_device_id arm_cmn_acpi_match[] = {
{ "ARMHC650" },
{ "ARMHC700" },
{ "ARMHC003" },
+ { "AMZN0070", PART_GRAVITON5 },
{}
};
MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match);
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5
2026-05-04 13:39 ` [PATCH v2] " Aviv Bakal
@ 2026-05-05 2:31 ` kernel test robot
0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2026-05-05 2:31 UTC (permalink / raw)
To: Aviv Bakal, robin.murphy, will, mark.rutland
Cc: llvm, oe-kbuild-all, linux-arm-kernel, linux-perf-users,
linux-kernel, zeev, blakgeof
Hi Aviv,
kernel test robot noticed the following build errors:
[auto build test ERROR on arm-perf/for-next/perf]
[also build test ERROR on soc/for-next linus/master v7.1-rc2 next-20260430]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Aviv-Bakal/perf-arm-cmn-Add-workarounds-for-CMN-S3-on-Graviton5/20260505-011858
base: https://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git for-next/perf
patch link: https://lore.kernel.org/r/20260504133923.23373-1-avivb%40amazon.com
patch subject: [PATCH v2] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5
config: i386-buildonly-randconfig-004-20260505 (https://download.01.org/0day-ci/archive/20260505/202605051052.zOemYJY9-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260505/202605051052.zOemYJY9-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605051052.zOemYJY9-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/perf/arm-cmn.c:617:15: error: static assertion failed due to requirement 'sizeof(struct arm_cmn_hw_event) <= __builtin_offsetof(struct hw_perf_event, target)': sizeof(struct arm_cmn_hw_event) <= offsetof(struct hw_perf_event, target)
617 | static_assert(sizeof(struct arm_cmn_hw_event) <= offsetof(struct hw_perf_event, target));
| ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:77:50: note: expanded from macro 'static_assert'
77 | #define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: expanded from macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
drivers/perf/arm-cmn.c:617:47: note: expression evaluates to '104 <= 96'
617 | static_assert(sizeof(struct arm_cmn_hw_event) <= offsetof(struct hw_perf_event, target));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:77:50: note: expanded from macro 'static_assert'
77 | #define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: expanded from macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
1 error generated.
vim +617 drivers/perf/arm-cmn.c
a88fa6c28b867a Robin Murphy 2021-12-03 600
0ba64770a2f2e5 Robin Murphy 2020-09-18 601 struct arm_cmn_hw_event {
0ba64770a2f2e5 Robin Murphy 2020-09-18 602 struct arm_cmn_node *dn;
359414b33e00ba Robin Murphy 2024-09-02 603 u64 dtm_idx[DIV_ROUND_UP(CMN_MAX_NODES_PER_EVENT * 2, 64)];
7633ec2c262fab Robin Murphy 2023-10-20 604 s8 dtc_idx[CMN_MAX_DTCS];
0ba64770a2f2e5 Robin Murphy 2020-09-18 605 u8 num_dns;
60d1504070c22c Robin Murphy 2021-12-03 606 u8 dtm_offset;
4a112585ebe8cb Ilkka Koskinen 2024-06-17 607
4a112585ebe8cb Ilkka Koskinen 2024-06-17 608 /*
4a112585ebe8cb Ilkka Koskinen 2024-06-17 609 * WP config registers are divided to UP and DOWN events. We need to
4a112585ebe8cb Ilkka Koskinen 2024-06-17 610 * keep to track only one of them.
4a112585ebe8cb Ilkka Koskinen 2024-06-17 611 */
4a112585ebe8cb Ilkka Koskinen 2024-06-17 612 DECLARE_BITMAP(wp_idx, CMN_MAX_XPS);
4a112585ebe8cb Ilkka Koskinen 2024-06-17 613
23760a0144173e Robin Murphy 2022-04-18 614 bool wide_sel;
65adf71398f5af Robin Murphy 2022-04-18 615 enum cmn_filter_select filter_sel;
0ba64770a2f2e5 Robin Murphy 2020-09-18 616 };
ff436cee694ee8 Robin Murphy 2024-09-02 @617 static_assert(sizeof(struct arm_cmn_hw_event) <= offsetof(struct hw_perf_event, target));
0ba64770a2f2e5 Robin Murphy 2020-09-18 618
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <20260503162039.E185EC2BCB4@smtp.kernel.org>]
* Re: [PATCH] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5
[not found] <20260503162039.E185EC2BCB4@smtp.kernel.org>
@ 2026-05-04 13:37 ` Aviv Bakal
0 siblings, 0 replies; 4+ messages in thread
From: Aviv Bakal @ 2026-05-04 13:37 UTC (permalink / raw)
To: sashiko-bot
Cc: robin.murphy, will, mark.rutland, linux-arm-kernel,
linux-perf-users, linux-kernel, zeev, blakgeof
> Will this cross-wire the DTC domains?
> In arm_cmn_init_dtcs(), the cmn->dns array is sorted by logid, and the
> cmn->dtc array is populated sequentially based on this sorted order.
> During PMU event programming, the driver uses the domain ID (dn->dtc) as an
> index into the cmn->dtc array.
> If the physical layout of the DTC XPs causes their xp->logid values (typically
> y * mesh_x + x) to sort differently than their computed domain IDs, wouldn't
> the cmn->dtc array be misaligned?
> For example, a Domain 1 DTC at (5,0) has a smaller logid (5) than a Domain 0
> DTC at (0,6) (60), meaning Domain 1 would incorrectly occupy cmn->dtc[0]. This
> cross-wiring could cause PMU events to program the wrong physical DTC hardware
> and map IRQs to the wrong domains, resulting in incorrect performance
> statistics and unhandled interrupts.
> Would it be better to assign the computed domain ID to the logical ID here
> using dn->logid = xp->dtc?
Good catch on the cleanliness — I'll switch to dn->logid = xp->dtc.
That said, the two approaches are equivalent on this hardware. The four
DTCs discovered on Graviton5 are:
pmu_base xp->dtc xp->logid
c030d900 0 0
e430d900 1 9
c370d900 2 130
e770d900 3 139
The xp->logid values (0, 9, 130, 139) sort in the same order as the
domain IDs (0, 1, 2, 3), so arm_cmn_node_cmp produces the same sorted
sequence either way, and dtc_idx++ assigns the same indices.
This follows from the topology: arm_cmn_graviton5_dtc_domain() computes
domain = (x/5) + (y/7)*2 over the 10x14 mesh, which increases
monotonically with the row-major XP position that logid encodes. So the
sort orders can't diverge for this mesh geometry.
Still, using xp->dtc is cleaner and more obviously correct — the logid
directly reflects the domain ID rather than relying on sort-order
equivalence. I'll update the patch.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-05 2:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-03 15:51 [PATCH] perf/arm-cmn: Add workarounds for CMN-S3 on Graviton5 Aviv Bakal
2026-05-04 13:39 ` [PATCH v2] " Aviv Bakal
2026-05-05 2:31 ` kernel test robot
[not found] <20260503162039.E185EC2BCB4@smtp.kernel.org>
2026-05-04 13:37 ` [PATCH] " Aviv Bakal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox