[PATCH v3 4/5] coresight: tools: Add config file write and reader tools
Mathieu Poirier
mathieu.poirier at linaro.org
Fri May 27 09:25:34 PDT 2022
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 at 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 at 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; \
> + }
> +
> +/* 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;
> +}
> +
> +
> +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;
> +}
> +/*
> + * 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
> + *
> + *
> + */
> +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 at 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 at linaro.org>
> + */
> +#include <linux/types.h>
> +#include <linux/unistd.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +#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"
> +
> +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 at 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"
> +
> +/* 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;
> +
> +#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 at 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 = ®s_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 at 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 at 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 */
> +};
I would call the above cscfg_feature_fs_desc and cscfg_config_fs_desc to make
sure they don't get confused with the kernel's internal structures of the same name.
Moreover, I would keep this file private to tools/coresight/ and rename it
coresight-config.h.
> +
> +#endif /* _CORESIGHT_CORESIGHT_CONFIG_UAPI_H */
> --
> 2.17.1
>
More information about the linux-arm-kernel
mailing list