All of lore.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Swapnil Sapkal <swapnil.sapkal@amd.com>
Cc: peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	irogers@google.com, james.clark@arm.com, ravi.bangoria@amd.com,
	yu.c.chen@intel.com, mark.rutland@arm.com,
	alexander.shishkin@linux.intel.com, jolsa@kernel.org,
	rostedt@goodmis.org, vincent.guittot@linaro.org,
	adrian.hunter@intel.com, kan.liang@linux.intel.com,
	gautham.shenoy@amd.com, kprateek.nayak@amd.com,
	juri.lelli@redhat.com, yangjihong@bytedance.com,
	void@manifault.com, tj@kernel.org, sshegde@linux.ibm.com,
	ctshao@google.com, quic_zhonhan@quicinc.com,
	thomas.falcon@intel.com, blakejones@google.com,
	ashelat@redhat.com, leo.yan@arm.com, dvyukov@google.com,
	ak@linux.intel.com, yujie.liu@intel.com, graham.woodward@arm.com,
	ben.gainey@arm.com, vineethr@linux.ibm.com,
	tim.c.chen@linux.intel.com, linux@treblig.org,
	linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	santosh.shukla@amd.com, sandipan.das@amd.com
Subject: Re: [PATCH RESEND v4 03/11] perf header: Support CPU DOMAIN relation info
Date: Fri, 2 Jan 2026 14:26:44 -0800	[thread overview]
Message-ID: <aVhGJJBp0F5kygFt@google.com> (raw)
In-Reply-To: <20250909114227.58802-4-swapnil.sapkal@amd.com>

