All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Poirier <mathieu.poirier@linaro.org>
To: Mike Leach <mike.leach@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org,
	suzuki.poulose@arm.com, leo.yan@linaro.org
Subject: Re: [PATCH v3 4/5] coresight: tools: Add config file write and reader tools
Date: Thu, 26 May 2022 11:46:02 -0600	[thread overview]
Message-ID: <20220526174602.GA309576@p14s> (raw)
In-Reply-To: <20220414064457.12052-5-mike.leach@linaro.org>

On Thu, Apr 14, 2022 at 07:44:56AM +0100, Mike Leach wrote:
> Add an example file generator to test loading configurations via a
> binary attribute in configfs.
> 
> Provides a file buffer writer function that can be re-used in other
> userspace programs.
> 
> Buffer write format matches that expected by the corresponding reader
> in the configfs driver code.
> 
> Add a config file reader and printer. Takes in config files and prints
> the contents. Uses file reader source from kernel driver.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  MAINTAINERS                                   |   2 +
>  .../coresight/coresight-config-file.c         |   2 +
>  tools/coresight/Makefile                      |  51 +++
>  tools/coresight/coresight-cfg-bufw.c          | 303 ++++++++++++++++++
>  tools/coresight/coresight-cfg-bufw.h          |  26 ++
>  tools/coresight/coresight-cfg-example1.c      |  65 ++++
>  tools/coresight/coresight-cfg-examples.h      |  27 ++
>  tools/coresight/coresight-cfg-file-read.c     | 197 ++++++++++++
>  tools/coresight/coresight-cfg-filegen.c       |  58 ++++
>  tools/include/uapi/coresight-config-uapi.h    |  76 +++++
>  10 files changed, 807 insertions(+)
>  create mode 100644 tools/coresight/Makefile
>  create mode 100644 tools/coresight/coresight-cfg-bufw.c
>  create mode 100644 tools/coresight/coresight-cfg-bufw.h
>  create mode 100644 tools/coresight/coresight-cfg-example1.c
>  create mode 100644 tools/coresight/coresight-cfg-examples.h
>  create mode 100644 tools/coresight/coresight-cfg-file-read.c
>  create mode 100644 tools/coresight/coresight-cfg-filegen.c
>  create mode 100644 tools/include/uapi/coresight-config-uapi.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 61d9f114c37f..4e59486e75b5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1985,6 +1985,8 @@ F:	drivers/hwtracing/coresight/*
>  F:	include/dt-bindings/arm/coresight-cti-dt.h
>  F:	include/linux/coresight*
>  F:	samples/coresight/*
> +F:	tools/coresight/*
> +F:	tools/include/uapi/coresight-config-uapi.h
>  F:	tools/perf/arch/arm/util/auxtrace.c
>  F:	tools/perf/arch/arm/util/cs-etm.c
>  F:	tools/perf/arch/arm/util/cs-etm.h
> diff --git a/drivers/hwtracing/coresight/coresight-config-file.c b/drivers/hwtracing/coresight/coresight-config-file.c
> index 5b8f635ac50e..4a8b64405d84 100644
> --- a/drivers/hwtracing/coresight/coresight-config-file.c
> +++ b/drivers/hwtracing/coresight/coresight-config-file.c
> @@ -36,6 +36,8 @@ static void *cscfg_zalloc(size_t size)
>  #include <string.h>
>  #include <stdlib.h>
>  
> +#include "uapi/coresight-config-uapi.h"
> +
>  static void *cscfg_calloc(size_t num, size_t size)
>  {
>  	return calloc(num, size);
> diff --git a/tools/coresight/Makefile b/tools/coresight/Makefile
> new file mode 100644
> index 000000000000..4004c315d65c
> --- /dev/null
> +++ b/tools/coresight/Makefile
> @@ -0,0 +1,51 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +include ../scripts/Makefile.include
> +include ../scripts/Makefile.arch
> +
> +# Makefile to build the coresight configuration file reader and generator tools
> +
> +this-makefile := $(lastword $(MAKEFILE_LIST))
> +tools-src := $(realpath $(dir $(this-makefile)))
> +srctree := $(realpath $(dir $(tools-src)/../../.))
> +
> +# ensure we use all as the default - skip anything in included Makefile
> +.DEFAULT_GOAL = all
> +# MAKECMDGOALS isn't set if there's no explicit goal in the
> +# command line, so set the default.
> +MAKECMDGOALS ?= $(.DEFAULT_GOAL)
> +
> +# compile flags
> +CFLAGS += $(CPPFLAGS) -c -Wall -DLINUX -Wno-switch -Wlogical-op -fPIC -I$(srctree)/drivers/hwtracing/coresight -I$(srctree)/tools/include/  -I$(srctree)/tools/include/uapi
> +
> +# object files
> +coresight-cfg-file-gen-objs := coresight-cfg-filegen.o coresight-cfg-bufw.o coresight-cfg-example1.o
> +coresight-cfg-file-read-objs := coresight-cfg-file-read.o coresight-config-file.o
> +
> +# debug variant
> +ifdef DEBUG
> +CFLAGS += -g -O0 -DDEBUG
> +else
> +CFLAGS += -O2 -DNDEBUG
> +endif
> +
> +.PHONY: all
> +all:  coresight-cfg-file-gen coresight-cfg-file-read
> +
> +coresight-config-file.o: src_copy
> +	$(CC) $(CFLAGS) coresight-config-file.c -o coresight-config-file.o
> +
> +.PHONY: src_copy
> +src_copy:
> +	@cp $(srctree)/drivers/hwtracing/coresight/coresight-config-file.c $(srctree)/tools/coresight/.
> +
> +coresight-cfg-file-gen: $(coresight-cfg-file-gen-objs)
> +	$(CC) $(LDFLAGS) $(coresight-cfg-file-gen-objs) -o coresight-cfg-file-gen
> +
> +coresight-cfg-file-read: $(coresight-cfg-file-read-objs)
> +	$(CC) $(LDFLAGS) $(coresight-cfg-file-read-objs) -o coresight-cfg-file-read
> +
> +clean:
> +	rm -f coresight-cfg-file-gen coresight-cfg-file-read
> +	rm -f *.o
> +	rm -f coresight-config-file.c
> +	rm -f *.cscfg
> diff --git a/tools/coresight/coresight-cfg-bufw.c b/tools/coresight/coresight-cfg-bufw.c
> new file mode 100644
> index 000000000000..73223de2b7e0
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-bufw.c
> @@ -0,0 +1,303 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include <string.h>
> +
> +#include "coresight-cfg-bufw.h"
> +#include "uapi/coresight-config-uapi.h"
> +
> +/*
> + * Set of macros to make writing the buffer code easier.
> + *.
> + * Uses naming convention as 'buffer' for the buffer pointer and
> + * 'used' as the current bytes used by the encosing function.
> + */
> +#define cscfg_write_u64(val64) {	\
> +	*(u64 *)(buffer + used) = val64; \
> +	used += sizeof(u64); \
> +	}
> +
> +#define cscfg_write_u32(val32) { \
> +	*(u32 *)(buffer + used) = val32;	\
> +	used += sizeof(u32); \
> +	}
> +
> +#define cscfg_write_u16(val16) { \
> +	*(u16 *)(buffer + used) = val16;	\
> +	used += sizeof(u16); \
> +	}
> +
> +#define cscfg_write_u8(val8) { \
> +	*(buffer + used) = val8;	\
> +	used++;	\
> +	}
> +
> +#define CHECK_WRET(rval) { \
> +	if (rval < 0) \
> +		return rval;	   \
> +	used += rval;		   \
> +	}
> +

