From patchwork Mon Nov 1 22:47:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12597517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0584C433EF for ; Mon, 1 Nov 2021 22:50:20 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8C10160F0F for ; Mon, 1 Nov 2021 22:50:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8C10160F0F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=na+rsbqUFRydmF/QVrOLa2iVQCQo8DoGE3x17z1VkYw=; b=VQLALkd/dUDDu1 2kRym0teXzGOqFaU++LaVat0H7r1OCjWog0EGIUK8NCKq9Z+f7d+LhISxHy87GRg0gxQnjn4oOYep DiLB5UMlCo2mGS6MdzxxsgNJ9V47aKlKqZy0P9MKBfs6ytOrUY7Vrg2crBwKyqYQ9CdHQrEXMvKdp 1Az/wGLNDZEtlD7jbzKZOD/gxb9akvQbqHBMGwMuIpJk8Iqkmc6GBoEbbZUTeNi4E0Gtit+5Zjs0G Iol/zYXxoh4uCC1depbVNSo2yZLU+GrJmMR8Zk6cWFSIbb08K9rs5QbNPkfGmsL4mAHNZTr7ug0+u R4XG5JrMQKCRKsvETtyw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mhg6b-00HRp0-7S; Mon, 01 Nov 2021 22:48:41 +0000 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mhg5Z-00HRWa-W5 for linux-arm-kernel@lists.infradead.org; Mon, 01 Nov 2021 22:47:41 +0000 Received: by mail-wm1-x331.google.com with SMTP id o4-20020a1c7504000000b0032cab7473caso604036wmc.1 for ; Mon, 01 Nov 2021 15:47:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Ky2DtWLrDHXeN3dfZEi54AGY8N6qWbQzEs2U9otpzmo=; b=SLAfoAZgZdLfT/Ok3mLdDCPAL9uUlIoa8zat/nGejcvBeAeutyt/oylM9vvrN3TE3c UjvhAcA0C4YWPzHn1M3NsLaLB37JV7j2pZs7Zs5O0ry8/acD9k5QHUpddLCedeETB/1U pHCtkDHrLMjt6HEAp4F4AXdKEjDlHilAVfDCUIqcdZofmZ8TxyWAaYEeGWgYSsWEwrFK /ww79aHpC1kv3iH9VV2Q0ykdRg1nc0/yP0Whjczw7dVdq0GkUu2wXL0UNfeK34Tqfueg GwSDMVGUiBqQQflsjWyDBUjoCnkh3wwNHpraVDevW58kEFdO/HR+j48mEyOXjFbHyaiD OKNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Ky2DtWLrDHXeN3dfZEi54AGY8N6qWbQzEs2U9otpzmo=; b=LhpiWP8CL/72oi2L2rUHET09HfEDhVQp7gMKsw1bhjmG45qbrsBHA6wekqFfxuAoYB DaYBs4n1ieT4PviXThcHlwZniMz6hsLXkvVDhUdNgxTym+mnVQx6yKof2CVaBEr395Ym CKeq59uTItY8edzZZWOpgPL+Iz+oq1KD4uILc/L5PDp5RxK861NiBHKDqolxM4861eyd XrWR8kWhqSNYy4p0AZEQWfza92JBAuv5oNj64nnIMhvK4Q4yCzYOj4i65VpqsLfIIMHP 1IjhKSNFaVGAgHIwB1+P3ZFuX6+MDdCrEELLXHU8uZ0NlmCoSkHBAf65MhAdr7K4AjNS yuDQ== X-Gm-Message-State: AOAM533Rq3Umt/mGP8KPaQQiqzI52T2uuB9GhmAReP1QQOIVPdZ/RqMQ 2j8u1rkirc5DAJD4VYVFUujl5A== X-Google-Smtp-Source: ABdhPJwb8FWIcbWRDxAH5Y/nVSx0eEFBMqCfqcnLXkTTbC4sZHKV59bKm//X97+XKt84SvAt4JVoMQ== X-Received: by 2002:a7b:c344:: with SMTP id l4mr2260228wmj.64.1635806856258; Mon, 01 Nov 2021 15:47:36 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:cd6d:75aa:3402:e4a]) by smtp.gmail.com with ESMTPSA id 10sm858647wme.27.2021.11.01.15.47.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Nov 2021 15:47:35 -0700 (PDT) From: Mike Leach To: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, Mike Leach Subject: [PATCH 4/6] coresight: samples: Add an example config writer for configfs load Date: Mon, 1 Nov 2021 22:47:29 +0000 Message-Id: <20211101224731.27870-5-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211101224731.27870-1-mike.leach@linaro.org> References: <20211101224731.27870-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211101_154738_079730_DA882E83 X-CRM114-Status: GOOD ( 32.07 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- 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 + */ + +#include + +#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 + */ + +#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 + */ + +#include +#include +#include +#include + +#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; +}