@@ -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
new file mode 100644
@@ -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)
new file mode 100644
@@ -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;
+}
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