* [PATCH 0/6] coresight: syscfg: Extend configfs for config load.
@ 2021-11-01 22:47 Mike Leach
2021-11-01 22:47 ` [PATCH 1/6] coresight: configfs: Add in functionality for load via configfs Mike Leach
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
This set extends the configfs support to allow loading and unloading of
configurations as binary files via configfs.
Additional attributes - load, unload and last_load_status are provided to
implement the load functionality.
Routines to generate binary configuration files are supplied in
./samples/coresight.
Documentation is updated to describe feature usage.
Set applies on top of dynamic load set here:
https://lists.linaro.org/pipermail/coresight/2021-October/007254.html
Mike Leach (6):
coresight: configfs: Add in functionality for load via configfs
coresight: configfs: Add in binary attributes to load files
coresight: configfs: Modify config files to allow userspace use
coresight: samples: Add an example config writer for configfs load
coresight: samples: Add coresight file reader sample program
Documentation: coresight: Update coresight configuration docs
.../trace/coresight/coresight-config.rst | 65 ++-
drivers/hwtracing/coresight/Makefile | 2 +-
.../coresight/coresight-config-file.c | 472 ++++++++++++++++++
.../coresight/coresight-config-file.h | 158 ++++++
.../hwtracing/coresight/coresight-config.h | 38 ++
.../coresight/coresight-syscfg-configfs.c | 148 +++++-
.../coresight/coresight-syscfg-configfs.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 36 ++
.../hwtracing/coresight/coresight-syscfg.h | 2 +
samples/coresight/Makefile | 23 +
samples/coresight/Makefile.host | 39 ++
samples/coresight/coresight-cfg-bufw.c | 302 +++++++++++
samples/coresight/coresight-cfg-bufw.h | 24 +
samples/coresight/coresight-cfg-file-read.c | 191 +++++++
samples/coresight/coresight-cfg-filegen.c | 89 ++++
15 files changed, 1583 insertions(+), 14 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config-file.c
create mode 100644 drivers/hwtracing/coresight/coresight-config-file.h
create mode 100644 samples/coresight/Makefile.host
create mode 100644 samples/coresight/coresight-cfg-bufw.c
create mode 100644 samples/coresight/coresight-cfg-bufw.h
create mode 100644 samples/coresight/coresight-cfg-file-read.c
create mode 100644 samples/coresight/coresight-cfg-filegen.c
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] coresight: configfs: Add in functionality for load via configfs
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
2021-11-01 22:47 ` [PATCH 2/6] coresight: configfs: Add in binary attributes to load files Mike Leach
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
Add in functionality to allow load via configfs.
define a binary file format and provide a reader for that format
that will create and populate configuration and feature structures
use by the driver infrastructure.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../coresight/coresight-config-file.c | 432 ++++++++++++++++++
.../coresight/coresight-config-file.h | 118 +++++
.../hwtracing/coresight/coresight-config.h | 17 +
.../hwtracing/coresight/coresight-syscfg.h | 1 +
5 files changed, 569 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config-file.c
create mode 100644 drivers/hwtracing/coresight/coresight-config-file.h
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index b6c4a48140ec..5de2bb79f4ac 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
coresight-sysfs.o coresight-syscfg.o coresight-config.o \
coresight-cfg-preload.o coresight-cfg-afdo.o \
- coresight-syscfg-configfs.o
+ coresight-syscfg-configfs.o coresight-config-file.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \
coresight-tmc-etr.o
diff --git a/drivers/hwtracing/coresight/coresight-config-file.c b/drivers/hwtracing/coresight/coresight-config-file.c
new file mode 100644
index 000000000000..3fd001938324
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-config-file.c
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include "coresight-config.h"
+#include "coresight-config-file.h"
+#include "coresight-syscfg.h"
+
+#define cscfg_extract_u64(val64) { \
+ val64 = *(u64 *)(buffer + used); \
+ used += sizeof(u64); \
+ }
+
+#define cscfg_extract_u32(val32) { \
+ val32 = *(u32 *)(buffer + used); \
+ used += sizeof(u32); \
+ }
+
+#define cscfg_extract_u16(val16) { \
+ val16 = *(u16 *)(buffer + used); \
+ used += sizeof(u16); \
+ }
+
+#define cscfg_extract_u8(val8) { \
+ val8 = *(buffer + used); \
+ used++; \
+ }
+
+static int cscfg_file_read_hdr(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_file_header *hdr)
+{
+ /* file header always at the start of the buffer */
+ int used = 0;
+
+ if (buflen < sizeof(struct cscfg_file_header))
+ return -EINVAL;
+
+ cscfg_extract_u32(hdr->magic_version);
+ if (hdr->magic_version != CSCFG_FILE_MAGIC_VERSION)
+ return -EINVAL;
+
+ cscfg_extract_u16(hdr->length);
+ if (hdr->length > buflen)
+ return -EINVAL;
+
+ cscfg_extract_u16(hdr->nr_features);
+
+ *buf_used = used;
+ return 0;
+}
+
+static int cscfg_file_read_elem_hdr(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_file_elem_header *elem_hdr)
+{
+ int used = *buf_used;
+
+ if ((buflen - used) < (sizeof(u16) + sizeof(u8)))
+ return -EINVAL;
+
+ /* read length and check enough buffer remains for this element */
+ elem_hdr->elem_length = *(u16 *)(buffer + used);
+ if ((buflen - used) < elem_hdr->elem_length)
+ return -EINVAL;
+ /* don't use extract fn as we update used _after_ the comparison */
+ used += sizeof(u16);
+
+ /* read type and validate */
+ cscfg_extract_u8(elem_hdr->elem_type);
+ if ((elem_hdr->elem_type < CSCFG_FILE_ELEM_TYPE_FEAT) ||
+ (elem_hdr->elem_type > CSCFG_FILE_ELEM_TYPE_CFG))
+ return -EINVAL;
+
+ *buf_used = used;
+ return 0;
+}
+
+static int cscfg_file_read_elem_str(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_file_elem_str *elem_str)
+{
+ int used = *buf_used;
+
+ if ((buflen - used) < sizeof(u16))
+ return -EINVAL;
+
+ cscfg_extract_u16(elem_str->str_len);
+
+ if ((buflen - used) < elem_str->str_len)
+ return -EINVAL;
+
+ /* check for 0 termination */
+ if (buffer[elem_str->str_len - 1] != 0)
+ return -EINVAL;
+
+ elem_str->str = devm_kstrdup(cscfg_device(), (char *)buffer, GFP_KERNEL);
+ used += elem_str->str_len;
+
+ *buf_used = used;
+ return 0;
+}
+
+static int cscfg_file_alloc_desc_arrays(struct cscfg_fs_load_descs *desc_arrays,
+ int nr_features)
+{
+ /* arrays are 0 terminated - max of 1 config & nr_features features */
+ desc_arrays->config_descs = devm_kcalloc(cscfg_device(), 2,
+ sizeof(struct cscfg_config_desc *),
+ GFP_KERNEL);
+ if (!desc_arrays->config_descs)
+ return -ENOMEM;
+ desc_arrays->feat_descs = devm_kcalloc(cscfg_device(), nr_features + 1,
+ sizeof(struct cscfg_feature_desc *),
+ GFP_KERNEL);
+ if (!desc_arrays->feat_descs)
+ return -ENOMEM;
+ return 0;
+}
+
+static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_fs_load_descs *desc_arrays)
+{
+ struct cscfg_file_elem_header elem_hdr;
+ struct cscfg_file_elem_str elem_str;
+ struct cscfg_config_desc *config_desc;
+ int used = *buf_used, nr_preset_vals, nr_preset_bytes, i;
+ int err = 0;
+ u64 *presets;
+
+ /*
+ * read the header - if not config, then don't update buf_used
+ * pointer on return
+ */
+ err = cscfg_file_read_elem_hdr(buffer, buflen, &used, &elem_hdr);
+ if (err)
+ return err;
+ if (elem_hdr.elem_type != CSCFG_FILE_ELEM_TYPE_CFG)
+ return 0;
+
+ /* we have a config - allocate the descriptor */
+ config_desc = devm_kzalloc(cscfg_device(), sizeof(struct cscfg_config_desc),
+ GFP_KERNEL);
+ if (!config_desc)
+ return -ENOMEM;
+
+ /* read the name string */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ config_desc->name = elem_str.str;
+
+ /* read the description string */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ config_desc->description = elem_str.str;
+
+ /* read in some values */
+ if ((buflen - used) < sizeof(u64))
+ return -EINVAL;
+ cscfg_extract_u16(config_desc->nr_presets);
+ cscfg_extract_u32(config_desc->nr_total_params);
+ cscfg_extract_u16(config_desc->nr_feat_refs);
+
+ /* read the array of 64bit presets if present */
+ nr_preset_vals = config_desc->nr_total_params * config_desc->nr_presets;
+ if (nr_preset_vals) {
+ presets = devm_kcalloc(cscfg_device(), nr_preset_vals,
+ sizeof(u64), GFP_KERNEL);
+ if (!presets)
+ return -ENOMEM;
+
+ nr_preset_bytes = sizeof(u64) * nr_preset_vals;
+ if ((buflen - used) < nr_preset_bytes)
+ return -EINVAL;
+
+ memcpy(presets, (buffer + used), nr_preset_bytes);
+ config_desc->presets = presets;
+ used += nr_preset_bytes;
+ }
+
+ /* read the array of feature names referenced by the config */
+ if (config_desc->nr_feat_refs) {
+ config_desc->feat_ref_names = devm_kcalloc(cscfg_device(),
+ config_desc->nr_feat_refs,
+ sizeof(char *),
+ GFP_KERNEL);
+ if (!config_desc->feat_ref_names)
+ return -ENOMEM;
+
+ for (i = 0; i < config_desc->nr_feat_refs; i++) {
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ config_desc->feat_ref_names[i] = elem_str.str;
+ }
+ }
+
+ desc_arrays->config_descs[0] = config_desc;
+ *buf_used = used;
+ return 0;
+}
+
+/* just read the config name - if there is a config at this position */
+static int cscfg_file_read_elem_config_name(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_file_elem_str *elem_str)
+{
+ struct cscfg_file_elem_header elem_hdr;
+ int used = *buf_used;
+ int err;
+
+ elem_str->str_len = 0;
+ /*
+ * read the header - if not config, then don't update buf_used
+ * pointer on return
+ */
+ err = cscfg_file_read_elem_hdr(buffer, buflen, &used, &elem_hdr);
+ if (err)
+ return err;
+ if (elem_hdr.elem_type != CSCFG_FILE_ELEM_TYPE_CFG)
+ return 0;
+
+ /* read the name string */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, elem_str);
+ if (err)
+ return err;
+ *buf_used = used;
+
+ return 0;
+}
+
+static int cscfg_file_read_elem_param(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_parameter_desc *param_desc)
+{
+ struct cscfg_file_elem_str elem_str;
+ int err = 0, used = *buf_used;
+
+ /* parameter name */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ param_desc->name = elem_str.str;
+
+ /* parameter value */
+ if ((buflen - used) < sizeof(u64))
+ return -EINVAL;
+ cscfg_extract_u64(param_desc->value);
+
+ *buf_used = used;
+ return err;
+}
+
+static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_fs_load_descs *desc_arrays,
+ const int feat_idx)
+{
+ struct cscfg_file_elem_header elem_hdr;
+ struct cscfg_file_elem_str elem_str;
+ struct cscfg_feature_desc *feat_desc;
+ struct cscfg_regval_desc *p_reg_desc;
+ int used = *buf_used, err, i, nr_regs_bytes;
+ u32 val32;
+
+ /* allocate the feature descriptor object */
+ feat_desc = devm_kzalloc(cscfg_device(), sizeof(struct cscfg_feature_desc),
+ GFP_KERNEL);
+ if (!feat_desc)
+ return -ENOMEM;
+
+ /* read and check the element header */
+ err = cscfg_file_read_elem_hdr(buffer, buflen, &used, &elem_hdr);
+ if (err)
+ return err;
+
+ if (elem_hdr.elem_type != CSCFG_FILE_ELEM_TYPE_FEAT)
+ return -EINVAL;
+
+ /* read the feature name */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ feat_desc->name = elem_str.str;
+
+ /* read the description string */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ feat_desc->description = elem_str.str;
+
+ /*
+ * read in some values
+ * [u32 value: match_flags]
+ * [u16 value: nr_regs] - number of registers.
+ * [u16 value: nr_params] - number of parameters.
+ */
+ cscfg_extract_u32(feat_desc->match_flags);
+ cscfg_extract_u16(feat_desc->nr_regs);
+ cscfg_extract_u16(feat_desc->nr_params);
+
+ /* register descriptors - 32 bit + 64 bit value */
+ if (feat_desc->nr_regs) {
+ nr_regs_bytes = ((sizeof(u32) + sizeof(u64)) * feat_desc->nr_regs);
+ if ((buflen - used) < nr_regs_bytes)
+ return -EINVAL;
+ feat_desc->regs_desc = devm_kcalloc(cscfg_device(),
+ feat_desc->nr_regs,
+ sizeof(struct cscfg_regval_desc),
+ GFP_KERNEL);
+ if (!feat_desc->regs_desc)
+ return -ENOMEM;
+
+ for (i = 0; i < feat_desc->nr_regs; i++) {
+ cscfg_extract_u32(val32);
+ p_reg_desc = (struct cscfg_regval_desc *)&feat_desc->regs_desc[i];
+ CSCFG_FILE_U32_TO_REG_DESC_INFO(val32, p_reg_desc);
+ cscfg_extract_u64(feat_desc->regs_desc[i].val64);
+ }
+ }
+
+ /* parameter descriptors - string + 64 bit value */
+ if (feat_desc->nr_params) {
+ feat_desc->params_desc = devm_kcalloc(cscfg_device(),
+ feat_desc->nr_params,
+ sizeof(struct cscfg_parameter_desc),
+ GFP_KERNEL);
+ if (!feat_desc->params_desc)
+ return -ENOMEM;
+ for (i = 0; i < feat_desc->nr_params; i++) {
+ err = cscfg_file_read_elem_param(buffer, buflen, &used,
+ &feat_desc->params_desc[i]);
+ if (err)
+ return err;
+ }
+ }
+
+ desc_arrays->feat_descs[feat_idx] = feat_desc;
+ *buf_used = used;
+ return 0;
+}
+
+/* just read the feature name - if there is a feature at this position */
+static int cscfg_file_read_elem_feat_name(const u8 *buffer, const int buflen, int *buf_used,
+ struct cscfg_file_elem_str *elem_str)
+{
+ struct cscfg_file_elem_header elem_hdr;
+ int used = *buf_used;
+ int err;
+
+ elem_str->str_len = 0;
+ /*
+ * read the header - if not config, then don't update buf_used
+ * pointer on return
+ */
+ err = cscfg_file_read_elem_hdr(buffer, buflen, &used, &elem_hdr);
+ if (err)
+ return err;
+ if (elem_hdr.elem_type != CSCFG_FILE_ELEM_TYPE_FEAT)
+ return -EINVAL;
+
+ /* read the feature name */
+ err = cscfg_file_read_elem_str(buffer, buflen, &used, elem_str);
+ if (err)
+ return err;
+ *buf_used = used;
+
+ return 0;
+}
+
+/*
+ * Read a buffer and create the configuration and feature
+ * descriptors to load into the cscfg system
+ */
+int cscfg_file_read_buffer(const u8 *buffer, const int buflen,
+ struct cscfg_fs_load_descs *desc_arrays)
+{
+ struct cscfg_file_header hdr;
+ int used = 0, err, i;
+
+ /* read in the file header */
+ err = cscfg_file_read_hdr(buffer, buflen, &used, &hdr);
+ if (err)
+ return err;
+
+ /* allocate the memory for the descriptor pointer arrays */
+ err = cscfg_file_alloc_desc_arrays(desc_arrays, hdr.nr_features);
+ if (err)
+ return err;
+
+ /* read elements */
+
+ /* first element could be a config so check */
+ err = cscfg_file_read_elem_config(buffer, buflen, &used, desc_arrays);
+ if (err)
+ return err;
+
+ /* now read and populate all the feature descriptors */
+ for (i = 0; i < hdr.nr_features; i++) {
+ err = cscfg_file_read_elem_feature(buffer, buflen, &used, desc_arrays, i);
+ if (err)
+ return err;
+ }
+ return used;
+}
+
+int cscfg_file_read_buffer_first_name(const u8 *buffer, const int buflen,
+ const char **name)
+{
+ struct cscfg_file_header hdr;
+ struct cscfg_file_elem_str elem_str;
+ int used = 0, err = 0;
+
+ *name = NULL;
+
+ /* read in the file header */
+ err = cscfg_file_read_hdr(buffer, buflen, &used, &hdr);
+ if (err)
+ return err;
+
+ err = cscfg_file_read_elem_config_name(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+
+ /* no config string - get first feature name */
+ if (!elem_str.str_len) {
+ err = cscfg_file_read_elem_feat_name(buffer, buflen, &used, &elem_str);
+ if (err)
+ return err;
+ }
+ if (elem_str.str_len)
+ *name = elem_str.str;
+ return err;
+}
diff --git a/drivers/hwtracing/coresight/coresight-config-file.h b/drivers/hwtracing/coresight/coresight-config-file.h
new file mode 100644
index 000000000000..6c8c5af0a614
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-config-file.h
@@ -0,0 +1,118 @@
+/* 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_FILE_H
+#define _CORESIGHT_CORESIGHT_CONFIG_FILE_H
+
+/*
+ * Structures to represent configuration descriptors in a memory buffer
+ * to serialise to and from files
+ *
+ * File structure - for loading a configuration + features
+ * from configfs.
+ *
+ * [cscfg_file_header] - mandatory
+ * [CONFIG_ELEM] - optional - only one permitted,
+ * [FEATURE_ELEM] * [cscfg_file_header.nr_features]
+ * - optional - file valid with config only.
+ *
+ * Invalid file if no config or features.
+ *
+ *
+ * File structure for [CONFIG_ELEM]:
+ *
+ * [cscfg_file_elem_header] - header length value to end of feature strings.
+ * [cscfg_file_elem_str] - name of the configuration
+ * [cscfg_file_elem_str] - description of configuration
+ * [u16 value - nr_presets]
+ * [u32 value - nr_total_params]
+ * [u16 value - nr_feat_refs]
+ * [u64 values] * (nr_presets * nr_total_params)
+ * [cscfg_file_elem_str] * nr_feat_refs
+ *
+ * Only one configuration per file.
+ *
+ * File structure for a [FEATURE_ELEM]
+ *
+ * [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
+ *
+ * File structure for [PARAM_ELEM]
+ *
+ * [cscfg_file_elem_str] - parameter name.
+ * [u64 value: param_value] - initial value.
+ */
+
+/* major element types - configurations and features */
+
+#define CSCFG_FILE_ELEM_TYPE_FEAT 0x1
+#define CSCFG_FILE_ELEM_TYPE_CFG 0x2
+
+#define CSCFG_FILE_MAGIC_VERSION 0xC5CF0001
+
+#define CSCFG_FILE_U32_TO_REG_DESC_INFO(val32, p_desc) \
+ { \
+ p_desc->type = (val32 >> 24) & 0xFF; \
+ p_desc->offset = (val32 >> 12) & 0xFFF; \
+ p_desc->hw_info = val32 & 0xFFF; \
+ }
+
+#define CSCFG_FILE_REG_DESC_INFO_TO_U32(val32, p_desc) \
+ { \
+ val32 = p_desc->hw_info & 0xFFF; \
+ val32 |= ((p_desc->offset & 0xFFF) << 12); \
+ val32 |= ((p_desc->type & 0xFF) << 24); \
+ }
+
+/* binary attributes in configfs need a max size - declare a value for this. */
+#define CSCFG_FILE_MAXSIZE 16384
+
+/* limit string sizes */
+#define CSCFG_FILE_STR_MAXSIZE 1024
+
+
+/**
+ * file header.
+ *
+ * @magic_version: magic number / version for file/buffer format.
+ * @length : total length of all data in the buffer.
+ * @nr_features : total number of features in the buffer.
+ */
+struct cscfg_file_header {
+ u32 magic_version;
+ u16 length;
+ u16 nr_features;
+};
+
+/**
+ * element header
+ *
+ * @elem_length: total length of this element
+ * @elem_type : type of this element - one of CSCFG_FILE_ELEM_TYPE.. defines.
+ */
+struct cscfg_file_elem_header {
+ u16 elem_length;
+ u8 elem_type;
+};
+
+/**
+ * string file element.
+ *
+ * @str_len: length of string buffer including 0 terminator
+ * @str : string buffer - 0 terminated.
+ */
+struct cscfg_file_elem_str {
+ u16 str_len;
+ char *str;
+};
+
+#endif /* _CORESIGHT_CORESIGHT_CONFIG_FILE_H */
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 9bd44b940add..770986316bc2 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -150,6 +150,23 @@ struct cscfg_config_desc {
struct config_group *fs_group;
};
+/**
+ * Dynamically loaded descriptor arrays loaded via configfs.
+ *
+ * For builtin or module loaded configurations / features these are
+ * statically defined at compile time. For configfs we create the arrays
+ * dynamically so need a structure to handle this.
+ *
+ * @owner_info: associated owner info struct to add to load order list.
+ * @config_descs: array of config descriptor pointers.
+ * @feat_descs: array of feature descriptor pointers.
+ */
+struct cscfg_fs_load_descs {
+ void *owner_info;
+ struct cscfg_config_desc **config_descs;
+ struct cscfg_feature_desc **feat_descs;
+};
+
/**
* config register instance - part of a loaded feature.
* maps register values to csdev driver structures
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
index 9106ffab4833..6a6e33585be9 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.h
+++ b/drivers/hwtracing/coresight/coresight-syscfg.h
@@ -66,6 +66,7 @@ struct cscfg_registered_csdev {
enum cscfg_load_owner_type {
CSCFG_OWNER_PRELOAD,
CSCFG_OWNER_MODULE,
+ CSCFG_OWNER_CONFIGFS,
};
/**
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] coresight: configfs: Add in binary attributes to load files
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
2021-11-01 22:47 ` [PATCH 1/6] coresight: configfs: Add in functionality for load via configfs Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
2021-11-01 22:47 ` [PATCH 3/6] coresight: configfs: Modify config files to allow userspace use Mike Leach
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
Add in functionality and binary attribute to load configurations
as binary data.
Reads the incoming attribute, which must be formatted correctly
as defined in the file reader code - and will create a configuration
and/or features and load them into the system.
These will then appear in configfs ready for use.
Unload functionality is also provided.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
.../coresight/coresight-config-file.h | 7 +
.../coresight/coresight-syscfg-configfs.c | 148 +++++++++++++++++-
.../coresight/coresight-syscfg-configfs.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 36 +++++
.../hwtracing/coresight/coresight-syscfg.h | 1 +
5 files changed, 193 insertions(+), 7 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-config-file.h b/drivers/hwtracing/coresight/coresight-config-file.h
index 6c8c5af0a614..03899f7d94c9 100644
--- a/drivers/hwtracing/coresight/coresight-config-file.h
+++ b/drivers/hwtracing/coresight/coresight-config-file.h
@@ -115,4 +115,11 @@ struct cscfg_file_elem_str {
char *str;
};
+/* kernel configfs needs to read the incoming file buffers to load. */
+int cscfg_file_read_buffer(const u8 *buffer, const int buflen,
+ struct cscfg_fs_load_descs *desc_arrays);
+/* to unload we just need the first name - config or first feature */
+int cscfg_file_read_buffer_first_name(const u8 *buffer, const int buflen,
+ const char **name);
+
#endif /* _CORESIGHT_CORESIGHT_CONFIG_FILE_H */
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
index c388a77a2683..21a67aae4ea9 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -7,6 +7,7 @@
#include <linux/configfs.h>
#include "coresight-config.h"
+#include "coresight-config-file.h"
#include "coresight-syscfg-configfs.h"
/* create a default ci_type. */
@@ -380,14 +381,147 @@ static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc
return &feat_view->group;
}
+/* Attributes in configfs that allow load and unload of configuration binary files */
+
+/* load "buffer" as a configuration binary file */
+static ssize_t cscfg_cfg_load_write(struct config_item *item, const void *buffer, size_t size)
+{
+ struct cscfg_fs_configs_grp *configs_grp;
+ struct cscfg_fs_load_descs *load_descs = 0;
+ struct cscfg_load_owner_info *owner_info = 0;
+ int err = 0;
+ const char *name;
+
+ configs_grp = container_of(to_config_group(item), struct cscfg_fs_configs_grp, group);
+ if (size > CSCFG_FILE_MAXSIZE) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Load error: Input file too large.\n");
+ return -EINVAL;
+ }
+
+ load_descs = kzalloc(sizeof(struct cscfg_fs_load_descs), GFP_KERNEL);
+ owner_info = kzalloc(sizeof(struct cscfg_load_owner_info), GFP_KERNEL);
+ if (!load_descs || !owner_info) {
+ err = -ENOMEM;
+ goto exit_memfree;
+ }
+
+ load_descs->owner_info = owner_info;
+ owner_info->owner_handle = load_descs;
+ owner_info->type = CSCFG_OWNER_CONFIGFS;
+
+ err = cscfg_file_read_buffer(buffer, size, load_descs);
+ if (err) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Load error: Failed to read input file.\n");
+ goto exit_memfree;
+ }
+
+ err = cscfg_load_config_sets(load_descs->config_descs, load_descs->feat_descs, owner_info);
+ if (err) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Load error: Failed to load configuaration file.\n");
+ goto exit_memfree;
+ }
+
+ /* name of config if there is one, otherwise first feature */
+ if (load_descs->config_descs[0])
+ name = load_descs->config_descs[0]->name;
+ else
+ name = load_descs->feat_descs[0]->name;
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "OK: configuration file loaded (%s).\n", name);
+
+ return size;
+
+exit_memfree:
+ kfree(load_descs);
+ kfree(owner_info);
+ return err;
+}
+CONFIGFS_BIN_ATTR_WO(cscfg_cfg_, load, NULL, CSCFG_FILE_MAXSIZE);
+
+/* read "buffer" and unload configuration */
+static ssize_t cscfg_cfg_unload_write(struct config_item *item, const void *buffer, size_t size)
+{
+ struct cscfg_fs_configs_grp *configs_grp;
+ struct cscfg_fs_load_descs *load_descs;
+ const char *name;
+ int err;
+
+ configs_grp = container_of(to_config_group(item), struct cscfg_fs_configs_grp, group);
+ if (size > CSCFG_FILE_MAXSIZE) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Unload error: Input file too large\n");
+ return -EINVAL;
+ }
+
+ err = cscfg_file_read_buffer_first_name(buffer, size, &name);
+ if (err) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Unload error: Failed to read input file\n");
+ return err;
+ }
+
+ load_descs = cscfg_find_fs_owned_cfg_by_name(name);
+ if (!load_descs) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Unload error: Failed to find configuration %s from input file\n",
+ name);
+ return err;
+ }
+ err = cscfg_unload_config_sets(load_descs->owner_info);
+ if (err) {
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "Unload error: Cannot unload configuration %s\n",
+ name);
+ return err;
+ }
+
+ scnprintf(configs_grp->status, CSCFG_FS_STATUS_STRLEN,
+ "OK: configuration file unloaded (%s).\n", name);
+
+ kfree((struct cscfg_load_owner_info *)load_descs->owner_info);
+ kfree(load_descs);
+ return size;
+}
+CONFIGFS_BIN_ATTR_WO(cscfg_cfg_, unload, NULL, CSCFG_FILE_MAXSIZE);
+
+/* show the status of the last load / unload operation */
+static ssize_t cscfg_cfg_last_load_status_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_configs_grp *configs_grp;
+
+ configs_grp = container_of(to_config_group(item), struct cscfg_fs_configs_grp, group);
+
+ return scnprintf(page, PAGE_SIZE, "%s\n", configs_grp->status);
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, last_load_status);
+
+static struct configfs_attribute *cscfg_config_configs_attrs[] = {
+ &cscfg_cfg_attr_last_load_status,
+ NULL,
+};
+
+static struct configfs_bin_attribute *cscfg_config_configfs_bin_attrs[] = {
+ &cscfg_cfg_attr_load,
+ &cscfg_cfg_attr_unload,
+ NULL,
+};
+
static struct config_item_type cscfg_configs_type = {
.ct_owner = THIS_MODULE,
+ .ct_bin_attrs = cscfg_config_configfs_bin_attrs,
+ .ct_attrs = cscfg_config_configs_attrs,
};
-static struct config_group cscfg_configs_grp = {
- .cg_item = {
- .ci_namebuf = "configurations",
- .ci_type = &cscfg_configs_type,
+/* group for configurations dir, with load, unload and status attribs */
+static struct cscfg_fs_configs_grp cscfg_configs_grp = {
+ .group = {
+ .cg_item = {
+ .ci_namebuf = "configurations",
+ .ci_type = &cscfg_configs_type,
+ },
},
};
@@ -400,7 +534,7 @@ int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc)
new_group = cscfg_create_config_group(config_desc);
if (IS_ERR(new_group))
return PTR_ERR(new_group);
- err = configfs_register_group(&cscfg_configs_grp, new_group);
+ err = configfs_register_group(&cscfg_configs_grp.group, new_group);
if (!err)
config_desc->fs_group = new_group;
return err;
@@ -468,8 +602,8 @@ int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr)
mutex_init(&subsys->su_mutex);
/* Add default groups to subsystem */
- config_group_init(&cscfg_configs_grp);
- configfs_add_default_group(&cscfg_configs_grp, &subsys->su_group);
+ config_group_init(&cscfg_configs_grp.group);
+ configfs_add_default_group(&cscfg_configs_grp.group, &subsys->su_group);
config_group_init(&cscfg_features_grp);
configfs_add_default_group(&cscfg_features_grp, &subsys->su_group);
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
index 373d84d43268..8d6900e8c1ea 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
@@ -11,6 +11,14 @@
#define CSCFG_FS_SUBSYS_NAME "cs-syscfg"
+#define CSCFG_FS_STATUS_STRLEN 256
+
+/* container for configs group */
+struct cscfg_fs_configs_grp {
+ struct config_group group;
+ char status[CSCFG_FS_STATUS_STRLEN];
+};
+
/* container for configuration view */
struct cscfg_fs_config {
struct cscfg_config_desc *config_desc;
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 759c32889efd..ceab30eac9b9 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -586,6 +586,42 @@ int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info)
}
EXPORT_SYMBOL_GPL(cscfg_unload_config_sets);
+/* find a configuration owned by configfs by name of config / first feature */
+struct cscfg_fs_load_descs *cscfg_find_fs_owned_cfg_by_name(const char *name)
+{
+ struct cscfg_load_owner_info *owner_info;
+ struct cscfg_fs_load_descs *fs_load_cfg = NULL;
+ struct cscfg_config_desc *config_desc;
+ struct cscfg_feature_desc *feat_desc;
+
+ mutex_lock(&cscfg_mutex);
+
+ /* search the load_owner list for CONFIGFS loaded types */
+ list_for_each_entry(owner_info, &cscfg_mgr->load_order_list, item) {
+ /* if this is a config fs owned item, then try to match */
+ if (owner_info->type == CSCFG_OWNER_CONFIGFS) {
+ fs_load_cfg = owner_info->owner_handle;
+ /* first try to match the name against the config if it exists */
+ if (fs_load_cfg->config_descs[0]) {
+ config_desc = fs_load_cfg->config_descs[0];
+ if (!strcmp(config_desc->name, name))
+ goto exit_unlock;
+ /* no config - match against first feature name */
+ } else {
+ feat_desc = fs_load_cfg->feat_descs[0];
+ if (!strcmp(feat_desc->name, name))
+ goto exit_unlock;
+ }
+ /* no match - move on */
+ fs_load_cfg = NULL;
+ }
+ }
+
+exit_unlock:
+ mutex_unlock(&cscfg_mutex);
+ return fs_load_cfg;
+}
+
/* Handle coresight device registration and add configs and features to devices */
/* iterate through config lists and load matching configs to device */
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
index 6a6e33585be9..6bc29abe0650 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.h
+++ b/drivers/hwtracing/coresight/coresight-syscfg.h
@@ -95,6 +95,7 @@ int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
int param_idx, u64 value);
int cscfg_config_sysfs_activate(struct cscfg_config_desc *cfg_desc, bool activate);
void cscfg_config_sysfs_set_preset(int preset);
+struct cscfg_fs_load_descs *cscfg_find_fs_owned_cfg_by_name(const char *name);
/* syscfg manager external API */
int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] coresight: configfs: Modify config files to allow userspace use
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
2021-11-01 22:47 ` [PATCH 1/6] coresight: configfs: Add in functionality for load via configfs Mike Leach
2021-11-01 22:47 ` [PATCH 2/6] coresight: configfs: Add in binary attributes to load files Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
2021-11-01 22:47 ` [PATCH 4/6] coresight: samples: Add an example config writer for configfs load Mike Leach
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
Update coresight-config.h and the coresight-config-file.c & .h
to allow use in userspace programs.
Use __KERNEL__ defines to filter out driver only structures and
elements so that user space programs can use the descriptor structures.
Abstract memory allocation in coresight-config-file.c to allow read
file functions to be run in userspace and kernel drivers.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
.../coresight/coresight-config-file.c | 96 +++++++++++++------
.../coresight/coresight-config-file.h | 33 +++++++
.../hwtracing/coresight/coresight-config.h | 21 ++++
3 files changed, 122 insertions(+), 28 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-config-file.c b/drivers/hwtracing/coresight/coresight-config-file.c
index 3fd001938324..77a64b54280d 100644
--- a/drivers/hwtracing/coresight/coresight-config-file.c
+++ b/drivers/hwtracing/coresight/coresight-config-file.c
@@ -4,10 +4,58 @@
* Author: Mike Leach <mike.leach@linaro.org>
*/
-#include "coresight-config.h"
#include "coresight-config-file.h"
+
+/*
+ * To allow reuse of this source in tools, define memory allocation fns according
+ * to build environment.
+ */
+
+#ifdef __KERNEL__
#include "coresight-syscfg.h"
+static void *cscfg_calloc(size_t num, size_t size)
+{
+ return devm_kcalloc(cscfg_device(), num, size, GFP_KERNEL);
+}
+
+static char *cscfg_strdup(const char *str)
+{
+ return devm_kstrdup(cscfg_device(), str, GFP_KERNEL);
+}
+
+static void *cscfg_zalloc(size_t size)
+{
+ return devm_kzalloc(cscfg_device(), size, GFP_KERNEL);
+}
+
+#else
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void *cscfg_calloc(size_t num, size_t size)
+{
+ return calloc(num, size);
+}
+
+static char *cscfg_strdup(const char *str)
+{
+ return strdup(str);
+}
+
+static void *cscfg_zalloc(size_t size)
+{
+ void *ptr = malloc(size);
+
+ if (ptr)
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+#endif
+
#define cscfg_extract_u64(val64) { \
val64 = *(u64 *)(buffer + used); \
used += sizeof(u64); \
@@ -80,6 +128,7 @@ static int cscfg_file_read_elem_str(const u8 *buffer, const int buflen, int *buf
struct cscfg_file_elem_str *elem_str)
{
int used = *buf_used;
+ const u8 *str;
if ((buflen - used) < sizeof(u16))
return -EINVAL;
@@ -89,11 +138,13 @@ static int cscfg_file_read_elem_str(const u8 *buffer, const int buflen, int *buf
if ((buflen - used) < elem_str->str_len)
return -EINVAL;
+ str = buffer + used;
+
/* check for 0 termination */
- if (buffer[elem_str->str_len - 1] != 0)
+ if (str[elem_str->str_len - 1] != 0)
return -EINVAL;
- elem_str->str = devm_kstrdup(cscfg_device(), (char *)buffer, GFP_KERNEL);
+ elem_str->str = cscfg_strdup((char *)str);
used += elem_str->str_len;
*buf_used = used;
@@ -104,14 +155,12 @@ static int cscfg_file_alloc_desc_arrays(struct cscfg_fs_load_descs *desc_arrays,
int nr_features)
{
/* arrays are 0 terminated - max of 1 config & nr_features features */
- desc_arrays->config_descs = devm_kcalloc(cscfg_device(), 2,
- sizeof(struct cscfg_config_desc *),
- GFP_KERNEL);
+ desc_arrays->config_descs = cscfg_calloc(2, sizeof(struct cscfg_config_desc *));
if (!desc_arrays->config_descs)
return -ENOMEM;
- desc_arrays->feat_descs = devm_kcalloc(cscfg_device(), nr_features + 1,
- sizeof(struct cscfg_feature_desc *),
- GFP_KERNEL);
+
+ desc_arrays->feat_descs = cscfg_calloc(nr_features + 1,
+ sizeof(struct cscfg_feature_desc *));
if (!desc_arrays->feat_descs)
return -ENOMEM;
return 0;
@@ -138,8 +187,7 @@ static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *
return 0;
/* we have a config - allocate the descriptor */
- config_desc = devm_kzalloc(cscfg_device(), sizeof(struct cscfg_config_desc),
- GFP_KERNEL);
+ config_desc = cscfg_zalloc(sizeof(struct cscfg_config_desc));
if (!config_desc)
return -ENOMEM;
@@ -165,8 +213,7 @@ static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *
/* read the array of 64bit presets if present */
nr_preset_vals = config_desc->nr_total_params * config_desc->nr_presets;
if (nr_preset_vals) {
- presets = devm_kcalloc(cscfg_device(), nr_preset_vals,
- sizeof(u64), GFP_KERNEL);
+ presets = cscfg_calloc(nr_preset_vals, sizeof(u64));
if (!presets)
return -ENOMEM;
@@ -181,10 +228,8 @@ static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *
/* read the array of feature names referenced by the config */
if (config_desc->nr_feat_refs) {
- config_desc->feat_ref_names = devm_kcalloc(cscfg_device(),
- config_desc->nr_feat_refs,
- sizeof(char *),
- GFP_KERNEL);
+ config_desc->feat_ref_names = cscfg_calloc(config_desc->nr_feat_refs,
+ sizeof(char *));
if (!config_desc->feat_ref_names)
return -ENOMEM;
@@ -262,8 +307,7 @@ static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int
u32 val32;
/* allocate the feature descriptor object */
- feat_desc = devm_kzalloc(cscfg_device(), sizeof(struct cscfg_feature_desc),
- GFP_KERNEL);
+ feat_desc = cscfg_zalloc(sizeof(struct cscfg_feature_desc));
if (!feat_desc)
return -ENOMEM;
@@ -302,10 +346,8 @@ static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int
nr_regs_bytes = ((sizeof(u32) + sizeof(u64)) * feat_desc->nr_regs);
if ((buflen - used) < nr_regs_bytes)
return -EINVAL;
- feat_desc->regs_desc = devm_kcalloc(cscfg_device(),
- feat_desc->nr_regs,
- sizeof(struct cscfg_regval_desc),
- GFP_KERNEL);
+ feat_desc->regs_desc = cscfg_calloc(feat_desc->nr_regs,
+ sizeof(struct cscfg_regval_desc));
if (!feat_desc->regs_desc)
return -ENOMEM;
@@ -319,10 +361,8 @@ static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int
/* parameter descriptors - string + 64 bit value */
if (feat_desc->nr_params) {
- feat_desc->params_desc = devm_kcalloc(cscfg_device(),
- feat_desc->nr_params,
- sizeof(struct cscfg_parameter_desc),
- GFP_KERNEL);
+ feat_desc->params_desc = cscfg_calloc(feat_desc->nr_params,
+ sizeof(struct cscfg_parameter_desc));
if (!feat_desc->params_desc)
return -ENOMEM;
for (i = 0; i < feat_desc->nr_params; i++) {
@@ -399,7 +439,7 @@ int cscfg_file_read_buffer(const u8 *buffer, const int buflen,
if (err)
return err;
}
- return used;
+ return 0;
}
int cscfg_file_read_buffer_first_name(const u8 *buffer, const int buflen,
diff --git a/drivers/hwtracing/coresight/coresight-config-file.h b/drivers/hwtracing/coresight/coresight-config-file.h
index 03899f7d94c9..04c365e5109b 100644
--- a/drivers/hwtracing/coresight/coresight-config-file.h
+++ b/drivers/hwtracing/coresight/coresight-config-file.h
@@ -7,6 +7,39 @@
#ifndef _CORESIGHT_CORESIGHT_CONFIG_FILE_H
#define _CORESIGHT_CORESIGHT_CONFIG_FILE_H
+#include <linux/types.h>
+
+#ifndef __KERNEL__
+/*
+ * allow the user space programs to include the coresight config headers
+ * to use the _desc structures, and reuse the read code
+ */
+#ifndef u8
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+#endif
+
+/* ARRAY SIZE is useful too */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+/* define EINVAL for user space */
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+
+#endif
+
+#include "coresight-config.h"
+
+
/*
* Structures to represent configuration descriptors in a memory buffer
* to serialise to and from files
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 770986316bc2..2136393df710 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -7,7 +7,14 @@
#ifndef _CORESIGHT_CORESIGHT_CONFIG_H
#define _CORESIGHT_CORESIGHT_CONFIG_H
+/*
+ * Filter out kernel only portions of the file to allow user space programs
+ * to use the descriptor definitions.
+ */
+#ifdef __KERNEL__
#include <linux/coresight.h>
+#endif
+
#include <linux/types.h>
/* CoreSight Configuration Management - component and system wide configuration */
@@ -103,14 +110,18 @@ struct cscfg_regval_desc {
struct cscfg_feature_desc {
const char *name;
const char *description;
+#ifdef __KERNEL__
struct list_head item;
+#endif
u32 match_flags;
int nr_params;
struct cscfg_parameter_desc *params_desc;
int nr_regs;
struct cscfg_regval_desc *regs_desc;
+#ifdef __KERNEL__
void *load_owner;
struct config_group *fs_group;
+#endif
};
/**
@@ -138,16 +149,20 @@ struct cscfg_feature_desc {
struct cscfg_config_desc {
const char *name;
const char *description;
+#ifdef __KERNEL__
struct list_head item;
+#endif
int nr_feat_refs;
const char **feat_ref_names;
int nr_presets;
int nr_total_params;
const u64 *presets; /* nr_presets * nr_total_params */
+#ifdef __KERNEL__
struct dev_ext_attribute *event_ea;
atomic_t active_cnt;
void *load_owner;
struct config_group *fs_group;
+#endif
};
/**
@@ -162,11 +177,16 @@ struct cscfg_config_desc {
* @feat_descs: array of feature descriptor pointers.
*/
struct cscfg_fs_load_descs {
+#ifdef __KERNEL__
void *owner_info;
+#endif
struct cscfg_config_desc **config_descs;
struct cscfg_feature_desc **feat_descs;
};
+/* remainder of header is used by the kernel drivers only */
+#ifdef __KERNEL__
+
/**
* config register instance - part of a loaded feature.
* maps register values to csdev driver structures
@@ -274,4 +294,5 @@ void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev);
/* reset a feature to default values */
void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev);
+#endif /* __KERNEL__ */
#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] coresight: samples: Add an example config writer for configfs load
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
` (2 preceding siblings ...)
2021-11-01 22:47 ` [PATCH 3/6] coresight: configfs: Modify config files to allow userspace use Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
2021-11-01 22:47 ` [PATCH 5/6] coresight: samples: Add coresight file reader sample program Mike Leach
2021-11-01 22:47 ` [PATCH 6/6] Documentation: coresight: Update coresight configuration docs Mike Leach
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
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.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
samples/coresight/Makefile | 7 +
samples/coresight/coresight-cfg-bufw.c | 302 ++++++++++++++++++++++
samples/coresight/coresight-cfg-bufw.h | 24 ++
samples/coresight/coresight-cfg-filegen.c | 89 +++++++
4 files changed, 422 insertions(+)
create mode 100644 samples/coresight/coresight-cfg-bufw.c
create mode 100644 samples/coresight/coresight-cfg-bufw.h
create mode 100644 samples/coresight/coresight-cfg-filegen.c
diff --git a/samples/coresight/Makefile b/samples/coresight/Makefile
index b3fce4af2347..07bfd99d7a68 100644
--- a/samples/coresight/Makefile
+++ b/samples/coresight/Makefile
@@ -1,4 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
+# coresight config - loadable module configuration.
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-cfg-filegen-objs := coresight-cfg-filegen.o coresight-cfg-bufw.o
+userccflags += -I$(srctree)/drivers/hwtracing/coresight
diff --git a/samples/coresight/coresight-cfg-bufw.c b/samples/coresight/coresight-cfg-bufw.c
new file mode 100644
index 000000000000..8c32a8509eef
--- /dev/null
+++ b/samples/coresight/coresight-cfg-bufw.c
@@ -0,0 +1,302 @@
+// 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"
+
+/*
+ * 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/samples/coresight/coresight-cfg-bufw.h b/samples/coresight/coresight-cfg-bufw.h
new file mode 100644
index 000000000000..00b16c583cad
--- /dev/null
+++ b/samples/coresight/coresight-cfg-bufw.h
@@ -0,0 +1,24 @@
+/* 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 "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/samples/coresight/coresight-cfg-filegen.c b/samples/coresight/coresight-cfg-filegen.c
new file mode 100644
index 000000000000..c8be18ee97b6
--- /dev/null
+++ b/samples/coresight/coresight-cfg-filegen.c
@@ -0,0 +1,89 @@
+// 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"
+
+/*
+ * generate example binary coresight configuration files for loading
+ * into the coresight subsystem via configfs
+ */
+
+/* create a similar configuration example as the coresight-cfg-sample.c file. */
+
+/* we will provide 4 sets of preset parameter values */
+#define AFDO2_NR_PRESETS 4
+/* the total number of parameters in used features - strobing has 2 */
+#define AFDO2_NR_PARAM_SUM 2
+
+static const char *afdo2_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 afdo2_presets[AFDO2_NR_PRESETS][AFDO2_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(afdo2_ref_names),
+ .feat_ref_names = afdo2_ref_names,
+ .nr_presets = AFDO2_NR_PRESETS,
+ .nr_total_params = AFDO2_NR_PARAM_SUM,
+ .presets = &afdo2_presets[0][0],
+};
+
+static struct cscfg_feature_desc *sample_feats[] = {
+ NULL
+};
+
+static struct cscfg_config_desc *sample_cfgs[] = {
+ &afdo3,
+ NULL
+};
+
+
+#define CSCFG_BIN_FILENAME "example1.cscfg"
+
+int main(int argc, char **argv)
+{
+ u8 buffer[CSCFG_FILE_MAXSIZE];
+ int used;
+ FILE *fp;
+
+ printf("Coresight Configuration file Generator\n\n");
+
+ used = cscfg_file_write_buffer(buffer, CSCFG_FILE_MAXSIZE,
+ sample_cfgs[0], sample_feats);
+
+ if (used < 0) {
+ printf("Error %d writing configuration %s into buffer\n",
+ used, sample_cfgs[0]->name);
+ return used;
+ }
+
+ fp = fopen(CSCFG_BIN_FILENAME, "wb");
+ if (fp == NULL) {
+ printf("Error opening file %s\n", CSCFG_BIN_FILENAME);
+ return -1;
+ }
+ fwrite(buffer, used, sizeof(u8), fp);
+ fclose(fp);
+ return 0;
+}
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] coresight: samples: Add coresight file reader sample program
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
` (3 preceding siblings ...)
2021-11-01 22:47 ` [PATCH 4/6] coresight: samples: Add an example config writer for configfs load Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
2021-11-01 22:47 ` [PATCH 6/6] Documentation: coresight: Update coresight configuration docs Mike Leach
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
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 | 39 ++++
samples/coresight/coresight-cfg-file-read.c | 191 ++++++++++++++++++++
3 files changed, 248 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..068cc2ca6ece
--- /dev/null
+++ b/samples/coresight/Makefile.host
@@ -0,0 +1,39 @@
+# 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)/../../.))
+
+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
+
+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;
+}
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] Documentation: coresight: Update coresight configuration docs
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
` (4 preceding siblings ...)
2021-11-01 22:47 ` [PATCH 5/6] coresight: samples: Add coresight file reader sample program Mike Leach
@ 2021-11-01 22:47 ` Mike Leach
5 siblings, 0 replies; 7+ messages in thread
From: Mike Leach @ 2021-11-01 22:47 UTC (permalink / raw)
To: coresight
Cc: linux-arm-kernel, mathieu.poirier, suzuki.poulose, leo.yan,
Mike Leach
Add documentation covering the configfs updates that allow
binary configuration files to be loaded and unloaded, along
with the demonstration programs in samples.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
.../trace/coresight/coresight-config.rst | 65 +++++++++++++++++--
1 file changed, 59 insertions(+), 6 deletions(-)
diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst
index 911db4da7f99..8ea640b3f6f9 100644
--- a/Documentation/trace/coresight/coresight-config.rst
+++ b/Documentation/trace/coresight/coresight-config.rst
@@ -152,7 +152,7 @@ follows::
$ cd configurations/
$ ls
- autofdo
+ autofdo last_load_status load unload
$ cd autofdo/
$ ls
description preset1 preset3 preset5 preset7 preset9
@@ -247,9 +247,19 @@ Creating and Loading Custom Configurations
==========================================
Custom configurations and / or features can be dynamically loaded into the
-system by using a loadable module.
+system by using a loadable module, or by loading a binary configuration
+file in configfs.
+
+Loaded configurations can use previously loaded features. The system will
+ensure that it is not possible to unload a feature that is currently in
+use, by enforcing the unload order as the strict reverse of the load order.
+
+An example of a custom configuration module, and generators for binary
+configuration files are found in './samples/coresight'.
+
-An example of a custom configuration is found in ./samples/coresight.
+Using a Loadable Module
+-----------------------
This creates a new configuration that uses the existing built in
strobing feature, but provides a different set of presets.
@@ -258,6 +268,49 @@ When the module is loaded, then the configuration appears in the configfs
file system and is selectable in the same way as the built in configuration
described above.
-Configurations can use previously loaded features. The system will ensure
-that it is not possible to unload a feature that is currently in use, by
-enforcing the unload order as the strict reverse of the load order.
+The file 'coresight-cfg-sample.c' contains the configuration and module
+initialisation code needed to create the loadable module.
+
+This will be built alongside the kernel modules if select in KConfig.
+
+
+Using a Binary Configuration File
+---------------------------------
+
+Building the samples creates the 'coresight-cfg-filegen' program that will
+generate a configuration binary 'example1.cscfg' that can be loaded into the
+system using configfs. The configuration declared in the source file
+'coresight-cfg-filegen.c' is named 'autofdo3' - the name that will be used
+once loaded.
+
+The source files 'coresight-cfg-bufw.h' and 'coresight-cfg-bufw.c' provide a
+standard function to convert a configuration declared in 'C' into the correct
+binary buffer format. These files can be re-used to create new custom
+configurations.
+
+The program 'coresight-cfg-file-read' can read back and print a configuration
+binary. This is built using the reader from the driver code.
+
+There are additional attributes in the configurations directory - load, unload
+and last_load_status that can be used to load and unload configuration
+binary files. To load, 'cat' the binary config into the load attribute::
+
+ $ ls /config/cs-syscfg/configurations/
+ autofdo last_load_status load unload
+ $ cat example1.cscfg > /config/cs-syscfg/configurations/load
+ $ ls /config/cs-syscfg/configurations/
+ autofdo autofdo3 last_load_status load unload
+ $ cat /config/cs-syscfg/configurations/last_load_status
+ OK: configuration file loaded (autofdo3).
+
+To unload, use the same file in the unload attribute::
+
+ $ cat example1.cscfg > /config/cs-syscfg/configurations/unload
+ $ cat /config/cs-syscfg/configurations/last_load_status
+ OK: configuration file unloaded (autofdo3).
+ ls /config/cs-syscfg/configurations/
+ autofdo last_load_status load unload
+
+The generator and reader programs can also be built directly, separately from
+the kernel build by using the 'Makefile.host' file. This allows binaries to be
+created on the host machine when cross compiling.
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-11-01 22:50 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-01 22:47 [PATCH 0/6] coresight: syscfg: Extend configfs for config load Mike Leach
2021-11-01 22:47 ` [PATCH 1/6] coresight: configfs: Add in functionality for load via configfs Mike Leach
2021-11-01 22:47 ` [PATCH 2/6] coresight: configfs: Add in binary attributes to load files Mike Leach
2021-11-01 22:47 ` [PATCH 3/6] coresight: configfs: Modify config files to allow userspace use Mike Leach
2021-11-01 22:47 ` [PATCH 4/6] coresight: samples: Add an example config writer for configfs load Mike Leach
2021-11-01 22:47 ` [PATCH 5/6] coresight: samples: Add coresight file reader sample program Mike Leach
2021-11-01 22:47 ` [PATCH 6/6] Documentation: coresight: Update coresight configuration docs Mike Leach
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).