Either use a single space between the code and the '\' character or align them
all on the same column.

> +/* write the header at the start of the buffer */
> +static int cscfg_file_write_fhdr(u8 *buffer, const int buflen,
> +				 const struct cscfg_file_header *fhdr)
> +{
> +	int used = 0;
> +
> +	cscfg_write_u32(fhdr->magic_version);
> +	cscfg_write_u16(fhdr->length);
> +	cscfg_write_u16(fhdr->nr_features);
> +	return used;
> +}
> +
> +static int cscfg_file_write_string(u8 *buffer, const int buflen, const char *string)
> +{
> +	int len, used = 0;
> +
> +	len = strlen(string);
> +	if (len > CSCFG_FILE_STR_MAXSIZE)
> +		return -EINVAL;
> +
> +	if (buflen < (len + 1 + sizeof(u16)))
> +		return -EINVAL;
> +
> +	cscfg_write_u16((u16)(len + 1));
> +	strcpy((char *)(buffer + used), string);
> +	used += (len + 1);
> +
> +	return used;
> +}
> +
> +static int cscfg_file_write_elem_hdr(u8 *buffer, const int buflen,
> +				     struct cscfg_file_elem_header *ehdr)
> +{
> +	int used = 0;
> +
> +	if (buflen < (sizeof(u16) + sizeof(u8)))
> +		return -EINVAL;
> +
> +	cscfg_write_u16(ehdr->elem_length);
> +	cscfg_write_u8(ehdr->elem_type);
> +
> +	return used;
> +}
> +
> +

