From ff9124c53fb4b22c30403b7f9f51385dd11f84d8 Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Mon, 1 Jun 2026 11:21:12 +0800 Subject: [PATCH] platform: xuantie: Harden xuantie link pmu init Several robustness fixes in xuantie_link_pmu_device_init(): - Use `>= 0` to validate fdt_node_offset_by_compatible() result; the previous `> 0` check would miss a node at offset 0. - Iterate all instances of each PMU compatible instead of only the first one, so multi-cluster SoCs initialise every L3 PMU. - Skip nodes with status = "disabled" via fdt_node_is_enabled(). - Default-inhibit all counters (matches the kernel driver probe behaviour) so counters do not free-run between OpenSBI and kernel handoff. - Replace magic numbers with named macros (CNT_BITMAP, AUTHCR_AUTH, AUTHCR_INTPEND). - Bail out early if fdt_get_address_rw() returns NULL. Signed-off-by: Chen Pei --- .../generic/include/xuantie/xuantie_link.h | 5 ++ platform/generic/xuantie/xuantie_link.c | 55 +++++++++++++------ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/platform/generic/include/xuantie/xuantie_link.h b/platform/generic/include/xuantie/xuantie_link.h index 02b113f8..ebce8c64 100644 --- a/platform/generic/include/xuantie/xuantie_link.h +++ b/platform/generic/include/xuantie/xuantie_link.h @@ -28,6 +28,11 @@ #define XUANTIE_LINK_PMU_HPCPINTPEND 0x5e8 #define XUANTIE_LINK_PMU_VENDOR_N_IMP_ID 0x600 // XL300 +#define XUANTIE_LINK_PMU_NUM_COUNTERS 6 +#define XUANTIE_LINK_PMU_CNT_BITMAP GENMASK_ULL(XUANTIE_LINK_PMU_NUM_COUNTERS - 1, 0) +#define XUANTIE_LINK_PMU_AUTHCR_AUTH BIT_ULL(40) +#define XUANTIE_LINK_PMU_AUTHCR_INTPEND BIT_ULL(32) + /* HPCP dev type */ #define XUANTIE_LINK_DEV_TYPE_XL100 100 #define XUANTIE_LINK_DEV_TYPE_XL200 200 diff --git a/platform/generic/xuantie/xuantie_link.c b/platform/generic/xuantie/xuantie_link.c index 89c86ac9..0093b7e9 100644 --- a/platform/generic/xuantie/xuantie_link.c +++ b/platform/generic/xuantie/xuantie_link.c @@ -12,29 +12,48 @@ int xuantie_link_pmu_device_init(void) { #if __riscv_xlen == 64 - int nodeoffset, rc, dev_type; - uint64_t addr; + static const struct { + const char *compat; + int dev_type; + } pmu_match[] = { + { "xuantie,xl100-pmu", XUANTIE_LINK_DEV_TYPE_XL100 }, + { "xuantie,xl200-pmu", XUANTIE_LINK_DEV_TYPE_XL200 }, + { "xuantie,xl300-pmu", XUANTIE_LINK_DEV_TYPE_XL300 }, + }; void *fdt = fdt_get_address_rw(); + bool found = false; + unsigned int i; - if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl100-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL100; - else if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl200-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL200; - else if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl300-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL300; - else + if (!fdt) return SBI_ENODEV; - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, &addr, NULL); - if (rc) - return SBI_ENODEV; + for (i = 0; i < array_size(pmu_match); i++) { + int nodeoffset = -1; + + while ((nodeoffset = fdt_node_offset_by_compatible( + fdt, nodeoffset, pmu_match[i].compat)) >= 0) { + uint64_t addr; + + if (!fdt_node_is_enabled(fdt, nodeoffset)) + continue; + if (fdt_get_node_addr_size(fdt, nodeoffset, 0, &addr, NULL)) + continue; - if (dev_type == XUANTIE_LINK_DEV_TYPE_XL300) - writeq(BIT_ULL(40) | BIT_ULL(32) | 0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPHAUTHCR); - writeq(0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPMAUTHCR); - writeq(0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPSAUTHCR); - writeq(0x1, (void *)addr + XUANTIE_LINK_PMU_L3MAUTHCR); - writeq(0x0, (void *)addr + XUANTIE_LINK_PMU_HPCPINHIBIT); + if (pmu_match[i].dev_type == XUANTIE_LINK_DEV_TYPE_XL300) + writeq(XUANTIE_LINK_PMU_AUTHCR_AUTH | + XUANTIE_LINK_PMU_AUTHCR_INTPEND | + XUANTIE_LINK_PMU_CNT_BITMAP, + (void *)addr + XUANTIE_LINK_PMU_HPCPHAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPMAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPSAUTHCR); + writeq(0x1, (void *)addr + XUANTIE_LINK_PMU_L3MAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPINHIBIT); + found = true; + } + } + + if (!found) + return SBI_ENODEV; #endif return SBI_OK; }