From nobody Mon Sep 28 19:23:41 2026 Received: from mailgw1.hygon.cn (unknown [101.204.27.37]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AF16126158B; Tue, 18 Aug 2026 10:01:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=101.204.27.37 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787047319; cv=none; b=dXTY0BIRab12wXU8HC2Awu/+ncsXQc+6/2STbJ5YfC71r/j+Owx6027B+AnRmRCk/5Ru/tASTlORCQMTvkKGzCq5NQaEBmN7a5UZdEgmZVLIEOch+3BRQgq7ry//MXxknH+qmOpk458S3FGo8VYO0Q0CGGGMWNmUH9vJ31VDya8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787047319; c=relaxed/simple; bh=aC8jxNkG0sgpCFjQQ6fMvhVMD2WVYXA/runDYs61u+E=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=D8b6T+2gmIoqJ5rq0l3SsGg01VU0MPgbpHclLxeSrBSD0wBRba8iK2n2VNTEeRA2gz+vnnJDZdkbmYNuNBml4oa5x89FabLf0crXT9LKxg4oSXiSpSRAGWKsJuiPCyWpHItcGykTdioVTRQkiCzbErllXknekt/A3ctKlylT+u0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=hygon.cn; spf=pass smtp.mailfrom=hygon.cn; arc=none smtp.client-ip=101.204.27.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=hygon.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=hygon.cn Received: from maildlp1.hygon.cn (unknown [127.0.0.1]) by mailgw1.hygon.cn (Postfix) with ESMTP id 4hPQGD02ytz18tXg; Tue, 18 Aug 2026 18:01:40 +0800 (CST) Received: from maildlp1.hygon.cn (unknown [172.23.18.60]) by mailgw1.hygon.cn (Postfix) with ESMTP id 4hPQG96MMVz18tWX; Tue, 18 Aug 2026 18:01:37 +0800 (CST) Received: from cncheex04.Hygon.cn (unknown [172.23.18.114]) by maildlp1.hygon.cn (Postfix) with ESMTPS id 89C7278AD; Tue, 18 Aug 2026 18:01:32 +0800 (CST) Received: from neptune.hygon.cn (172.22.228.106) by cncheex04.Hygon.cn (172.23.18.114) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 18 Aug 2026 18:01:37 +0800 From: Qi Liu To: , , , , , , , , CC: , , , , Zhenglang Hu Subject: [PATCH v5 1/2] perf/x86/amd/uncore: Add Hygon uncore PMU support Date: Tue, 18 Aug 2026 10:01:17 +0000 Message-ID: <20260818100118.12944-2-liuqi@hygon.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260818100118.12944-1-liuqi@hygon.cn> References: <20260818100118.12944-1-liuqi@hygon.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: cncheex05.Hygon.cn (172.23.18.115) To cncheex04.Hygon.cn (172.23.18.114) Content-Type: text/plain; charset="utf-8" Add uncore PMU driver for Hygon Family 18h processors, supporting two PMU types: - hygon_df: Data Fabric counters shared across CPUs within the same DF instance, identified via Node ID. - hygon_df_iod: Data Fabric counters on the IO Die (IOD) for monitoring memory access metrics. A per-context hrtimer periodically reads the counters since uncore PMUs do not generate interrupts. CPU hotplug callbacks handle context creation, migration, and teardown. Keeping Hygon support in a separate driver avoids accumulating vendor checks in uncore.c as more Hygon-specific features are introduced. Remove the now-unnecessary Hygon checks from the AMD uncore driver. Signed-off-by: Qi Liu Tested-by: Zhenglang Hu --- arch/x86/events/Kconfig | 11 + arch/x86/events/amd/Makefile | 2 + arch/x86/events/amd/hygon_uncore.c | 872 +++++++++++++++++++++++++++++ arch/x86/events/amd/uncore.c | 11 +- arch/x86/include/asm/msr-index.h | 2 + arch/x86/include/asm/perf_event.h | 20 + include/linux/cpuhotplug.h | 3 + 7 files changed, 913 insertions(+), 8 deletions(-) create mode 100644 arch/x86/events/amd/hygon_uncore.c diff --git a/arch/x86/events/Kconfig b/arch/x86/events/Kconfig index dabdf3d7bf84..cc8387236b95 100644 --- a/arch/x86/events/Kconfig +++ b/arch/x86/events/Kconfig @@ -45,6 +45,17 @@ config PERF_EVENTS_AMD_UNCORE To compile this driver as a module, choose M here: the module will be called 'amd-uncore'. =20 +config PERF_EVENTS_HYGON_UNCORE + tristate "Hygon Uncore performance events" + depends on PERF_EVENTS && CPU_SUP_HYGON + default y + help + Include support for Hygon uncore performance events for use with + e.g., perf stat -e hygon_df/.../. + + To compile this driver as a module, choose M here: the + module will be called 'hygon-uncore'. + config PERF_EVENTS_AMD_BRS depends on PERF_EVENTS && CPU_SUP_AMD bool "AMD Zen3 Branch Sampling support" diff --git a/arch/x86/events/amd/Makefile b/arch/x86/events/amd/Makefile index 527d947eb76b..c373fd1d1525 100644 --- a/arch/x86/events/amd/Makefile +++ b/arch/x86/events/amd/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_PERF_EVENTS_AMD_POWER) +=3D power.o obj-$(CONFIG_X86_LOCAL_APIC) +=3D ibs.o obj-$(CONFIG_PERF_EVENTS_AMD_UNCORE) +=3D amd-uncore.o amd-uncore-objs :=3D uncore.o +obj-$(CONFIG_PERF_EVENTS_HYGON_UNCORE) +=3D hygon-uncore.o +hygon-uncore-objs :=3D hygon_uncore.o ifdef CONFIG_AMD_IOMMU obj-$(CONFIG_CPU_SUP_AMD) +=3D iommu.o endif diff --git a/arch/x86/events/amd/hygon_uncore.c b/arch/x86/events/amd/hygon= _uncore.c new file mode 100644 index 000000000000..471955d6fc28 --- /dev/null +++ b/arch/x86/events/amd/hygon_uncore.c @@ -0,0 +1,872 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Chengdu Haiguang IC Design Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define HYGON_UNCORE_NUM_COUNTERS_DF 4 +#define HYGON_UNCORE_NUM_COUNTERS_MAX 8 + +#define HYGON_UNCORE_NAME_LEN 16 +#define HYGON_UNCORE_COUNTER_SHIFT 16 + +#undef pr_fmt +#define pr_fmt(fmt) "hygon_uncore: " fmt + +struct hygon_uncore_ctx { + int refcnt; + int cpu; + struct perf_event **events; + unsigned long active_mask[BITS_TO_LONGS(HYGON_UNCORE_NUM_COUNTERS_MAX)]; + int nr_active; + struct hrtimer hrtimer; + u64 hrtimer_duration; +}; + +struct hygon_uncore_pmu { + char name[HYGON_UNCORE_NAME_LEN]; + int type; + int num_counters; + u32 msr_base; + cpumask_t active_mask; + struct pmu pmu; + struct hygon_uncore_ctx * __percpu *ctx; +}; + +enum { + HYGON_UNCORE_TYPE_DF, + HYGON_UNCORE_TYPE_DF_IOD, + HYGON_UNCORE_TYPE_MAX +}; + +union hygon_uncore_info { + struct { + u64 num_iods:8; /* number of iods of each package */ + u64 num_pmcs:8; /* number of counters */ + u64 cid:8; /* context id */ + } split; + u64 full; +}; + +struct hygon_uncore { + union hygon_uncore_info __percpu *info; + struct hygon_uncore_pmu pmu; + bool pmu_registered; + bool init_done; + void (*scan)(struct hygon_uncore *uncore, unsigned int cpu); + int (*init)(struct hygon_uncore *uncore, unsigned int cpu); + void (*move)(struct hygon_uncore *uncore, unsigned int cpu); + void (*free)(struct hygon_uncore *uncore, unsigned int cpu); +}; +static struct hygon_uncore uncores[]; + +static unsigned int update_interval =3D 60 * MSEC_PER_SEC; +module_param(update_interval, uint, 0444); + +static struct hygon_uncore_pmu *event_to_hygon_uncore_pmu(struct perf_even= t *event) +{ + return container_of(event->pmu, struct hygon_uncore_pmu, pmu); +} + +static __always_inline bool is_uncore_df_iod_event(struct hygon_uncore_pmu= *pmu) +{ + return pmu->type =3D=3D HYGON_UNCORE_TYPE_DF_IOD; +} + +static __always_inline int hygon_uncore_ctx_num_pmcs(struct hygon_uncore *= uncore, unsigned int cpu) +{ + union hygon_uncore_info *info =3D per_cpu_ptr(uncore->info, cpu); + + return info->split.num_pmcs; +} + +static __always_inline int hygon_uncore_ctx_cid(struct hygon_uncore *uncor= e, unsigned int cpu) +{ + union hygon_uncore_info *info =3D per_cpu_ptr(uncore->info, cpu); + + return info->split.cid; +} + +static __always_inline int hygon_uncore_ctx_num_iods(struct hygon_uncore *= uncore, unsigned int cpu) +{ + union hygon_uncore_info *info =3D per_cpu_ptr(uncore->info, cpu); + + return info->split.num_iods; +} + +static enum hrtimer_restart hygon_uncore_hrtimer(struct hrtimer *hrtimer) +{ + struct hygon_uncore_ctx *ctx; + struct perf_event *event; + int bit; + + ctx =3D container_of(hrtimer, struct hygon_uncore_ctx, hrtimer); + + if (!ctx->nr_active || ctx->cpu !=3D smp_processor_id()) + return HRTIMER_NORESTART; + + for_each_set_bit(bit, ctx->active_mask, HYGON_UNCORE_NUM_COUNTERS_MAX) { + event =3D ctx->events[bit]; + event->pmu->read(event); + } + + hrtimer_forward_now(hrtimer, ns_to_ktime(ctx->hrtimer_duration)); + return HRTIMER_RESTART; +} + +static void hygon_uncore_start_hrtimer(struct hygon_uncore_ctx *ctx) +{ + hrtimer_start(&ctx->hrtimer, ns_to_ktime(ctx->hrtimer_duration), + HRTIMER_MODE_REL_PINNED_HARD); +} + +static void hygon_uncore_cancel_hrtimer(struct hygon_uncore_ctx *ctx) +{ + hrtimer_cancel(&ctx->hrtimer); +} + +static void hygon_uncore_init_hrtimer(struct hygon_uncore_ctx *ctx) +{ + hrtimer_setup(&ctx->hrtimer, hygon_uncore_hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_HARD); +} + +static void hygon_uncore_read(struct perf_event *event) +{ + struct hw_perf_event *hwc =3D &event->hw; + u64 prev, cur; + s64 delta; + + do { + prev =3D local64_read(&hwc->prev_count); + rdmsrq(hwc->event_base, cur); + } while (local64_cmpxchg(&hwc->prev_count, prev, cur) !=3D prev); + delta =3D (cur << HYGON_UNCORE_COUNTER_SHIFT) - + (prev << HYGON_UNCORE_COUNTER_SHIFT); + delta >>=3D HYGON_UNCORE_COUNTER_SHIFT; + local64_add(delta, &event->count); +} + +static void hygon_uncore_start(struct perf_event *event, int flags) +{ + struct hygon_uncore_pmu *pmu =3D event_to_hygon_uncore_pmu(event); + struct hygon_uncore_ctx *ctx =3D *per_cpu_ptr(pmu->ctx, event->cpu); + struct hw_perf_event *hwc =3D &event->hw; + + if (!ctx->nr_active++) + hygon_uncore_start_hrtimer(ctx); + + if (flags & PERF_EF_RELOAD) + wrmsrq(hwc->event_base, (u64)local64_read(&hwc->prev_count)); + + hwc->state =3D 0; + __set_bit(hwc->idx, ctx->active_mask); + wrmsrq(hwc->config_base, (hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE)); + perf_event_update_userpage(event); +} + +static void hygon_uncore_stop(struct perf_event *event, int flags) +{ + struct hygon_uncore_pmu *pmu =3D event_to_hygon_uncore_pmu(event); + struct hygon_uncore_ctx *ctx =3D *per_cpu_ptr(pmu->ctx, event->cpu); + struct hw_perf_event *hwc =3D &event->hw; + + wrmsrq(hwc->config_base, hwc->config); + hwc->state |=3D PERF_HES_STOPPED; + + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { + event->pmu->read(event); + hwc->state |=3D PERF_HES_UPTODATE; + } + + if (!--ctx->nr_active) + hygon_uncore_cancel_hrtimer(ctx); + + __clear_bit(hwc->idx, ctx->active_mask); +} + +static int hygon_uncore_add(struct perf_event *event, int flags) +{ + struct hygon_uncore_pmu *pmu =3D event_to_hygon_uncore_pmu(event); + struct hygon_uncore_ctx *ctx =3D *per_cpu_ptr(pmu->ctx, event->cpu); + struct hw_perf_event *hwc =3D &event->hw; + int i, iod_idx; + + if (!ctx) + return -ENODEV; + + if (hwc->idx !=3D -1 && ctx->events[hwc->idx] =3D=3D event) + goto out; + + for (i =3D 0; i < pmu->num_counters; i++) { + if (ctx->events[i] =3D=3D event) { + hwc->idx =3D i; + goto out; + } + } + + hwc->idx =3D -1; + if (is_uncore_df_iod_event(pmu)) { + iod_idx =3D event->attr.config1; + for (i =3D iod_idx * HYGON_UNCORE_NUM_COUNTERS_DF; + i < (iod_idx + 1) * HYGON_UNCORE_NUM_COUNTERS_DF; + i++) { + struct perf_event *tmp =3D NULL; + + if (try_cmpxchg(&ctx->events[i], &tmp, event)) { + hwc->idx =3D i; + break; + } + } + } else { + for (i =3D 0; i < pmu->num_counters; i++) { + struct perf_event *tmp =3D NULL; + + if (try_cmpxchg(&ctx->events[i], &tmp, event)) { + hwc->idx =3D i; + break; + } + } + } +out: + if (hwc->idx =3D=3D -1) + return -EBUSY; + + hwc->config_base =3D pmu->msr_base + (2 * hwc->idx); + hwc->event_base =3D pmu->msr_base + 1 + (2 * hwc->idx); + hwc->state =3D PERF_HES_UPTODATE | PERF_HES_STOPPED; + if (flags & PERF_EF_START) + event->pmu->start(event, PERF_EF_RELOAD); + + return 0; +} + +static void hygon_uncore_del(struct perf_event *event, int flags) +{ + struct hygon_uncore_pmu *pmu =3D event_to_hygon_uncore_pmu(event); + struct hygon_uncore_ctx *ctx =3D *per_cpu_ptr(pmu->ctx, event->cpu); + struct hw_perf_event *hwc =3D &event->hw; + int i; + + if (!ctx) + return; + + event->pmu->stop(event, PERF_EF_UPDATE); + for (i =3D 0; i < pmu->num_counters; i++) { + struct perf_event *tmp =3D event; + + if (try_cmpxchg(&ctx->events[i], &tmp, NULL)) + break; + } + + hwc->idx =3D -1; +} + +static int hygon_uncore_event_init(struct perf_event *event) +{ + struct hw_perf_event *hwc =3D &event->hw; + struct hygon_uncore_pmu *pmu; + struct hygon_uncore_ctx *ctx; + + if (event->attr.type !=3D event->pmu->type) + return -ENOENT; + + if (event->cpu < 0) + return -EINVAL; + + pmu =3D event_to_hygon_uncore_pmu(event); + ctx =3D *per_cpu_ptr(pmu->ctx, event->cpu); + if (!ctx) + return -ENODEV; + + event->cpu =3D ctx->cpu; + hwc->config =3D event->attr.config; + hwc->idx =3D -1; + + return 0; +} + +static int hygon_uncore_df_event_init(struct perf_event *event) +{ + int ret =3D hygon_uncore_event_init(event); + struct hw_perf_event *hwc =3D &event->hw; + struct hygon_uncore_pmu *pmu; + struct hygon_uncore *uncore; + u64 event_mask =3D HYGON_F18H_RAW_EVENT_MASK_DF; + + if (ret) + return ret; + + pmu =3D event_to_hygon_uncore_pmu(event); + uncore =3D &uncores[pmu->type]; + if (is_uncore_df_iod_event(pmu) && + (event->attr.config1 >=3D hygon_uncore_ctx_num_iods(uncore, event->cp= u))) + return -EINVAL; + + if (boot_cpu_data.x86_model =3D=3D 0x4 || + boot_cpu_data.x86_model =3D=3D 0x5) + event_mask =3D HYGON_F18H_M4H_RAW_EVENT_MASK_DF; + else if (boot_cpu_data.x86_model >=3D 0x6 && + boot_cpu_data.x86_model <=3D 0x18) + event_mask =3D HYGON_F18H_M6H_RAW_EVENT_MASK_DF; + + hwc->config =3D event->attr.config & event_mask; + return 0; +} + +static ssize_t cpumask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pmu *ptr =3D dev_get_drvdata(dev); + struct hygon_uncore_pmu *pmu =3D container_of(ptr, struct hygon_uncore_pm= u, pmu); + + return cpumap_print_to_pagebuf(true, buf, &pmu->active_mask); +} +static DEVICE_ATTR_RO(cpumask); + +static struct attribute *hygon_uncore_attrs[] =3D { + &dev_attr_cpumask.attr, + NULL, +}; + +static struct attribute_group hygon_uncore_attr_group =3D { + .attrs =3D hygon_uncore_attrs, +}; + +#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \ +static ssize_t __uncore_##_var##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *page) \ +{ \ + BUILD_BUG_ON(sizeof(_format) >=3D PAGE_SIZE); \ + return sprintf(page, _format "\n"); \ +} \ +static struct device_attribute format_attr_##_var =3D \ + __ATTR(_name, 0444, __uncore_##_var##_show, NULL) + +DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-5"); +DEFINE_UNCORE_FORMAT_ATTR(umask8, umask, "config:8-15"); +DEFINE_UNCORE_FORMAT_ATTR(umask10, umask, "config:8-17"); /* F18h M4h DF= */ +DEFINE_UNCORE_FORMAT_ATTR(umask12, umask, "config:8-19"); /* F18h M6h DF= */ +DEFINE_UNCORE_FORMAT_ATTR(compid, compid, "config:6-7,32-35,61-62"); +DEFINE_UNCORE_FORMAT_ATTR(iod, iod, "config1:0-1"); + +static struct attribute *hygon_uncore_df_umask_attr(void) +{ + if (boot_cpu_data.x86_model =3D=3D 0x4 || + boot_cpu_data.x86_model =3D=3D 0x5) + return &format_attr_umask10.attr; + + if (boot_cpu_data.x86_model >=3D 0x6 && + boot_cpu_data.x86_model <=3D 0x18) + return &format_attr_umask12.attr; + + return &format_attr_umask8.attr; +} + +static struct attribute *hygon_uncore_df_format_attr[] =3D { + &format_attr_event.attr, /* event */ + &format_attr_umask8.attr, /* umask */ + &format_attr_compid.attr, /* compid */ + NULL, +}; + +static struct attribute_group hygon_uncore_df_format_group =3D { + .name =3D "format", + .attrs =3D hygon_uncore_df_format_attr, +}; + +static const struct attribute_group *hygon_uncore_df_attr_groups[] =3D { + &hygon_uncore_attr_group, + &hygon_uncore_df_format_group, + NULL, +}; + +static struct attribute *hygon_uncore_df_iod_format_attr[] =3D { + &format_attr_event.attr, /* event */ + &format_attr_umask10.attr, /* umask */ + &format_attr_compid.attr, /* compid */ + &format_attr_iod.attr, /* iod */ + NULL, +}; + +static struct attribute_group hygon_uncore_df_iod_format_group =3D { + .name =3D "format", + .attrs =3D hygon_uncore_df_iod_format_attr, +}; + +static const struct attribute_group *hygon_uncore_df_iod_attr_groups[] =3D= { + &hygon_uncore_attr_group, + &hygon_uncore_df_iod_format_group, + NULL, +}; + +static int hygon_uncore_cpu_starting(unsigned int cpu) +{ + struct hygon_uncore *uncore; + int i; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + uncore->scan(uncore, cpu); + } + + return 0; +} + +static int hygon_uncore_cpu_dead(unsigned int cpu) +{ + struct hygon_uncore *uncore; + int i; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + uncore->free(uncore, cpu); + } + + return 0; +} + +static int hygon_uncore_cpu_online(unsigned int cpu) +{ + struct hygon_uncore *uncore; + int i; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + if (uncore->init(uncore, cpu)) + continue; + } + + return 0; +} + +static int hygon_uncore_cpu_down_prepare(unsigned int cpu) +{ + struct hygon_uncore *uncore; + int i; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + uncore->move(uncore, cpu); + } + + return 0; +} + +static void hygon_uncore_ctx_free(struct hygon_uncore *uncore, unsigned in= t cpu) +{ + struct hygon_uncore_pmu *pmu =3D &uncore->pmu; + struct hygon_uncore_ctx *ctx; + + if (!uncore->init_done || !uncore->pmu_registered) + return; + + if (!pmu->ctx) + return; + + ctx =3D *per_cpu_ptr(pmu->ctx, cpu); + if (!ctx) + return; + + if (cpu =3D=3D ctx->cpu) + cpumask_clear_cpu(cpu, &pmu->active_mask); + + if (!--ctx->refcnt) { + hygon_uncore_cancel_hrtimer(ctx); + kfree(ctx->events); + kfree(ctx); + } + + *per_cpu_ptr(pmu->ctx, cpu) =3D NULL; +} + +static void hygon_uncore_ctx_move(struct hygon_uncore *uncore, unsigned in= t cpu) +{ + struct hygon_uncore_pmu *pmu =3D &uncore->pmu; + struct hygon_uncore_ctx *curr, *next; + int i; + + if (!uncore->init_done || !uncore->pmu_registered) + return; + + if (!pmu->ctx) + return; + + curr =3D *per_cpu_ptr(pmu->ctx, cpu); + if (!curr) + return; + + for_each_online_cpu(i) { + next =3D *per_cpu_ptr(pmu->ctx, i); + if (!next || cpu =3D=3D i) + continue; + + if (curr =3D=3D next) { + perf_pmu_migrate_context(&pmu->pmu, cpu, i); + cpumask_clear_cpu(cpu, &pmu->active_mask); + cpumask_set_cpu(i, &pmu->active_mask); + next->cpu =3D i; + break; + } + } +} + +static int hygon_uncore_ctx_init(struct hygon_uncore *uncore, unsigned int= cpu) +{ + struct hygon_uncore_ctx *curr, *prev; + struct hygon_uncore_pmu *pmu =3D &uncore->pmu; + int node, cid, i; + + if (!uncore->init_done || !uncore->pmu_registered) + return 0; + + if (!pmu->ctx) + return 0; + + cid =3D hygon_uncore_ctx_cid(uncore, cpu); + *per_cpu_ptr(pmu->ctx, cpu) =3D NULL; + curr =3D NULL; + + for_each_online_cpu(i) { + if (cpu =3D=3D i) + continue; + + prev =3D *per_cpu_ptr(pmu->ctx, i); + if (!prev) + continue; + if (cid =3D=3D hygon_uncore_ctx_cid(uncore, i)) { + curr =3D prev; + break; + } + } + + if (!curr) { + node =3D cpu_to_node(cpu); + curr =3D kzalloc_node(sizeof(*curr), GFP_KERNEL, node); + if (!curr) + goto fail; + + curr->cpu =3D cpu; + curr->events =3D kzalloc_node(sizeof(*curr->events) * + pmu->num_counters, + GFP_KERNEL, node); + if (!curr->events) { + kfree(curr); + goto fail; + } + + cpumask_set_cpu(cpu, &pmu->active_mask); + + hygon_uncore_init_hrtimer(curr); + curr->hrtimer_duration =3D (u64)update_interval * NSEC_PER_MSEC; + } + + curr->refcnt++; + *per_cpu_ptr(pmu->ctx, cpu) =3D curr; + + return 0; + +fail: + hygon_uncore_ctx_free(uncore, cpu); + + return -ENOMEM; +} + +static void hygon_uncore_df_ctx_scan(struct hygon_uncore *uncore, unsigned= int cpu) +{ + union hygon_uncore_info info =3D {}; + + if (!boot_cpu_has(X86_FEATURE_PERFCTR_NB)) + return; + + info.split.num_iods =3D 0; + info.split.num_pmcs =3D HYGON_UNCORE_NUM_COUNTERS_DF; + info.split.cid =3D topology_amd_node_id(cpu); + + *per_cpu_ptr(uncore->info, cpu) =3D info; +} + +static +int hygon_uncore_df_ctx_init(struct hygon_uncore *uncore, unsigned int cpu) +{ + struct hygon_uncore_pmu *pmu =3D &uncore->pmu; + int num_counters; + + if (uncore->init_done) + return hygon_uncore_ctx_init(uncore, cpu); + + num_counters =3D hygon_uncore_ctx_num_pmcs(uncore, cpu); + if (!num_counters) + goto done; + + strscpy(pmu->name, "hygon_df", sizeof(pmu->name)); + pmu->num_counters =3D num_counters; + pmu->msr_base =3D MSR_HYGON_F18H_DF_CTL; + pmu->type =3D HYGON_UNCORE_TYPE_DF; + + hygon_uncore_df_format_attr[1] =3D hygon_uncore_df_umask_attr(); + + pmu->ctx =3D alloc_percpu(struct hygon_uncore_ctx *); + if (!pmu->ctx) + goto done; + + pmu->pmu =3D (struct pmu) { + .task_ctx_nr =3D perf_invalid_context, + .attr_groups =3D hygon_uncore_df_attr_groups, + .name =3D pmu->name, + .event_init =3D hygon_uncore_df_event_init, + .add =3D hygon_uncore_add, + .del =3D hygon_uncore_del, + .start =3D hygon_uncore_start, + .stop =3D hygon_uncore_stop, + .read =3D hygon_uncore_read, + .capabilities =3D PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, + .module =3D THIS_MODULE, + }; + + if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) { + free_percpu(pmu->ctx); + pmu->ctx =3D NULL; + goto done; + } + uncore->pmu_registered =3D true; + +done: + uncore->init_done =3D true; + return hygon_uncore_ctx_init(uncore, cpu); +} + +static +void hygon_uncore_df_iod_ctx_scan(struct hygon_uncore *uncore, unsigned in= t cpu) +{ + union hygon_uncore_info info =3D {}; + int num_packages, num_cdds, iods_per_package; + + if (!boot_cpu_has(X86_FEATURE_PERFCTR_NB)) + return; + + if (boot_cpu_data.x86_model < 0x4 || boot_cpu_data.x86_model =3D=3D 0x6) + return; + + num_packages =3D topology_max_packages(); + num_cdds =3D topology_max_dies_per_package() * num_packages; + iods_per_package =3D (amd_nb_num() - num_cdds) / num_packages; + + /* Hardware does not support more than 2 IODs per package. */ + if (iods_per_package <=3D 0 || iods_per_package > 2) + return; + + info.split.cid =3D topology_physical_package_id(cpu); + info.split.num_iods =3D iods_per_package; + info.split.num_pmcs =3D HYGON_UNCORE_NUM_COUNTERS_DF * iods_per_package; + + *per_cpu_ptr(uncore->info, cpu) =3D info; +} + +static +int hygon_uncore_df_iod_ctx_init(struct hygon_uncore *uncore, unsigned int= cpu) +{ + struct hygon_uncore_pmu *pmu =3D &uncore->pmu; + int num_counters; + + if (uncore->init_done) + return hygon_uncore_ctx_init(uncore, cpu); + + num_counters =3D hygon_uncore_ctx_num_pmcs(uncore, cpu); + if (!num_counters) + goto done; + + strscpy(pmu->name, "hygon_df_iod", sizeof(pmu->name)); + pmu->num_counters =3D num_counters; + pmu->msr_base =3D MSR_HYGON_F18H_DF_IOD_CTL; + pmu->type =3D HYGON_UNCORE_TYPE_DF_IOD; + + hygon_uncore_df_iod_format_attr[1] =3D hygon_uncore_df_umask_attr(); + + pmu->ctx =3D alloc_percpu(struct hygon_uncore_ctx *); + if (!pmu->ctx) + goto done; + + pmu->pmu =3D (struct pmu) { + .task_ctx_nr =3D perf_invalid_context, + .attr_groups =3D hygon_uncore_df_iod_attr_groups, + .name =3D pmu->name, + .event_init =3D hygon_uncore_df_event_init, + .add =3D hygon_uncore_add, + .del =3D hygon_uncore_del, + .start =3D hygon_uncore_start, + .stop =3D hygon_uncore_stop, + .read =3D hygon_uncore_read, + .capabilities =3D PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, + .module =3D THIS_MODULE, + }; + + if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) { + free_percpu(pmu->ctx); + pmu->ctx =3D NULL; + goto done; + } + uncore->pmu_registered =3D true; +done: + uncore->init_done =3D true; + return hygon_uncore_ctx_init(uncore, cpu); +} + +static struct hygon_uncore uncores[HYGON_UNCORE_TYPE_MAX] =3D { + /* HYGON DF */ + { + .scan =3D hygon_uncore_df_ctx_scan, + .init =3D hygon_uncore_df_ctx_init, + .move =3D hygon_uncore_ctx_move, + .free =3D hygon_uncore_ctx_free, + }, + /* HYGON DF IOD */ + { + .scan =3D hygon_uncore_df_iod_ctx_scan, + .init =3D hygon_uncore_df_iod_ctx_init, + .move =3D hygon_uncore_ctx_move, + .free =3D hygon_uncore_ctx_free, + } +}; + +static void hygon_uncore_pmu_cleanup(void) +{ + struct hygon_uncore_ctx *ctx; + struct hygon_uncore *uncore; + int i, cpu; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + + /* Unregister PMU before freeing its contexts. */ + if (uncore->pmu_registered) { + perf_pmu_unregister(&uncore->pmu.pmu); + uncore->pmu_registered =3D false; + } + + if (!uncore->pmu.ctx) + continue; + + /* Shared ctx objects are released through their refcnt. */ + for_each_possible_cpu(cpu) { + ctx =3D *per_cpu_ptr(uncore->pmu.ctx, cpu); + if (!ctx) + continue; + + if (!--ctx->refcnt) { + hygon_uncore_cancel_hrtimer(ctx); + kfree(ctx->events); + kfree(ctx); + } + *per_cpu_ptr(uncore->pmu.ctx, cpu) =3D NULL; + } + + free_percpu(uncore->pmu.ctx); + uncore->pmu.ctx =3D NULL; + } +} + +static void hygon_uncore_info_cleanup(void) +{ + struct hygon_uncore *uncore; + int i; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + if (uncore->info) { + free_percpu(uncore->info); + uncore->info =3D NULL; + } + } +} + +static int __init hygon_uncore_init(void) +{ + struct hygon_uncore *uncore; + int ret =3D -ENODEV; + int i; + + + if (!update_interval) { + pr_err("update_interval must be greater than 0 ms\n"); + return -EINVAL; + } + + if (boot_cpu_data.x86_vendor !=3D X86_VENDOR_HYGON) + return -ENODEV; + + if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) + return -ENODEV; + + for (i =3D 0; i < HYGON_UNCORE_TYPE_MAX; i++) { + uncore =3D &uncores[i]; + + uncore->info =3D alloc_percpu(union hygon_uncore_info); + if (!uncore->info) { + ret =3D -ENOMEM; + goto fail; + } + } + + ret =3D cpuhp_setup_state(CPUHP_PERF_X86_HYGON_UNCORE_PREP, + "perf/x86/hygon/uncore:prepare", + NULL, hygon_uncore_cpu_dead); + if (ret) + goto fail; + + ret =3D cpuhp_setup_state(CPUHP_AP_PERF_X86_HYGON_UNCORE_STARTING, + "perf/x86/hygon/uncore:starting", + hygon_uncore_cpu_starting, NULL); + if (ret) + goto fail_prep; + + ret =3D cpuhp_setup_state(CPUHP_AP_PERF_X86_HYGON_UNCORE_ONLINE, + "perf/x86/hygon/uncore:online", + hygon_uncore_cpu_online, + hygon_uncore_cpu_down_prepare); + if (ret) + goto fail_start; + + return 0; + +fail_start: + cpuhp_remove_state(CPUHP_AP_PERF_X86_HYGON_UNCORE_STARTING); +fail_prep: + cpuhp_remove_state(CPUHP_PERF_X86_HYGON_UNCORE_PREP); +fail: + hygon_uncore_info_cleanup(); + return ret; +} + +static void __exit hygon_uncore_exit(void) +{ + cpuhp_remove_state(CPUHP_AP_PERF_X86_HYGON_UNCORE_ONLINE); + cpuhp_remove_state(CPUHP_AP_PERF_X86_HYGON_UNCORE_STARTING); + cpuhp_remove_state(CPUHP_PERF_X86_HYGON_UNCORE_PREP); + + hygon_uncore_pmu_cleanup(); + hygon_uncore_info_cleanup(); +} +module_init(hygon_uncore_init); +module_exit(hygon_uncore_exit); + +MODULE_DESCRIPTION("Hygon Uncore Driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index dbc00b6dd69e..6c486e1ab001 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -775,9 +775,7 @@ int amd_uncore_df_ctx_init(struct amd_uncore *uncore, u= nsigned int cpu) goto done; } =20 - pr_info("%d %s%s counters detected\n", pmu->num_counters, - boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_HYGON ? "HYGON " : "", - pmu->pmu.name); + pr_info("%d %s counters detected\n", pmu->num_counters, pmu->pmu.name); =20 uncore->num_pmus =3D 1; =20 @@ -911,9 +909,7 @@ int amd_uncore_l3_ctx_init(struct amd_uncore *uncore, u= nsigned int cpu) goto done; } =20 - pr_info("%d %s%s counters detected\n", pmu->num_counters, - boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_HYGON ? "HYGON " : "", - pmu->pmu.name); + pr_info("%d %s counters detected\n", pmu->num_counters, pmu->pmu.name); =20 uncore->num_pmus =3D 1; =20 @@ -1120,8 +1116,7 @@ static int __init amd_uncore_init(void) int ret =3D -ENODEV; int i; =20 - if (boot_cpu_data.x86_vendor !=3D X86_VENDOR_AMD && - boot_cpu_data.x86_vendor !=3D X86_VENDOR_HYGON) + if (boot_cpu_data.x86_vendor !=3D X86_VENDOR_AMD) return -ENODEV; =20 if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index 18c4be75e927..d20338f0b2b2 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -851,6 +851,8 @@ #define MSR_F15H_PTSC 0xc0010280 #define MSR_F15H_IC_CFG 0xc0011021 #define MSR_F15H_EX_CFG 0xc001102c +#define MSR_HYGON_F18H_DF_CTL 0xc0010240 +#define MSR_HYGON_F18H_DF_IOD_CTL 0xc0010250 =20 /* Fam 10h MSRs */ #define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058 diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 1eb13673e889..7c8c00ad56e9 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -124,6 +124,26 @@ (AMD64_PERFMON_V2_EVENTSEL_EVENT_NB | \ AMD64_PERFMON_V2_EVENTSEL_UMASK_NB) =20 +#define HYGON_F18H_EVENTSEL_EVENT_DF 0x0000003FULL +#define HYGON_F18H_EVENTSEL_UMASK_DF 0x0000FF00ULL +#define HYGON_F18H_M4H_EVENTSEL_UMASK_DF 0x0003FF00ULL +#define HYGON_F18H_M6H_EVENTSEL_UMASK_DF 0x000FFF00ULL +#define HYGON_F18H_EVENTSEL_CONSTID_DF \ + (0x000000C0ULL | GENMASK_ULL(35, 32) | GENMASK_ULL(62, 61)) + +#define HYGON_F18H_RAW_EVENT_MASK_DF \ + (HYGON_F18H_EVENTSEL_EVENT_DF | \ + HYGON_F18H_EVENTSEL_UMASK_DF | \ + HYGON_F18H_EVENTSEL_CONSTID_DF) +#define HYGON_F18H_M4H_RAW_EVENT_MASK_DF \ + (HYGON_F18H_EVENTSEL_EVENT_DF | \ + HYGON_F18H_M4H_EVENTSEL_UMASK_DF | \ + HYGON_F18H_EVENTSEL_CONSTID_DF) +#define HYGON_F18H_M6H_RAW_EVENT_MASK_DF \ + (HYGON_F18H_EVENTSEL_EVENT_DF | \ + HYGON_F18H_M6H_EVENTSEL_UMASK_DF | \ + HYGON_F18H_EVENTSEL_CONSTID_DF) + #define AMD64_PERFMON_V2_ENABLE_UMC BIT_ULL(31) #define AMD64_PERFMON_V2_EVENTSEL_EVENT_UMC GENMASK_ULL(7, 0) #define AMD64_PERFMON_V2_EVENTSEL_RDWRMASK_UMC GENMASK_ULL(9, 8) diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 0fb3a2a62eb0..bccdb87a0c05 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -62,6 +62,7 @@ enum cpuhp_state { CPUHP_CREATE_THREADS, CPUHP_PERF_X86_PREPARE, CPUHP_PERF_X86_AMD_UNCORE_PREP, + CPUHP_PERF_X86_HYGON_UNCORE_PREP, CPUHP_PERF_POWER, CPUHP_PERF_SUPERH, CPUHP_X86_HPET_DEAD, @@ -148,6 +149,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING, CPUHP_AP_ARM_MVEBU_COHERENCY, CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING, + CPUHP_AP_PERF_X86_HYGON_UNCORE_STARTING, CPUHP_AP_PERF_X86_STARTING, CPUHP_AP_PERF_X86_AMD_IBS_STARTING, CPUHP_AP_PERF_XTENSA_STARTING, @@ -205,6 +207,7 @@ enum cpuhp_state { CPUHP_AP_PERF_X86_ONLINE, CPUHP_AP_PERF_X86_UNCORE_ONLINE, CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE, + CPUHP_AP_PERF_X86_HYGON_UNCORE_ONLINE, CPUHP_AP_PERF_X86_AMD_POWER_ONLINE, CPUHP_AP_PERF_S390_CF_ONLINE, CPUHP_AP_PERF_S390_SF_ONLINE, --=20 2.34.1 From nobody Mon Sep 28 19:23:41 2026 Received: from mailgw1.hygon.cn (unknown [101.204.27.37]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AF1E328C5B1; Tue, 18 Aug 2026 10:01:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=101.204.27.37 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787047319; cv=none; b=UTFomigtdoRXHDqP/DV4wM11rzdOvRpQXQFFcbQsqCNYOkJ4jqKrOnt37ZMiUjdkXwjb1hWsPP0UeIYO5wpVsdtjJ30KjX6SyTcNhD6C9uVCvOpeimYulUi29sA5UNAOfJ3KyBYErH+WADs9EUi2tylSJEH6HdxfBfcbCLlpY4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787047319; c=relaxed/simple; bh=M1U75z66kRNZn5niV1VkLNHMdBAWSuKh5cPrLmEDI+k=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XSRJC+S7yOiGMbcVWIo72c4yieQaz9yYrJCOmiv6GpVKxUXOec2EiwnXUhyqyf7kJnozJDBrLopZf0djZKDs7+nZtDqDO27nB2WY+J4YjDRu+43tmUTE0yMkkP/xG/Bejtwmes6neKMaMuEnqbZ+6cKk3mSC26C+/41KMWib5Sw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=hygon.cn; spf=pass smtp.mailfrom=hygon.cn; arc=none smtp.client-ip=101.204.27.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=hygon.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=hygon.cn Received: from maildlp2.hygon.cn (unknown [127.0.0.1]) by mailgw1.hygon.cn (Postfix) with ESMTP id 4hPQGD02w8z18tXb; Tue, 18 Aug 2026 18:01:40 +0800 (CST) Received: from maildlp2.hygon.cn (unknown [172.23.18.61]) by mailgw1.hygon.cn (Postfix) with ESMTP id 4hPQGC0SsSz18tWX; Tue, 18 Aug 2026 18:01:39 +0800 (CST) Received: from cncheex04.Hygon.cn (unknown [172.23.18.114]) by maildlp2.hygon.cn (Postfix) with ESMTPS id 280B7300D1E7; Tue, 18 Aug 2026 17:58:12 +0800 (CST) Received: from neptune.hygon.cn (172.22.228.106) by cncheex04.Hygon.cn (172.23.18.114) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 18 Aug 2026 18:01:38 +0800 From: Qi Liu To: , , , , , , , , CC: , , , Subject: [PATCH v5 2/2] perf vendor events hygon: Add Hygon Data Fabric PMU events and metrics Date: Tue, 18 Aug 2026 10:01:18 +0000 Message-ID: <20260818100118.12944-3-liuqi@hygon.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260818100118.12944-1-liuqi@hygon.cn> References: <20260818100118.12944-1-liuqi@hygon.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: cncheex05.Hygon.cn (172.23.18.115) To cncheex04.Hygon.cn (172.23.18.114) Content-Type: text/plain; charset="utf-8" Add perf JSON event definitions and metrics for the Hygon Data Fabric (DF) uncore PMU. Signed-off-by: Qi Liu --- tools/perf/pmu-events/Build | 2 +- .../arch/x86/hygonm1/data-fabric.json | 95 ++++++++++ .../arch/x86/hygonm4/data-fabric.json | 134 ++++++++++++++ .../arch/x86/hygonm6/data-fabric.json | 170 ++++++++++++++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 3 + tools/perf/pmu-events/jevents.py | 2 + 6 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 tools/perf/pmu-events/arch/x86/hygonm1/data-fabric.json create mode 100644 tools/perf/pmu-events/arch/x86/hygonm4/data-fabric.json create mode 100644 tools/perf/pmu-events/arch/x86/hygonm6/data-fabric.json diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index 372773b998e4..79a9b4cad202 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -95,7 +95,7 @@ endif =20 ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all)) # Generate Intel Json -INTELS :=3D $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v map= file.csv) +INTELS :=3D $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v hyg= on|grep -v mapfile.csv) INTEL_METRICS =3D $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json) INTEL_METRICGROUPS =3D $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgro= ups.json) GEN_JSON +=3D $(INTEL_METRICS) $(INTEL_METRICGROUPS) diff --git a/tools/perf/pmu-events/arch/x86/hygonm1/data-fabric.json b/tool= s/perf/pmu-events/arch/x86/hygonm1/data-fabric.json new file mode 100644 index 000000000000..8c6a8e9ba9a5 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/hygonm1/data-fabric.json @@ -0,0 +1,95 @@ +[ + { + "EventName": "cpu_read_requests_cs_0", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_1", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_0", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_1", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_0", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_1", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_0", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_1", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "MetricName": "cpu_memory_bandwidth", + "MetricExpr": "(cpu_read_requests_cs_0 + cpu_read_requests_cs_1 + cpu_= write_requests_cs_0 + cpu_write_requests_cs_1) * 64 / (duration_time * 1e6)= ", + "BriefDescription": "Total CPU memory access bandwidth", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_max_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_wri= te_requests_cs_0 + io_write_requests_cs_1) * 64 / (duration_time * 1e6)", + "BriefDescription": "Maximum inbound I/O memory access bandwidth (uppe= r bound, assuming 64B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_min_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_wri= te_requests_cs_0 + io_write_requests_cs_1) * 32 / (duration_time * 1e6)", + "BriefDescription": "Minimum inbound I/O memory access bandwidth (lowe= r bound, assuming 32B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + } +] diff --git a/tools/perf/pmu-events/arch/x86/hygonm4/data-fabric.json b/tool= s/perf/pmu-events/arch/x86/hygonm4/data-fabric.json new file mode 100644 index 000000000000..41932a1a3d6d --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/hygonm4/data-fabric.json @@ -0,0 +1,134 @@ +[ + { + "EventName": "cpu_read_requests_cs_0", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_1", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_2", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 2 (CS2).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_0", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_1", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_2", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 2 (CS2).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_0", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_1", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_2", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 2 (CS2). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_0", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_1", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_2", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 2 (CS2). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "MetricName": "cpu_memory_bandwidth", + "MetricExpr": "(cpu_read_requests_cs_0 + cpu_read_requests_cs_1 + cpu_= read_requests_cs_2 + cpu_write_requests_cs_0 + cpu_write_requests_cs_1 + cp= u_write_requests_cs_2) * 64 / (duration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Total CPU memory access bandwidth", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_max_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_rea= d_requests_cs_2 + io_write_requests_cs_0 + io_write_requests_cs_1 + io_writ= e_requests_cs_2) * 64 / (duration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Maximum inbound I/O memory access bandwidth (uppe= r bound, assuming 64B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_min_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_rea= d_requests_cs_2 + io_write_requests_cs_0 + io_write_requests_cs_1 + io_writ= e_requests_cs_2) * 32 / (duration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Minimum inbound I/O memory access bandwidth (lowe= r bound, assuming 32B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + } +] diff --git a/tools/perf/pmu-events/arch/x86/hygonm6/data-fabric.json b/tool= s/perf/pmu-events/arch/x86/hygonm6/data-fabric.json new file mode 100644 index 000000000000..ee81e35dc6f3 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/hygonm6/data-fabric.json @@ -0,0 +1,170 @@ +[ + { + "EventName": "cpu_read_requests_cs_0", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_1", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_2", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 2 (CS2).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_read_requests_cs_3", + "BriefDescription": "Number of CPU read requests to memory in 64-byte = units for Coherent Subordinate 3 (CS3).", + "EventCode": "0x2", + "UMask": "0x07", + "CompId": "0x3", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_0", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 0 (CS0).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_1", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 1 (CS1).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_2", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 2 (CS2).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "cpu_write_requests_cs_3", + "BriefDescription": "Number of CPU write requests to memory in 64-byte= units for Coherent Subordinate 3 (CS3).", + "EventCode": "0x2", + "UMask": "0x08", + "CompId": "0x3", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_0", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_1", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_2", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 2 (CS2). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_read_requests_cs_3", + "BriefDescription": "Number of inbound I/O read requests to memory in = 64-byte units for Coherent Subordinate 3 (CS3). Some requests may be 32B, s= o the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x0F", + "CompId": "0x3", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_0", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 0 (CS0). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x0", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_1", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 1 (CS1). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x1", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_2", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 2 (CS2). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x2", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "EventName": "io_write_requests_cs_3", + "BriefDescription": "Number of inbound I/O write requests to memory in= 64-byte units for Coherent Subordinate 3 (CS3). Some requests may be 32B, = so the reported byte count may overestimate the actual data.", + "EventCode": "0x3", + "UMask": "0x70", + "CompId": "0x3", + "Unit": "HYGON_DF", + "ScaleUnit": "64Bytes" + }, + { + "MetricName": "cpu_memory_bandwidth", + "MetricExpr": "(cpu_read_requests_cs_0 + cpu_read_requests_cs_1 + cpu_= read_requests_cs_2 + cpu_read_requests_cs_3 + cpu_write_requests_cs_0 + cpu= _write_requests_cs_1 + cpu_write_requests_cs_2 + cpu_write_requests_cs_3) *= 64 / (duration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Total CPU memory access bandwidth", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_max_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_rea= d_requests_cs_2 + io_read_requests_cs_3 + io_write_requests_cs_0 + io_write= _requests_cs_1 + io_write_requests_cs_2 + io_write_requests_cs_3) * 64 / (d= uration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Maximum inbound I/O memory access bandwidth (uppe= r bound, assuming 64B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + }, + { + "MetricName": "io_memory_min_bandwidth", + "MetricExpr": "(io_read_requests_cs_0 + io_read_requests_cs_1 + io_rea= d_requests_cs_2 + io_read_requests_cs_3 + io_write_requests_cs_0 + io_write= _requests_cs_1 + io_write_requests_cs_2 + io_write_requests_cs_3) * 32 / (d= uration_time * 1e6)", + "MetricConstraint": "NO_GROUP_EVENTS", + "BriefDescription": "Minimum inbound I/O memory access bandwidth (lowe= r bound, assuming 32B per request. Actual inbound I/O requests may be 32B o= r 64B)", + "MetricGroup": "DF_Memory_BW", + "ScaleUnit": "1MB/s" + } +] diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-ev= ents/arch/x86/mapfile.csv index 50a403b429b1..ba17117245d1 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -45,3 +45,6 @@ AuthenticAMD-25-([245][[:xdigit:]]|[[:xdigit:]]),v1,amdze= n3,core AuthenticAMD-25-[[:xdigit:]]+,v1,amdzen4,core AuthenticAMD-26-([12467][[:xdigit:]]|[[:xdigit:]]),v1,amdzen5,core AuthenticAMD-26-[[:xdigit:]]+,v1,amdzen6,core +HygonGenuine-24-[0123],v1,hygonm1,core +HygonGenuine-24-[45],v1,hygonm4,core +HygonGenuine-24-(1[012345678]|[6789ABCDEF]),v1,hygonm6,core diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jeven= ts.py index 376dc2d24162..07a843d92483 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -294,6 +294,7 @@ class JsonEvent: 'L3PMC': 'amd_l3', 'DFPMC': 'amd_df', 'UMCPMC': 'amd_umc', + 'HYGON_DF': 'hygon_df', 'cpu_core': 'cpu_core', 'cpu_atom': 'cpu_atom', 'ali_drw': 'ali_drw', @@ -390,6 +391,7 @@ class JsonEvent: ('Invert', 'inv=3D'), ('SampleAfterValue', 'period=3D'), ('UMask', 'umask=3D'), + ('CompId', 'compid=3D'), ('NodeType', 'type=3D'), ('RdWrMask', 'rdwrmask=3D'), ('EnAllCores', 'enallcores=3D'), --=20 2.34.1