Extra line.

> +static int cscfg_file_write_config(u8 *buffer, const int buflen,
> +				   struct cscfg_config_desc *config_desc)
> +{
> +	int used = 0, bytes_w, space_req, preset_bytes, i;
> +	struct cscfg_file_elem_header ehdr;
> +
> +	ehdr.elem_length = 0;
> +	ehdr.elem_type = CSCFG_FILE_ELEM_TYPE_CFG;
> +
> +	/* write element header at current buffer location */
> +	bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr);
> +	CHECK_WRET(bytes_w);
> +
> +	/* write out the configuration name */
> +	bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +					  config_desc->name);
> +	CHECK_WRET(bytes_w);
> +
> +	/* write out the description string */
> +	bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +					  config_desc->description);
> +	CHECK_WRET(bytes_w);
> +
> +	/*
> +	 * calculate the space needed for variables + presets
> +	 * [u16 value - nr_presets]
> +	 * [u32 value - nr_total_params]
> +	 * [u16 value - nr_feat_refs]
> +	 * [u64 values] * (nr_presets * nr_total_params)
> +	 */
> +	preset_bytes = sizeof(u64) * config_desc->nr_presets * config_desc->nr_total_params;
> +	space_req = (sizeof(u16) * 2) + sizeof(u32) + preset_bytes;
> +
> +	if ((buflen - used) < space_req)
> +		return -EINVAL;
> +
> +	cscfg_write_u16((u16)config_desc->nr_presets);
> +	cscfg_write_u32((u32)config_desc->nr_total_params);
> +	cscfg_write_u16((u16)config_desc->nr_feat_refs);
> +	if (preset_bytes) {
> +		memcpy(buffer + used, (u8 *)config_desc->presets, preset_bytes);
> +		used += preset_bytes;
> +	}
> +
> +	/* now write the feature ref names */
> +	for (i = 0; i < config_desc->nr_feat_refs; i++) {
> +		bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +						  config_desc->feat_ref_names[i]);
> +		CHECK_WRET(bytes_w);
> +	}
> +
> +	/* rewrite the element header with the correct length */
> +	ehdr.elem_length = used;
> +	bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr);
> +	/* no CHECK_WRET as used must not be updated */
> +	if (bytes_w < 0)
> +		return bytes_w;
> +
> +	return used;
> +}
> +
> +/*
> + * write a parameter structure into the buffer in following format:
> + * [cscfg_file_elem_str]    - parameter name.
> + * [u64 value: param_value] - initial value.
> + */
> +static int cscfg_file_write_param(u8 *buffer, const int buflen,
> +				  struct cscfg_parameter_desc *param_desc)
> +{
> +	int used = 0, bytes_w;
> +
> +	bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +					  param_desc->name);
> +	CHECK_WRET(bytes_w);
> +
> +	if ((buflen - used) < sizeof(u64))
> +		return -EINVAL;
> +
> +	cscfg_write_u64(param_desc->value);
> +	return used;
> +}

Add an extra line.

