Hi Mathieu,
I've fixed up the minor comments from your previous mail
On Fri, 27 May 2022 at 17:25, Mathieu Poirier mathieu.poirier@linaro.org wrote:
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; \
}
+/* 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@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" +#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@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@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@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 */
+};
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.
The issue here is that the common reader code expects structs of these names.
The alternative was to put multiple #if _KERNEL__ defines in the middle of the structures in the kernel headers to eliminate kernel only elements- which you pointed out in your comments to v2 of this set was a maintenence issue.
This is a least worst alternative. We have common reader code, there are minimal changes to the kernel headers - some of the structures in coresight-config.h are backeted by a __KERNEL__ define but those without kernel specific elements are used in full.
The cost is maintaining these two structures to be the same as the kernel versions - which I believe to be minimal as I do not expect the data format to change going forwards.
Moreover, I would keep this file private to tools/coresight/ and rename it coresight-config.h.
I can and have moved it. Howver this file includes the kernel coresight-config.h, so renaming is a non-starter.
Thanks and Regards
Mike
+#endif /* _CORESIGHT_CORESIGHT_CONFIG_UAPI_H */
2.17.1