Add a userspace program to read and print a configuration generated for loading via the configfs attributes.
Signed-off-by: Mike Leach mike.leach@linaro.org --- samples/coresight/Makefile | 20 +- samples/coresight/Makefile.host | 47 +++++ samples/coresight/coresight-cfg-file-read.c | 191 ++++++++++++++++++++ 3 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 samples/coresight/Makefile.host create mode 100644 samples/coresight/coresight-cfg-file-read.c
diff --git a/samples/coresight/Makefile b/samples/coresight/Makefile index 07bfd99d7a68..ad8f29a77881 100644 --- a/samples/coresight/Makefile +++ b/samples/coresight/Makefile @@ -4,8 +4,24 @@ obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight-cfg-sample.o ccflags-y += -I$(srctree)/drivers/hwtracing/coresight
-# coresight config - configfs loadable binary config generator -userprogs-always-y += coresight-cfg-filegen +# coresight config - configfs loadable binary config generator & reader +userprogs-always-y += coresight-cfg-filegen coresight-cfg-file-read
coresight-cfg-filegen-objs := coresight-cfg-filegen.o coresight-cfg-bufw.o +coresight-cfg-file-read-objs := coresight-cfg-file-read.o coresight-config-file.o + +# pull in the coresight headers userccflags += -I$(srctree)/drivers/hwtracing/coresight + +# need to copy over the reader source from the driver tree - to build separately +CORESIGHT_SRC_PATH := $(abspath $(srctree)/$(src)) + +$(src)/coresight-config-file.c: copy_coresight_source + +.PHONY: copy_coresight_source + +copy_coresight_source: + @cp $(CORESIGHT_SRC_PATH)/../../drivers/hwtracing/coresight/coresight-config-file.c $(CORESIGHT_SRC_PATH)/. + +# clean up the copy after use. +clean-files += coresight-config-file.c diff --git a/samples/coresight/Makefile.host b/samples/coresight/Makefile.host new file mode 100644 index 000000000000..fc01f33bc1ff --- /dev/null +++ b/samples/coresight/Makefile.host @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# Makefile to build just the example userspace programs on host m/c + +this-makefile := $(lastword $(MAKEFILE_LIST)) +sample-src := $(realpath $(dir $(this-makefile))) +srctree := $(realpath $(dir $(sample-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) + +# include the main Makefile to use some of the vars from it +include Makefile + +# compile flags +CFLAGS += $(CPPFLAGS) -c -Wall -DLINUX -Wno-switch -Wlogical-op -fPIC $(userccflags) + +# debug variant +ifdef DEBUG +CFLAGS += -g -O0 -DDEBUG +else +CFLAGS += -O2 -DNDEBUG +endif + +.PHONY: all +all: coresight-cfg-filegen 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 $(sample-src)/. + +coresight-cfg-filegen: $(coresight-cfg-filegen-objs) + $(CC) $(LDFLAGS) $(coresight-cfg-filegen-objs) -o coresight-cfg-filegen + +coresight-cfg-file-read: $(coresight-cfg-file-read-objs) + $(CC) $(LDFLAGS) $(coresight-cfg-file-read-objs) -o coresight-cfg-file-read + +clean: + rm -f $(userprogs-always-y) + rm -f *.o + rm -f $(clean-files) diff --git a/samples/coresight/coresight-cfg-file-read.c b/samples/coresight/coresight-cfg-file-read.c new file mode 100644 index 000000000000..4e0fd840428f --- /dev/null +++ b/samples/coresight/coresight-cfg-file-read.c @@ -0,0 +1,191 @@ +// 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" + +/* + * 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%llx, ", 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%llx\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%llx\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; + } + fread(buffer, sizeof(u8), fsize, fp); + fclose(fp); + + /* 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; +}