> +/*
> + * Write a feature element from cscfg_feature_desc in following format:
> + *
> + * [cscfg_file_elem_header] - header length is total bytes to end of param structures.
> + * [cscfg_file_elem_str]    - feature name.
> + * [cscfg_file_elem_str]    - feature description.
> + * [u32 value: match_flags]
> + * [u16 value: nr_regs]	    - number of registers.
> + * [u16 value: nr_params]   - number of parameters.
> + * [cscfg_regval_desc struct] * nr_regs
> + * [PARAM_ELEM] * nr_params
> + *
> + *

Two extra lines.

> + */
> +static int cscfg_file_write_feat(u8 *buffer, const int buflen,
> +				 struct cscfg_feature_desc *feat_desc)
> +{
> +	struct cscfg_file_elem_header ehdr;
> +	struct cscfg_regval_desc *p_reg_desc;
> +	int used = 0, bytes_w, i, space_req;
> +	u32 val32;
> +
> +	ehdr.elem_length = 0;
> +	ehdr.elem_type = CSCFG_FILE_ELEM_TYPE_FEAT;
> +
> +	/* write element header at current buffer location */
> +	bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr);
> +	CHECK_WRET(bytes_w);
> +
> +	/* write out the name string */
> +	bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +					  feat_desc->name);
> +	CHECK_WRET(bytes_w)
> +
> +	/* write out the description string */
> +	bytes_w = cscfg_file_write_string(buffer + used, buflen - used,
> +					  feat_desc->description);
> +	CHECK_WRET(bytes_w);
> +
> +	/* check for space for variables and register structures */
> +	space_req = (sizeof(u16) * 2) + sizeof(u32) +
> +		(sizeof(struct cscfg_regval_desc) * feat_desc->nr_regs);
> +	if ((buflen - used) < space_req)
> +		return -EINVAL;
> +
> +	/* write the variables */
> +	cscfg_write_u32((u32)feat_desc->match_flags);
> +	cscfg_write_u16((u16)feat_desc->nr_regs);
> +	cscfg_write_u16((u16)feat_desc->nr_params);
> +
> +	/*write the registers */
> +	for (i = 0; i < feat_desc->nr_regs; i++) {
> +		p_reg_desc = (struct cscfg_regval_desc *)&feat_desc->regs_desc[i];
> +		CSCFG_FILE_REG_DESC_INFO_TO_U32(val32, p_reg_desc);
> +		cscfg_write_u32(val32);
> +		cscfg_write_u64(feat_desc->regs_desc[i].val64);
> +	}
> +
> +	/* write any parameters */
> +	for (i = 0; i < feat_desc->nr_params; i++) {
> +		bytes_w = cscfg_file_write_param(buffer + used, buflen - used,
> +						 &feat_desc->params_desc[i]);
> +		CHECK_WRET(bytes_w);
> +	}
> +
> +	/*
> +	 * rewrite the element header at the start of the buffer block
> +	 * with the correct length
> +	 */
> +	ehdr.elem_length = used;
> +	bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr);
> +	/* no CHECK_WRET as used must not be updated */
> +	if (bytes_w < 0)
> +		return bytes_w;
> +
> +	return used;
> +}
> +
> +/*
> + * write a buffer from the configuration and feature
> + * descriptors to write into a file for configfs.
> + *
> + * Will only write one config, and/or a number of features,
> + * per the file standard.
> + */
> +int cscfg_file_write_buffer(u8 *buffer, const int buflen,
> +			    struct cscfg_config_desc *config_desc,
> +			    struct cscfg_feature_desc **feat_descs)
> +{
> +	struct cscfg_file_header fhdr;
> +	int used = 0,  bytes_w, i;
> +
> +	/* init the file header */
> +	fhdr.magic_version = CSCFG_FILE_MAGIC_VERSION;
> +	fhdr.length = 0;
> +	fhdr.nr_features = 0;
> +
> +	/* count the features */
> +	if (feat_descs) {
> +		while (feat_descs[fhdr.nr_features])
> +			fhdr.nr_features++;
> +	}
> +
> +	/* need a buffer and at least one config or feature */
> +	if ((!config_desc && !fhdr.nr_features) ||
> +	    !buffer || (buflen > CSCFG_FILE_MAXSIZE))
> +		return -EINVAL;
> +
> +	/* write a header at the start to get the length of the header */
> +	bytes_w = cscfg_file_write_fhdr(buffer, buflen, &fhdr);
> +	CHECK_WRET(bytes_w);
> +
> +	/* write a single config */
> +	if (config_desc) {
> +		bytes_w = cscfg_file_write_config(buffer + used, buflen - used,
> +						  config_desc);
> +		CHECK_WRET(bytes_w);
> +	}
> +
> +	/* write any features */
> +	for (i = 0; i < fhdr.nr_features; i++) {
> +		bytes_w = cscfg_file_write_feat(buffer + used, buflen - used,
> +						feat_descs[i]);
> +		CHECK_WRET(bytes_w);
> +	}
> +
> +	/* finally re-write the header at the buffer start with the correct length */
> +	fhdr.length = (u16)used;
> +	bytes_w = cscfg_file_write_fhdr(buffer, buflen, &fhdr);
> +	/* no CHECK_WRET as used must not be updated */
> +	if (bytes_w < 0)
> +		return bytes_w;
> +	return used;
> +}
> diff --git a/tools/coresight/coresight-cfg-bufw.h b/tools/coresight/coresight-cfg-bufw.h
> new file mode 100644
> index 000000000000..562df97599fc
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-bufw.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#ifndef _CORESIGHT_CFG_BUFW_H
> +#define _CORESIGHT_CFG_BUFW_H
> +
> +#include <linux/types.h>
> +
> +#include "coresight-config-file.h"
> +
> +/*
> + * Function to take coresight configurations and features and
> + * write them into a supplied memory buffer for serialisation
> + * into a file.
> + *
> + * Resulting file can then be loaded into the coresight
> + * infrastructure via configfs.
> + */
> +int cscfg_file_write_buffer(u8 *buffer, const int buflen,
> +			    struct cscfg_config_desc *config_desc,
> +			    struct cscfg_feature_desc **feat_descs);
> +
> +#endif /* _CORESIGHT_CFG_BUFW_H */
> diff --git a/tools/coresight/coresight-cfg-example1.c b/tools/coresight/coresight-cfg-example1.c
> new file mode 100644
> index 000000000000..a71a6e43d7b3
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-example1.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +#include <linux/types.h>
> +#include <linux/unistd.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +#include "coresight-cfg-bufw.h"