On Tue, Sep 09, 2025 at 11:42:19AM +0000, Swapnil Sapkal wrote:
> '/proc/schedstat' gives the info about load balancing statistics within
> a given domain. It also contains the cpu_mask giving information about
> the sibling cpus and domain names after schedstat version 17. Storing
> this information in perf header will help tools like `perf sched stats`
> for better analysis.
> 
> Signed-off-by: Swapnil Sapkal <swapnil.sapkal@amd.com>
> ---
>  .../Documentation/perf.data-file-format.txt   |  17 +
>  tools/perf/builtin-inject.c                   |   1 +
>  tools/perf/util/env.h                         |  16 +
>  tools/perf/util/header.c                      | 304 ++++++++++++++++++
>  tools/perf/util/header.h                      |   1 +
>  tools/perf/util/util.c                        |  42 +++
>  tools/perf/util/util.h                        |   3 +
>  7 files changed, 384 insertions(+)
> 
> diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
> index cd95ba09f727..92dbba1003cf 100644
> --- a/tools/perf/Documentation/perf.data-file-format.txt
> +++ b/tools/perf/Documentation/perf.data-file-format.txt
> @@ -437,6 +437,23 @@ struct {
>  	} [nr_pmu];
>  };
>  
> +	HEADER_CPU_DOMAIN_INFO = 32,
> +
> +List of cpu-domain relation info. The format of the data is as below.
> +
> +struct domain_info {
> +	int domain;
> +	char dname[];
> +	char cpumask[];
> +	char cpulist[];
> +};
> +
> +struct cpu_domain_info {
> +	int cpu;
> +	int nr_domains;
> +	struct domain_info domains[];
> +};
> +
>  	other bits are reserved and should ignored for now
>  	HEADER_FEAT_BITS	= 256,
>  
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index a114b3fa1bea..f43a7ec44b5f 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -2058,6 +2058,7 @@ static bool keep_feat(int feat)
>  	case HEADER_CLOCK_DATA:
>  	case HEADER_HYBRID_TOPOLOGY:
>  	case HEADER_PMU_CAPS:
> +	case HEADER_CPU_DOMAIN_INFO:
>  		return true;
>  	/* Information that can be updated */
>  	case HEADER_BUILD_ID:
> diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
> index e00179787a34..71034c4b4488 100644
> --- a/tools/perf/util/env.h
> +++ b/tools/perf/util/env.h
> @@ -54,6 +54,19 @@ struct pmu_caps {
>  	char            *pmu_name;
>  };
>  
> +struct domain_info {
> +	u32	domain;
> +	char	*dname;
> +	char	*cpumask;
> +	char	*cpulist;
> +};
> +
> +struct cpu_domain_map {
> +	u32			cpu;
> +	u32			nr_domains;
> +	struct domain_info	**domains;
> +};
> +
>  typedef const char *(arch_syscalls__strerrno_t)(int err);
>  
>  struct perf_env {
> @@ -70,6 +83,8 @@ struct perf_env {
>  	unsigned int		max_branches;
>  	unsigned int		br_cntr_nr;
>  	unsigned int		br_cntr_width;
> +	unsigned int		schedstat_version;
> +	unsigned int		max_sched_domains;
>  	int			kernel_is_64_bit;
>  
>  	int			nr_cmdline;
> @@ -92,6 +107,7 @@ struct perf_env {
>  	char			**cpu_pmu_caps;
>  	struct cpu_topology_map	*cpu;
>  	struct cpu_cache_level	*caches;
> +	struct cpu_domain_map	**cpu_domain;
>  	int			 caches_cnt;
>  	u32			comp_ratio;
>  	u32			comp_ver;
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 4f2a6e10ed5c..7ff7434bac2c 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -1621,6 +1621,184 @@ static int write_pmu_caps(struct feat_fd *ff,
>  	return 0;
>  }
>  
> +static void free_cpu_domain_info(struct cpu_domain_map **cd_map, u32 schedstat_version, u32 nr)
> +{
> +	for (u32 i = 0; i < nr; i++) {
> +		if (cd_map[i]->domains) {
> +			for (u32 j = 0; j < cd_map[i]->nr_domains; j++) {
> +				struct domain_info *d_info = cd_map[i]->domains[j];
> +

I'm not sure if it needs a NULL check for d_info before access.


> +				if (schedstat_version >= 17)
> +					free(d_info->dname);
> +
> +				free(d_info->cpumask);
> +				free(d_info->cpulist);
> +			}
> +			free(cd_map[i]->domains);
> +		}
> +	}
> +
> +	free(cd_map);
> +}
> +
> +static struct cpu_domain_map  **build_cpu_domain_map(u32 *schedstat_version, u32 *max_sched_domains,
> +						     u32 nr)
> +{
> +	struct domain_info *domain_info;
> +	struct cpu_domain_map **cd_map;
> +	char dname[16], cpumask[256];
> +	char cpulist[1024];
> +	char *line = NULL;
> +	u32 cpu, domain;
> +	u32 dcount = 0;
> +	size_t len;
> +	FILE *fp;
> +
> +	fp = fopen("/proc/schedstat", "r");
> +	if (!fp) {
> +		pr_err("Failed to open /proc/schedstat\n");
> +		return NULL;
> +	}
> +
> +	cd_map = calloc(nr, sizeof(*cd_map));
> +	if (!cd_map)
> +		goto out;
> +
> +	while (getline(&line, &len, fp) > 0) {
> +		int retval;
> +
> +		if (strncmp(line, "version", 7) == 0) {
> +			retval = sscanf(line, "version %d\n", schedstat_version);
> +			if (retval != 1)
> +				continue;
> +
> +		} else if (strncmp(line, "cpu", 3) == 0) {
> +			retval = sscanf(line, "cpu%u %*s", &cpu);
> +			if (retval == 1) {
> +				cd_map[cpu] = calloc(1, sizeof(*cd_map[cpu]));
> +				if (!cd_map[cpu])
> +					goto out_free_line;
> +				cd_map[cpu]->cpu = cpu;
> +			} else
> +				continue;
> +
> +			dcount = 0;
> +		} else if (strncmp(line, "domain", 6) == 0) {
> +			dcount++;
> +
> +			cd_map[cpu]->domains = realloc(cd_map[cpu]->domains,
> +						       dcount * sizeof(domain_info));
> +			if (!cd_map[cpu]->domains)
> +				goto out_free_line;

Please use a temporary variable to save the result in order to not lose
the original pointer in case of failure.

> +
> +			domain_info = calloc(1, sizeof(*domain_info));
> +			if (!domain_info)
> +				goto out_free_line;
> +
> +			cd_map[cpu]->domains[dcount - 1] = domain_info;
> +
> +			if (*schedstat_version >= 17) {
> +				retval = sscanf(line, "domain%u %s %s %*s", &domain, dname,
> +						cpumask);
> +				if (retval != 3)
> +					continue;
> +
> +				domain_info->dname = calloc(strlen(dname) + 1, sizeof(char));
> +				if (!domain_info->dname)
> +					goto out_free_line;
> +
> +				strcpy(domain_info->dname, dname);

This can be simply:
				domain_info->dname = strdup(dname);


> +			} else {
> +				retval = sscanf(line, "domain%u %s %*s", &domain, cpumask);
> +				if (retval != 2)
> +					continue;
> +			}
> +
> +			domain_info->domain = domain;
> +			if (domain > *max_sched_domains)
> +				*max_sched_domains = domain;
> +
> +			domain_info->cpumask = calloc(strlen(cpumask) + 1, sizeof(char));
> +			if (!domain_info->cpumask)
> +				goto out_free_line;
> +
> +			strcpy(domain_info->cpumask, cpumask);
> +
> +			cpumask_to_cpulist(cpumask, cpulist);
> +			domain_info->cpulist = calloc(strlen(cpulist) + 1, sizeof(char));
> +			if (!domain_info->cpulist)
> +				goto out_free_line;

All error paths should call free_cpu_domain_info() at some point and
free the intermediate domain_info properly.

> +
> +			strcpy(domain_info->cpulist, cpulist);
> +			cd_map[cpu]->nr_domains = dcount;
> +		}
> +	}
> +
> +out_free_line:
> +	free(line);
> +out:
> +	fclose(fp);
> +	return cd_map;
> +}
> +
> +static int write_cpu_domain_info(struct feat_fd *ff,
> +				 struct evlist *evlist __maybe_unused)
> +{
> +	u32 max_sched_domains = 0, schedstat_version = 0;
> +	struct cpu_domain_map **cd_map;
> +	u32 i, j, nr, ret;
> +
> +	nr = cpu__max_present_cpu().cpu;
> +
> +	cd_map = build_cpu_domain_map(&schedstat_version, &max_sched_domains, nr);
> +	if (!cd_map)
> +		return -1;
> +
> +	ret = do_write(ff, &schedstat_version, sizeof(u32));
> +	if (ret < 0)
> +		goto out;
> +
> +	max_sched_domains += 1;
> +	ret = do_write(ff, &max_sched_domains, sizeof(u32));
> +	if (ret < 0)
> +		goto out;
> +
> +	for (i = 0; i < nr; i++) {
> +		if (cd_map[i]->domains) {

Is it supposed to have NULL domains?  Anyway it'd be nice if you can
skip the case like with 'continue' statement to reduce the indentation
level.

> +			ret = do_write(ff, &cd_map[i]->cpu, sizeof(u32));
> +			if (ret < 0)
> +				goto out;
> +
> +			ret = do_write(ff, &cd_map[i]->nr_domains, sizeof(u32));
> +			if (ret < 0)
> +				goto out;
> +
> +			for (j = 0; j < cd_map[i]->nr_domains; j++) {
> +				ret = do_write(ff, &cd_map[i]->domains[j]->domain, sizeof(u32));
> +				if (ret < 0)
> +					goto out;
> +				if (schedstat_version >= 17) {
> +					ret = do_write_string(ff, cd_map[i]->domains[j]->dname);
> +					if (ret < 0)
> +						goto out;
> +				}
> +
> +				ret = do_write_string(ff, cd_map[i]->domains[j]->cpumask);
> +				if (ret < 0)
> +					goto out;
> +
> +				ret = do_write_string(ff, cd_map[i]->domains[j]->cpulist);
> +				if (ret < 0)
> +					goto out;
> +			}
> +		}
> +	}
> +
> +out:
> +	free_cpu_domain_info(cd_map, schedstat_version, nr);
> +	return ret;
> +}
> +
>  static void print_hostname(struct feat_fd *ff, FILE *fp)
>  {
>  	fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
> @@ -2254,6 +2432,35 @@ static void print_mem_topology(struct feat_fd *ff, FILE *fp)
>  	}
>  }
>  
> +static void print_cpu_domain_info(struct feat_fd *ff, FILE *fp)
> +{
> +	struct cpu_domain_map **cd_map = ff->ph->env.cpu_domain;
> +	u32 nr = ff->ph->env.nr_cpus_avail;
> +	struct domain_info *d_info;
> +	u32 i, j;
> +
> +	fprintf(fp, "# schedstat version	: %u\n", ff->ph->env.schedstat_version);
> +	fprintf(fp, "# Maximum sched domains	: %u\n", ff->ph->env.max_sched_domains);
> +
> +	for (i = 0; i < nr; i++) {
> +		if (cd_map[i]->domains) {

Ditto.

> +			fprintf(fp, "# cpu		: %u\n", cd_map[i]->cpu);
> +			fprintf(fp, "# nr_domains	: %u\n", cd_map[i]->nr_domains);
> +
> +			for (j = 0; j < cd_map[i]->nr_domains; j++) {
> +				d_info = cd_map[i]->domains[j];
> +				fprintf(fp, "# Domain		: %u\n", d_info->domain);
> +
> +				if (ff->ph->env.schedstat_version >= 17)
> +					fprintf(fp, "# Domain name      : %s\n", d_info->dname);
> +
> +				fprintf(fp, "# Domain cpu map   : %s\n", d_info->cpumask);
> +				fprintf(fp, "# Domain cpu list  : %s\n", d_info->cpulist);
> +			}
> +		}
> +	}
> +}
> +
>  static int __event_process_build_id(struct perf_record_header_build_id *bev,
>  				    char *filename,
>  				    struct perf_session *session)
> @@ -3395,6 +3602,102 @@ static int process_pmu_caps(struct feat_fd *ff, void *data __maybe_unused)
>  	return ret;
>  }
>  
> +static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused)
> +{
> +	u32 schedstat_version, max_sched_domains, cpu, domain, nr_domains;
> +	struct perf_env *env = &ff->ph->env;
> +	char *dname, *cpumask, *cpulist;
> +	struct cpu_domain_map **cd_map;
> +	struct domain_info *d_info;
> +	u32 nra, nr, i, j;
> +	int ret;
> +
> +	nra = env->nr_cpus_avail;
> +	nr = env->nr_cpus_online;
> +
> +	cd_map = calloc(nra, sizeof(*cd_map));
> +	if (!cd_map)
> +		return -1;
> +
> +	env->cpu_domain = cd_map;

Where is it freed?

Thanks,
Namhyung

> +
> +	ret = do_read_u32(ff, &schedstat_version);
> +	if (ret)
> +		return ret;
> +
> +	env->schedstat_version = schedstat_version;
> +
> +	ret = do_read_u32(ff, &max_sched_domains);
> +	if (ret)
> +		return ret;
> +
> +	env->max_sched_domains = max_sched_domains;
> +
> +	for (i = 0; i < nr; i++) {
> +		if (do_read_u32(ff, &cpu))
> +			return -1;
> +
> +		cd_map[cpu] = calloc(1, sizeof(*cd_map[cpu]));
> +		if (!cd_map[cpu])
> +			return -1;
> +
> +		cd_map[cpu]->cpu = cpu;
> +
> +		if (do_read_u32(ff, &nr_domains))
> +			return -1;
> +
> +		cd_map[cpu]->nr_domains = nr_domains;
> +
> +		cd_map[cpu]->domains = calloc(max_sched_domains, sizeof(*d_info));
> +		if (!cd_map[cpu]->domains)
> +			return -1;
> +
> +		for (j = 0; j < nr_domains; j++) {
> +			if (do_read_u32(ff, &domain))
> +				return -1;
> +
> +			d_info = calloc(1, sizeof(*d_info));
> +			if (!d_info)
> +				return -1;
> +
> +			cd_map[cpu]->domains[domain] = d_info;
> +			d_info->domain = domain;
> +
> +			if (schedstat_version >= 17) {
> +				dname = do_read_string(ff);
> +				if (!dname)
> +					return -1;
> +
> +				d_info->dname = calloc(strlen(dname) + 1, sizeof(char));
> +				if (!d_info->dname)
> +					return -1;
> +
> +				strcpy(d_info->dname, dname);
> +			}
> +
> +			cpumask = do_read_string(ff);
> +			if (!cpumask)
> +				return -1;
> +
> +			d_info->cpumask = calloc(strlen(cpumask) + 1, sizeof(char));
> +			if (!d_info->cpumask)
> +				return -1;
> +			strcpy(d_info->cpumask, cpumask);
> +
> +			cpulist = do_read_string(ff);
> +			if (!cpulist)
> +				return -1;
> +
> +			d_info->cpulist = calloc(strlen(cpulist) + 1, sizeof(char));
> +			if (!d_info->cpulist)
> +				return -1;
> +			strcpy(d_info->cpulist, cpulist);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  #define FEAT_OPR(n, func, __full_only) \
>  	[HEADER_##n] = {					\
>  		.name	    = __stringify(n),			\
> @@ -3460,6 +3763,7 @@ const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
>  	FEAT_OPR(CLOCK_DATA,	clock_data,	false),
>  	FEAT_OPN(HYBRID_TOPOLOGY,	hybrid_topology,	true),
>  	FEAT_OPR(PMU_CAPS,	pmu_caps,	false),
> +	FEAT_OPR(CPU_DOMAIN_INFO,	cpu_domain_info,	true),
>  };
>  
>  struct header_print_data {
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index d16dfceccd74..edcb95e0dc49 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -53,6 +53,7 @@ enum {
>  	HEADER_CLOCK_DATA,
>  	HEADER_HYBRID_TOPOLOGY,
>  	HEADER_PMU_CAPS,
> +	HEADER_CPU_DOMAIN_INFO,
>  	HEADER_LAST_FEATURE,
>  	HEADER_FEAT_BITS	= 256,
>  };
> diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
> index 1b91834e11de..47bfc0259b0e 100644
> --- a/tools/perf/util/util.c
> +++ b/tools/perf/util/util.c
> @@ -263,6 +263,48 @@ void print_separator(int pre_dash_cnt, const char *s, int post_dash_cnt)
>  	       graph_dotted_line);
>  }
>  
> +void cpumask_to_cpulist(char *cpumask, char *cpulist)
> +{
> +	int i, j, bm_size, nbits;
> +	int len = strlen(cpumask);
> +	unsigned long *bm;
> +	char cpus[1024];
> +
> +	for (i = 0; i < len; i++) {
> +		if (cpumask[i] == ',') {
> +			for (j = i; j < len; j++)
> +				cpumask[j] = cpumask[j + 1];
> +		}
> +	}
> +
> +	len = strlen(cpumask);
> +	bm_size = (len + 15) / 16;
> +	nbits = bm_size * 64;
> +	if (nbits <= 0)
> +		return;
> +
> +	bm = calloc(bm_size, sizeof(unsigned long));
> +	if (!cpumask)
> +		goto free_bm;
> +
> +	for (i = 0; i < bm_size; i++) {
> +		char blk[17];
> +		int blklen = len > 16 ? 16 : len;
> +
> +		strncpy(blk, cpumask + len - blklen, blklen);
> +		blk[len] = '\0';
> +		bm[i] = strtoul(blk, NULL, 16);
> +		cpumask[len - blklen] = '\0';
> +		len = strlen(cpumask);
> +	}
> +
> +	bitmap_scnprintf(bm, nbits, cpus, sizeof(cpus));
> +	strcpy(cpulist, cpus);
> +
> +free_bm:
> +	free(bm);
> +}
> +
>  int rm_rf_perf_data(const char *path)
>  {
>  	const char *pat[] = {
> diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> index de69384380c2..90a8b4d2e59c 100644
> --- a/tools/perf/util/util.h
> +++ b/tools/perf/util/util.h
> @@ -11,6 +11,7 @@
>  #include <stdbool.h>
>  #include <stddef.h>
>  #include <linux/compiler.h>
> +#include <linux/bitmap.h>
>  #include <sys/types.h>
>  #ifndef __cplusplus
>  #include <internal/cpumap.h>
> @@ -50,6 +51,8 @@ int perf_tip(char **strp, const char *dirpath);
>  
>  void print_separator(int pre_dash_cnt, const char *s, int post_dash_cnt);
>  
> +void cpumask_to_cpulist(char *cpumask, char *cpulist);
> +
>  #ifndef HAVE_SCHED_GETCPU_SUPPORT
>  int sched_getcpu(void);
>  #endif
> -- 
> 2.43.0
> 

  parent reply	other threads:[~2026-01-02 22:26 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-09 11:42 [PATCH RESEND v4 00/11] perf sched: Introduce stats tool Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 01/11] perf: Add print_separator to util Swapnil Sapkal
2026-01-02 22:12   ` Namhyung Kim
2026-01-09 11:23     ` Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 02/11] tools/lib: Add list_is_first() Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 03/11] perf header: Support CPU DOMAIN relation info Swapnil Sapkal
2025-09-17  6:20   ` kernel test robot
2026-01-02 22:26   ` Namhyung Kim [this message]
2026-01-09 11:24     ` Swapnil Sapkal
2026-01-19 18:11       ` Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 04/11] perf sched stats: Add record and rawdump support Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 05/11] perf sched stats: Add schedstat v16 support Swapnil Sapkal
2026-01-02 22:28   ` Namhyung Kim
2026-01-09 11:24     ` Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 06/11] perf sched stats: Add schedstat v17 support Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 07/11] perf sched stats: Add support for report subcommand Swapnil Sapkal
2026-01-02 22:35   ` Namhyung Kim
2026-01-09 11:25     ` Swapnil Sapkal
2026-01-19 18:35       ` Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 08/11] perf sched stats: Add support for live mode Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 09/11] perf sched stats: Add support for diff subcommand Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 10/11] perf sched stats: Add basic perf sched stats test Swapnil Sapkal
2025-09-09 11:42 ` [PATCH RESEND v4 11/11] perf sched stats: Add details in man page Swapnil Sapkal

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=aVhGJJBp0F5kygFt@google.com \
    --to=namhyung@kernel.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=ashelat@redhat.com \
    --cc=ben.gainey@arm.com \
    --cc=blakejones@google.com \
    --cc=ctshao@google.com \
    --cc=dvyukov@google.com \
    --cc=gautham.shenoy@amd.com \
    --cc=graham.woodward@arm.com \
    --cc=irogers@google.com \
    --cc=james.clark@arm.com \
    --cc=jolsa@kernel.org \
    --cc=juri.lelli@redhat.com \
    --cc=kan.liang@linux.intel.com \
    --cc=kprateek.nayak@amd.com \
    --cc=leo.yan@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux@treblig.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=quic_zhonhan@quicinc.com \
    --cc=ravi.bangoria@amd.com \
    --cc=rostedt@goodmis.org \
    --cc=sandipan.das@amd.com \
    --cc=santosh.shukla@amd.com \
    --cc=sshegde@linux.ibm.com \
    --cc=swapnil.sapkal@amd.com \
    --cc=thomas.falcon@intel.com \
    --cc=tim.c.chen@linux.intel.com \
    --cc=tj@kernel.org \
    --cc=vincent.guittot@linaro.org \
    --cc=vineethr@linux.ibm.com \
    --cc=void@manifault.com \
    --cc=yangjihong@bytedance.com \
    --cc=yu.c.chen@intel.com \
    --cc=yujie.liu@intel.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.