There is no need to include coresight-cfg-bufw.h.

> +#include "coresight-cfg-examples.h"
> +
> +/*
> + * create a configuration only example using the strobing feature
> + */
> +
> +/* we will provide 4 sets of preset parameter values */
> +#define AFDO3_NR_PRESETS	4
> +/* the total number of parameters in used features - strobing has 2 */
> +#define AFDO3_NR_PARAM_SUM	2
> +
> +static const char *afdo3_ref_names[] = {
> +	"strobing",
> +};
> +
> +/*
> + * set of presets leaves strobing window constant while varying period to allow
> + * experimentation with mark / space ratios for various workloads
> + */
> +static u64 afdo3_presets[AFDO3_NR_PRESETS][AFDO3_NR_PARAM_SUM] = {
> +	{ 2000, 100 },
> +	{ 2000, 1000 },
> +	{ 2000, 5000 },
> +	{ 2000, 10000 },
> +};
> +
> +struct cscfg_config_desc afdo3 = {
> +	.name = "autofdo3",
> +	.description = "Setup ETMs with strobing for autofdo\n"
> +	"Supplied presets allow experimentation with mark-space ratio for various loads\n",
> +	.nr_feat_refs = ARRAY_SIZE(afdo3_ref_names),
> +	.feat_ref_names = afdo3_ref_names,
> +	.nr_presets = AFDO3_NR_PRESETS,
> +	.nr_total_params = AFDO3_NR_PARAM_SUM,
> +	.presets = &afdo3_presets[0][0],
> +};
> +
> +static struct cscfg_feature_desc *sample_feats[] = {
> +	NULL
> +};
> +
> +static struct cscfg_config_desc *sample_cfgs[] = {
> +	&afdo3,
> +	NULL
> +};
> +
> +#define CSCFG_EG1_FILENAME "example1.cscfg"

Not sure there is any value in specifying a define...  I'd just hard code it the
same way it was done for "example1".

> +
> +struct cscfg_file_eg_info buff_info_eg1 = {
> +	.example_name = "example1",
> +	.filename = CSCFG_EG1_FILENAME,
> +	.config_descs = sample_cfgs,
> +	.feat_descs = sample_feats,
> +};
> diff --git a/tools/coresight/coresight-cfg-examples.h b/tools/coresight/coresight-cfg-examples.h
> new file mode 100644
> index 000000000000..5c6908745201
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-examples.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#ifndef _CORESIGHT_CFG_EXAMPLES_H
> +#define _CORESIGHT_CFG_EXAMPLES_H
> +
> +#include <linux/kernel.h>
> +
> +#include "uapi/coresight-config-uapi.h"
> +#include "coresight-cfg-bufw.h"

Same here.

> +
> +/* structure to pass configuraiton information to generator program */
> +struct cscfg_file_eg_info {
> +	const char *example_name;
> +	const char *filename;
> +	struct cscfg_config_desc **config_descs;
> +	struct cscfg_feature_desc **feat_descs;
> +};
> +
> +
> +/* references to the configuration and feature example structures */
> +extern struct cscfg_file_eg_info buff_info_eg1;

I would put this in coresight-cfg-filegen.c.  That way people only have to
change a single file rather than two.

More comments to follow on this file.  I am not sure there is a need to read
.cscfg files.

> +
> +#endif /* _CORESIGHT_CFG_EXAMPLES_H */
> diff --git a/tools/coresight/coresight-cfg-file-read.c b/tools/coresight/coresight-cfg-file-read.c
> new file mode 100644
> index 000000000000..da7b831eb2df
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-file-read.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include <linux/types.h>
> +#include <linux/unistd.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +#include "coresight-config-file.h"
> +#include "uapi/coresight-config-uapi.h"
> +
> +/*
> + * tool to read and print a generated configuration
> + * re-uses the read code source from the driver.
> + */
> +
> +static void print_configs(struct cscfg_fs_load_descs *load_descs)
> +{
> +	struct cscfg_config_desc *config_desc = load_descs->config_descs[0];
> +	int i, j, p;
> +
> +	if (!config_desc) {
> +		printf("File contains no configurations.\n\n");
> +		return;
> +	}
> +
> +	printf("Configuration name : %s\n", config_desc->name);
> +	printf("Uses %d features:-\n", config_desc->nr_feat_refs);
> +	for (i = 0; i < config_desc->nr_feat_refs; i++)
> +		printf("Feature-%d: %s\n", i + 1, config_desc->feat_ref_names[i]);
> +
> +	printf("\nProvides %d sets of preset values, %d presets per set\n", config_desc->nr_presets,
> +	       config_desc->nr_total_params);
> +	if (config_desc->nr_presets) {
> +		for (i = 0; i < config_desc->nr_presets; i++) {
> +			printf("set[%d]: ", i);
> +			for (j = 0; j < config_desc->nr_total_params; j++) {
> +				p = (i * config_desc->nr_total_params) + j;
> +				printf("0x%lx, ",  config_desc->presets[p]);
> +			}
> +			printf("\n");
> +		}
> +	}
> +	printf("\n\n");
> +}
> +
> +static void print_reg_type_info(u8 type)
> +{
> +	if (type & CS_CFG_REG_TYPE_STD)
> +		printf("std_reg ");
> +	if (type & CS_CFG_REG_TYPE_RESOURCE)
> +		printf("resource ");
> +	if (type & CS_CFG_REG_TYPE_VAL_PARAM)
> +		printf("param_index ");
> +	if (type & CS_CFG_REG_TYPE_VAL_64BIT)
> +		printf("64_bit ");
> +	else
> +		printf("32_bit ");
> +	if (type & CS_CFG_REG_TYPE_VAL_MASK)
> +		printf("masked ");
> +	if (type & CS_CFG_REG_TYPE_VAL_SAVE)
> +		printf("save_on_disable ");
> +
> +}
> +
> +static void print_regs(int nr, struct cscfg_regval_desc *regs_desc_array)
> +{
> +	int i;
> +	struct cscfg_regval_desc *reg_desc;
> +	u8 type;
> +	u16 offset;
> +	u16 info;
> +
> +	for (i = 0; i < nr; i++) {
> +		reg_desc = &regs_desc_array[i];
> +		type = (u8)reg_desc->type;
> +		offset = (u16)reg_desc->offset;
> +		info = (u16)reg_desc->hw_info;
> +
> +		printf("Reg(%d): Type 0x%x: ", i, type);
> +		print_reg_type_info(type);
> +		printf("\nOffset: 0x%03x; HW Info: 0x%03x\n", offset, info);
> +		printf("Value: ");
> +		if (type & CS_CFG_REG_TYPE_VAL_64BIT)
> +			printf("0x%lx\n", reg_desc->val64);
> +		else if (type & CS_CFG_REG_TYPE_VAL_PARAM)
> +			printf("idx = %d\n", reg_desc->param_idx);
> +		else {
> +			printf("0x%x ", reg_desc->val32);
> +			if (type & CS_CFG_REG_TYPE_VAL_MASK)
> +				printf(" mask: 0x%x", reg_desc->mask32);
> +			printf("\n");
> +		}
> +	}
> +}
> +
> +static void print_params(int nr, struct cscfg_parameter_desc *params_desc)
> +{
> +	int i;
> +
> +	for (i = 0; i < nr; i++)
> +		printf("Param(%d) : %s; Init value 0x%lx\n", i,
> +		       params_desc[i].name, params_desc[i].value);
> +}
> +
> +static void print_features(struct cscfg_fs_load_descs *load_descs)
> +{
> +	struct cscfg_feature_desc *feat_desc = 0;
> +	int idx = 0;
> +
> +	feat_desc = load_descs->feat_descs[idx];
> +	if (!feat_desc) {
> +		printf("File contains no features\n\n");
> +		return;
> +	}
> +
> +	while (feat_desc) {
> +		printf("Feature %d name : %s\n", idx+1, feat_desc->name);
> +		printf("Description: %s\n", feat_desc->description);
> +		printf("Match flags: 0x%x\n", feat_desc->match_flags);
> +		printf("Number of Paraneters: %d\n", feat_desc->nr_params);
> +		if (feat_desc->nr_params)
> +			print_params(feat_desc->nr_params, feat_desc->params_desc);
> +		printf("Number of Registers: %d\n", feat_desc->nr_regs);
> +		if (feat_desc->nr_regs)
> +			print_regs(feat_desc->nr_regs, feat_desc->regs_desc);
> +		printf("\n\n");
> +
> +		/* next feature */
> +		idx++;
> +		feat_desc = load_descs->feat_descs[idx];
> +	}
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	FILE *fp;
> +	struct cscfg_fs_load_descs *load_descs;
> +	int err, fsize;
> +	u8 buffer[CSCFG_FILE_MAXSIZE];
> +
> +	printf("CoreSight Configuration file reader\n\n");
> +
> +	/* need a filename */
> +	if (argc <= 1) {
> +		printf("Please provide filename on command line\n");
> +		return -EINVAL;
> +	}
> +
> +	/* open file and read into the buffer. */
> +	fp = fopen(argv[1], "rb");
> +	if (fp == NULL) {
> +		printf("Error opening file %s\n", argv[1]);
> +		return -EINVAL;
> +	}
> +
> +	fseek(fp, 0, SEEK_END);
> +	fsize = ftell(fp);
> +	rewind(fp);
> +	if (fsize > CSCFG_FILE_MAXSIZE) {
> +		printf("Error: Input file too large.");
> +		fclose(fp);
> +		return -EINVAL;
> +	}
> +	err = fread(buffer, sizeof(u8), fsize, fp);
> +	fclose(fp);
> +
> +	if (err < fsize) {
> +		printf("Error reading file %s\n", argv[1]);
> +		return -EINVAL;
> +	}
> +
> +	/* allocate the descriptor structures to be populated by read operation */
> +	load_descs = malloc(sizeof(struct cscfg_fs_load_descs));
> +	if (!load_descs) {
> +		printf("Error allocating load descs structure.\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* read the buffer and create the configuration and feature structures */
> +	err = cscfg_file_read_buffer(buffer, fsize, load_descs);
> +	if (err) {
> +		printf("Error reading configuration file\n");
> +		goto exit_free_mem;
> +	}
> +	/* print the contents of the structures */
> +	print_configs(load_descs);
> +	print_features(load_descs);
> +
> +exit_free_mem:
> +	free(load_descs);
> +	return err;
> +}
> diff --git a/tools/coresight/coresight-cfg-filegen.c b/tools/coresight/coresight-cfg-filegen.c
> new file mode 100644
> index 000000000000..cd0589661d92
> --- /dev/null
> +++ b/tools/coresight/coresight-cfg-filegen.c
> @@ -0,0 +1,58 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include <linux/types.h>
> +#include <linux/unistd.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +#include "uapi/coresight-config-uapi.h"
> +#include "coresight-cfg-bufw.h"
> +#include "coresight-cfg-examples.h"
> +
> +
> +/* array of example files to generate */
> +struct cscfg_file_eg_info *info_ptrs[] = {
> +	&buff_info_eg1,
> +	NULL,
> +};
> +
> +int main(int argc, char **argv)
> +{
> +	struct cscfg_config_desc *config_desc;
> +	struct cscfg_feature_desc **feat_descs;
> +	u8 buffer[CSCFG_FILE_MAXSIZE];
> +	int used, idx = 0;
> +	FILE *fp;
> +	const char *filename;
> +
> +	printf("Coresight Configuration file Generator\n\n");
> +
> +	while (info_ptrs[idx]) {
> +		printf("Generating %s example\n", info_ptrs[idx]->example_name);
> +		config_desc = info_ptrs[idx]->config_descs[0];
> +		feat_descs = info_ptrs[idx]->feat_descs;
> +		filename = info_ptrs[idx]->filename;
> +		used = cscfg_file_write_buffer(buffer, CSCFG_FILE_MAXSIZE,
> +					       config_desc, feat_descs);
> +
> +		if (used < 0) {
> +			printf("Error %d writing configuration %s into buffer\n",
> +			       used, info_ptrs[idx]->example_name);
> +			return used;
> +		}
> +
> +		fp = fopen(filename, "wb");
> +		if (fp == NULL) {
> +			printf("Error opening file %s\n", filename);
> +			return -1;
> +		}
> +		fwrite(buffer, used, sizeof(u8), fp);
> +		fclose(fp);
> +		idx++;
> +	}
> +	return 0;
> +}
> diff --git a/tools/include/uapi/coresight-config-uapi.h b/tools/include/uapi/coresight-config-uapi.h
> new file mode 100644
> index 000000000000..d051c01ea982
> --- /dev/null
> +++ b/tools/include/uapi/coresight-config-uapi.h
> @@ -0,0 +1,76 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2020 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#ifndef _CORESIGHT_CORESIGHT_CONFIG_UAPI_H
> +#define _CORESIGHT_CORESIGHT_CONFIG_UAPI_H
> +
> +#include <linux/types.h>
> +#include <asm-generic/errno-base.h>
> +
> +#include "coresight-config.h"
> +
> +/*
> + * Userspace versions of the configuration and feature descriptors.
> + * Used in the tools/coresight programs.
> + *
> + * Compatible with structures in coresight-config.h for use in
> + * coresight-config-file.c common reader source file.
> + */
> +
> +/**
> + * Device feature descriptor - combination of registers and parameters to
> + * program a device to implement a specific complex function.
> + *
> + * UAPI version - removed kernel constructs.
> + *
> + * @name:	 feature name.
> + * @description: brief description of the feature.
> + * @match_flags: matching information if loading into a device
> + * @nr_params:   number of parameters used.
> + * @params_desc: array of parameters used.
> + * @nr_regs:	 number of registers used.
> + * @regs_desc:	 array of registers used.
> + */
> +struct cscfg_feature_desc {
> +	const char *name;
> +	const char *description;
> +	u32 match_flags;
> +	int nr_params;
> +	struct cscfg_parameter_desc *params_desc;
> +	int nr_regs;
> +	struct cscfg_regval_desc *regs_desc;
> +};
> +
> +/**
> + * Configuration descriptor - describes selectable system configuration.
> + *
> + * A configuration describes device features in use, and may provide preset
> + * values for the parameters in those features.
> + *
> + * A single set of presets is the sum of the parameters declared by
> + * all the features in use - this value is @nr_total_params.
> + *
> + * UAPI version - removed kernel constructs.
> + *
> + * @name:		name of the configuration - used for selection.
> + * @description:	description of the purpose of the configuration.
> + * @nr_feat_refs:	Number of features used in this configuration.
> + * @feat_ref_names:	references to features used in this configuration.
> + * @nr_presets:		Number of sets of presets supplied by this configuration.
> + * @nr_total_params:	Sum of all parameters declared by used features
> + * @presets:		Array of preset values.
> + */
> +struct cscfg_config_desc {
> +	const char *name;
> +	const char *description;
> +	int nr_feat_refs;
> +	const char **feat_ref_names;
> +	int nr_presets;
> +	int nr_total_params;
> +	const u64 *presets; /* nr_presets * nr_total_params */
> +};
> +
> +#endif /* _CORESIGHT_CORESIGHT_CONFIG_UAPI_H */
> -- 
> 2.17.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2022-05-26 17:47 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-14  6:44 [PATCH v3 0/5] coresight: syscfg: Extend configfs for config load Mike Leach
2022-04-14  6:44 ` [PATCH v3 1/5] coresight: configfs: Add in functionality for load via configfs Mike Leach
2022-05-11 17:58   ` Mathieu Poirier
2022-05-16 12:43     ` Mike Leach
2022-05-12 17:54   ` Mathieu Poirier
2022-05-25 17:38   ` Mathieu Poirier
2022-06-01  8:32     ` Mike Leach
2022-04-14  6:44 ` [PATCH v3 2/5] coresight: configfs: Add in binary attributes to load files Mike Leach
2022-05-25 18:00   ` Mathieu Poirier
2022-05-25 19:30   ` Mathieu Poirier
2022-06-01  8:33     ` Mike Leach
2022-04-14  6:44 ` [PATCH v3 3/5] coresight: configfs: Modify config files to allow userspace use Mike Leach
2022-05-25 19:57   ` Mathieu Poirier
2022-04-14  6:44 ` [PATCH v3 4/5] coresight: tools: Add config file write and reader tools Mike Leach
2022-05-26 17:46   ` Mathieu Poirier [this message]
2022-05-27 16:25   ` Mathieu Poirier
2022-06-01 10:56     ` Mike Leach
2022-06-01 16:10       ` Mathieu Poirier
2022-04-14  6:44 ` [PATCH v3 5/5] Documentation: coresight: docs for config load via configfs Mike Leach
2022-05-26 17:48   ` Mathieu Poirier
2022-05-10 15:39 ` [PATCH v3 0/5] coresight: syscfg: Extend configfs for config load Mathieu Poirier
2022-05-27 16:32 ` Mathieu Poirier
2022-06-01  8:30   ` Mike Leach

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=20220526174602.GA309576@p14s \
    --to=mathieu.poirier@linaro.org \
    --cc=coresight@lists.linaro.org \
    --cc=leo.yan@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mike.leach@linaro.org \
    --cc=suzuki.poulose@arm.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.