From patchwork Mon Jul 4 15:42:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905530 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 5B797C433EF for ; Mon, 4 Jul 2022 15:44:22 +0000 (UTC) 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=rZpj1nruNSdzVLU01P8E5Jb5nB95as/iiCwziRObtPc=; b=fDF1bPO/xyPGAP 9xHoVUsEbrbw+T3nEZmiwumJ9mmqObvm42V30uKKvfkzbquP/+inu377NVcJIAcCM32sTWXdoMFnd F2+fr6Lyo2UPKtFLuZfEB+vP4PIIWsMmAOYI33I29QSVUmK6d1AZ4qcQuemPUbzdraInc8rWKsj9t MhYlvGYtlYLbBfAxZodsPLFXmoa+lnmTf7VW3jKiFzYF2c2+ShvFlD2lym/panqcpSXx4wCk9pDo3 IdcNQwu0UNmkwgN8vgWsOhN/dI4DbMEVpM61hqL/dWnw1vLu11iFZJunHniBFX66CXCegXQO5Mojb zt704oQOCqLtaMeMsS9Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OEI-009lsK-7e; Mon, 04 Jul 2022 15:43:18 +0000 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8ODw-009liW-AY for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:42:58 +0000 Received: by mail-wr1-x434.google.com with SMTP id cl1so14041237wrb.4 for ; Mon, 04 Jul 2022 08:42:53 -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=kVN6AgfRQ9JB5xb8lTlVzU3nqEsQK95Vgz2t3dnIbI4=; b=ckrJIPJAwHonM+IdF9BVRdc90bYnnfjbzbzju65B1KKFYa86FIKxjcOMzgLDhZrgfn lQCOT7a/eRpKZNQLSZdgZFLd2CKqoyKnal9I6wA4s0Q5lo/YFLjl9FRRgyiWblFu7u0l olP3hDmCQyOej4mYLBf3JXxSmwAIe8g7uBUj2WEYUoJShN3eWmr7krp36q8tl+6+6l1k h10yiVsRyi5B5TY5beZk7k/Yak3ce0h+1b3WLb2+793FbxdPEBxF0sjGHt/1u5rgO0fX jY41sbXkT/H3wflu4/f/jlsSa/yGFvAy6WX6CxHv1wezjNp2HyHTSEXSWNVaNVerpO81 kk5g== 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=kVN6AgfRQ9JB5xb8lTlVzU3nqEsQK95Vgz2t3dnIbI4=; b=a4N3qYqJDNj/1syR+8/Ecf24/ULoVlrNf59nYvmQbr42kSIgdlag5L4uI13EcAE+nC b3UUsqoeE6ZJJebMxatCu/KQ8aMiL5qgv+zEdreT3QKLxUvxKFoQ4sx9BMxGyRiMIO06 POEvciorQInQQLEIL9whc9SvbG43lpd4Em4auQSAFWiDGsZv+K+Wgyi07RF7jDw/71wk kfIkJHSHJhUYpeL2AZl3sH2NHWa4TJkd2iui/LILnl6jRcLuO+YiD7INKLBye+p9oRc9 6+ZTuIQs0QXVxAdZbgSwd5kjyAxZWwIlp569ug8oypzVawTM555f1L7cW9MRfCUkWpT4 R2eA== X-Gm-Message-State: AJIora9GUb2krVvbW6HEHcXbc+PQhCN2yQXxahg2f+IVI1JZhkF3G4zY T9Lzyp9rlpjliFNWNTm/2WKfJ1TpmgLDlQ== X-Google-Smtp-Source: AGRyM1uKhJamkuobuces0fTri6XuS3VttQB16ma2+ZCWseG8v2023ndZovt8Tx3S96NngTmG1hNtpg== X-Received: by 2002:a5d:6d46:0:b0:21b:933d:7950 with SMTP id k6-20020a5d6d46000000b0021b933d7950mr27576848wri.679.1656949372566; Mon, 04 Jul 2022 08:42:52 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:52 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach Subject: [PATCH v4 1/7] coresight: configfs: Update memory allocation / free for configfs elements Date: Mon, 4 Jul 2022 16:42:43 +0100 Message-Id: <20220704154249.11501-2-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084256_459795_69A31266 X-CRM114-Status: GOOD ( 24.62 ) 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 Previously, the objects backing the configfs directories and files were created using devm managed memory on the coresight device. Now we are adding configfs load/unload, configurations can be loaded many times over the lifetime of the device, so it is more appropriate to use normally allocated and freed memory. Signed-off-by: Mike Leach --- .../coresight/coresight-syscfg-configfs.c | 119 +++++++++++++----- 1 file changed, 88 insertions(+), 31 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c index 433ede94dd63..6e8c8db52d39 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c @@ -14,7 +14,7 @@ static inline struct config_item_type *cscfg_create_ci_type(void) { struct config_item_type *ci_type; - ci_type = devm_kzalloc(cscfg_device(), sizeof(*ci_type), GFP_KERNEL); + ci_type = kzalloc(sizeof(*ci_type), GFP_KERNEL); if (ci_type) ci_type->ct_owner = THIS_MODULE; @@ -175,6 +175,19 @@ static struct config_item_type cscfg_config_preset_type = { .ct_attrs = cscfg_config_preset_attrs, }; + +/* walk list of presets and free the previously allocated memory */ +static void cscfg_destroy_preset_groups(struct config_group *cfg_view_group) +{ + struct cscfg_fs_preset *cfg_fs_preset; + struct config_group *p_group; + + list_for_each_entry(p_group, &cfg_view_group->default_groups, default_groups) { + cfg_fs_preset = container_of(p_group, struct cscfg_fs_preset, group); + kfree(cfg_fs_preset); + } +} + static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view) { int preset_num; @@ -186,11 +199,12 @@ static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view) return 0; for (preset_num = 1; preset_num <= config_desc->nr_presets; preset_num++) { - cfg_fs_preset = devm_kzalloc(cscfg_device(), - sizeof(struct cscfg_fs_preset), GFP_KERNEL); + cfg_fs_preset = kzalloc(sizeof(struct cscfg_fs_preset), GFP_KERNEL); - if (!cfg_fs_preset) + if (!cfg_fs_preset) { + cscfg_destroy_preset_groups(&cfg_view->group); return -ENOMEM; + } snprintf(name, CONFIGFS_ITEM_NAME_LEN, "preset%d", preset_num); cfg_fs_preset->preset_num = preset_num; @@ -204,14 +218,10 @@ static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view) static struct config_group *cscfg_create_config_group(struct cscfg_config_desc *config_desc) { - struct cscfg_fs_config *cfg_view; - struct device *dev = cscfg_device(); + struct cscfg_fs_config *cfg_view = NULL; int err; - if (!dev) - return ERR_PTR(-EINVAL); - - cfg_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_config), GFP_KERNEL); + cfg_view = kzalloc(sizeof(struct cscfg_fs_config), GFP_KERNEL); if (!cfg_view) return ERR_PTR(-ENOMEM); @@ -220,12 +230,21 @@ static struct config_group *cscfg_create_config_group(struct cscfg_config_desc * /* add in a preset dir for each preset */ err = cscfg_add_preset_groups(cfg_view); - if (err) + if (err) { + kfree(cfg_view); return ERR_PTR(err); - + } return &cfg_view->group; } +static void cscfg_destroy_config_group(struct config_group *group) +{ + struct cscfg_fs_config *cfg_view = container_of(group, struct cscfg_fs_config, group); + + cscfg_destroy_preset_groups(&cfg_view->group); + kfree(cfg_view); +} + /* attributes for features view */ static ssize_t cscfg_feat_description_show(struct config_item *item, char *page) @@ -314,6 +333,17 @@ static struct config_item_type cscfg_param_view_type = { .ct_attrs = cscfg_param_view_attrs, }; +/* walk the list of default groups - which were set as param items and remove */ +static void cscfg_destroy_params_group_items(struct config_group *params_group) +{ + struct cscfg_fs_param *param_item; + struct config_group *p_group; + + list_for_each_entry(p_group, ¶ms_group->default_groups, default_groups) { + param_item = container_of(p_group, struct cscfg_fs_param, group); + kfree(param_item); + } +} /* * configfs has far less functionality provided to add attributes dynamically than sysfs, * and the show and store fns pass the enclosing config_item so the actual attribute cannot @@ -322,15 +352,16 @@ static struct config_item_type cscfg_param_view_type = { static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc, struct config_group *params_group) { - struct device *dev = cscfg_device(); struct cscfg_fs_param *param_item; int i; /* parameter items - as groups with default_value attribute */ for (i = 0; i < feat_desc->nr_params; i++) { - param_item = devm_kzalloc(dev, sizeof(struct cscfg_fs_param), GFP_KERNEL); - if (!param_item) + param_item = kzalloc(sizeof(struct cscfg_fs_param), GFP_KERNEL); + if (!param_item) { + cscfg_destroy_params_group_items(params_group); return -ENOMEM; + } param_item->feat_desc = feat_desc; param_item->param_idx = i; config_group_init_type_name(¶m_item->group, @@ -343,27 +374,22 @@ static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc, static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc *feat_desc) { - struct cscfg_fs_feature *feat_view; - struct config_item_type *params_group_type; + struct cscfg_fs_feature *feat_view = NULL; + struct config_item_type *params_group_type = NULL; struct config_group *params_group = NULL; - struct device *dev = cscfg_device(); - int item_err; - - if (!dev) - return ERR_PTR(-EINVAL); + int err = -ENOMEM; - feat_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL); + feat_view = kzalloc(sizeof(struct cscfg_fs_feature), GFP_KERNEL); if (!feat_view) return ERR_PTR(-ENOMEM); if (feat_desc->nr_params) { - params_group = devm_kzalloc(dev, sizeof(struct config_group), GFP_KERNEL); + params_group = kzalloc(sizeof(struct config_group), GFP_KERNEL); if (!params_group) - return ERR_PTR(-ENOMEM); - + goto exit_err_free_mem; params_group_type = cscfg_create_ci_type(); if (!params_group_type) - return ERR_PTR(-ENOMEM); + goto exit_err_free_mem; } feat_view->feat_desc = feat_desc; @@ -373,11 +399,36 @@ static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc if (params_group) { config_group_init_type_name(params_group, "params", params_group_type); configfs_add_default_group(params_group, &feat_view->group); - item_err = cscfg_create_params_group_items(feat_desc, params_group); - if (item_err) - return ERR_PTR(item_err); + err = cscfg_create_params_group_items(feat_desc, params_group); + if (err) + goto exit_err_free_mem; } return &feat_view->group; + +exit_err_free_mem: + kfree(feat_view); + kfree(params_group_type); + kfree(params_group); + return ERR_PTR(err); +} + +static void cscfg_destroy_feature_group(struct config_group *feat_group) +{ + struct cscfg_fs_feature *feat_view; + struct config_group *params_group = NULL; + + feat_view = container_of(feat_group, struct cscfg_fs_feature, group); + + /* params group is the first item on the default group list */ + if (!list_empty(&feat_group->default_groups)) { + params_group = list_first_entry(&feat_group->default_groups, + struct config_group, default_groups); + cscfg_destroy_params_group_items(params_group); + /* free the item type, then the group */ + kfree(params_group->cg_item.ci_type); + kfree(params_group); + } + kfree(feat_view); } static struct config_item_type cscfg_configs_type = { @@ -403,6 +454,8 @@ int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc) err = configfs_register_group(&cscfg_configs_grp, new_group); if (!err) config_desc->fs_group = new_group; + else + cscfg_destroy_config_group(new_group); return err; } @@ -410,6 +463,7 @@ void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc) { if (config_desc->fs_group) { configfs_unregister_group(config_desc->fs_group); + cscfg_destroy_config_group(config_desc->fs_group); config_desc->fs_group = NULL; } } @@ -434,9 +488,11 @@ int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc) new_group = cscfg_create_feature_group(feat_desc); if (IS_ERR(new_group)) return PTR_ERR(new_group); - err = configfs_register_group(&cscfg_features_grp, new_group); + err = configfs_register_group(&cscfg_features_grp, new_group); if (!err) feat_desc->fs_group = new_group; + else + cscfg_destroy_feature_group(new_group); return err; } @@ -444,6 +500,7 @@ void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc) { if (feat_desc->fs_group) { configfs_unregister_group(feat_desc->fs_group); + cscfg_destroy_feature_group(feat_desc->fs_group); feat_desc->fs_group = NULL; } } From patchwork Mon Jul 4 15:42:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905529 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 798EEC433EF for ; Mon, 4 Jul 2022 15:44:16 +0000 (UTC) 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=ELGPhRFft0y7XNbYbkTJxA39DZRQMARJdwhVeenDSAQ=; b=S209LT92WsiZPY QtlcjLNTBmfBO4Q3mcPv9MSYrFfqduu22WmChh+iDsTD9OnydarQcjkcCTz3w37kd/uDVwGSu29pR oaRo71nHQOLP9So5zU+z63bNHalMs8R29h6xMRCUEQS1Tz+KOckhPifjwGixoZccrciXyvAGnU+d8 a/73Jurbdb37qKgegzeY7UIPr/gKgfltn8TxvtLsxddPx3mct8cmMA2raJcW/ahFosZj07sLADeS6 d+C5AfdwKD89vvq+/7LDjaceNOl9FBxkvetgeLCQI5ZMFGJj+nbTb0cvLMvKHIq0Rds6OZRquMkoO 6ayFuNgjyh7fiK9LU13g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OE8-009lpJ-8M; Mon, 04 Jul 2022 15:43:08 +0000 Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8ODu-009lj1-VJ for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:42:58 +0000 Received: by mail-wm1-x32a.google.com with SMTP id h14-20020a1ccc0e000000b0039eff745c53so5876134wmb.5 for ; Mon, 04 Jul 2022 08:42:54 -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=+/qhlqAn1+lyzdXpSXR4rFVGbOoEQWBDWuMIJIRGZ3A=; b=e9Wp7gRva44v2ejPGQXq0uT0hR/4+K82UL/RFN/o3Ac6YZE4cpyss4xB+Dl+Lq2gzg 5wpfL4b5lN3sV9s0WZTIaIblFAWYyY0BLhwQc/twA+CpF2y1PNaR8dmGzjq9sJjY4C8r YvpqhKZED2AVLoAM6wL25e+NdhxKJ+9vBmHAnL1KTKESIvNbvRWKAZT6zzEu43WkEDWz 8lze71GGIkxxsx0V3K/wqAVUf5zlvqB3ybjs0H9nY3nL2duUXqBWm/RPxUzCzZjsOlHB GJp5U8VoxUqDMtdMf24nQSdRjYryNSfj9iC3IOClOL14g1+l2zOFkV3K7hhUA6LjtSNF fx1w== 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=+/qhlqAn1+lyzdXpSXR4rFVGbOoEQWBDWuMIJIRGZ3A=; b=BTi6sB0UlmcFsNsOh/5XDog6pIllRz7/kxGx4NghibGsUNRI4v91UeiMP0jI73LL+3 MkfEcDZMAwrEYrCe1zE3MFqeU0VnZI816Yh18KPCZEsOkm5orZH71t36YYRrxfsY1lwF GptCSqGD3ZoVwbl2tno4TL0P08NaSeiuDxdtZsoE48nSpzJ8ikArj9g+KOg0DBd359G5 VnfxSgASXQc7AjD62Yi8pKRjCaGeendyT2cAbNNNbR+otd+DlcXuS2Nbp1+aWaq7UAMY cCe8pZQQSzitrzmFR3vgVGH+7IP1aeoG+a4lRUvWGFgmu5J7Wu+NaAcFshPLxGkf7tgC 17vQ== X-Gm-Message-State: AJIora8lZ67Ez8aENxs2JpYyUq1QzjSoyRlZ6aKqdyePQk9pUGzihCab zlt+CLcadsaUQDcILN5CFhc8PeSmEHQEXg== X-Google-Smtp-Source: AGRyM1sYLvw68OWNDVsdoJ99vrbtzMIRKZ58kxDMIAzg9YVtCRtOjZAOrDx2/zMgzIUeIPJ/DfHlqw== X-Received: by 2002:a1c:19c3:0:b0:39c:6479:3ca with SMTP id 186-20020a1c19c3000000b0039c647903camr32962682wmz.27.1656949373388; Mon, 04 Jul 2022 08:42:53 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:52 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach Subject: [PATCH v4 2/7] coresight: configfs: Add in functionality for load via configfs Date: Mon, 4 Jul 2022 16:42:44 +0100 Message-Id: <20220704154249.11501-3-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084255_069884_1F4F81CE X-CRM114-Status: GOOD ( 32.16 ) 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 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. Adds API to access new functionality. Signed-off-by: Mike Leach --- drivers/hwtracing/coresight/Makefile | 2 +- .../coresight/coresight-config-file.c | 520 ++++++++++++++++++ .../coresight/coresight-config-file.h | 139 +++++ .../hwtracing/coresight/coresight-config.h | 15 + .../hwtracing/coresight/coresight-syscfg.h | 1 + 5 files changed, 676 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..be11261e3a14 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-config-file.c @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include "coresight-config.h" +#include "coresight-config-file.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_configs); + 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[used + (elem_str->str_len - 1)] != 0) + return -EINVAL; + + elem_str->str = kstrdup((char *)(buffer + used), 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, int nr_configs) +{ + /* arrays are 0 terminated - nr_configs & nr_features elements */ + desc_arrays->config_descs = kcalloc(nr_configs + 1, sizeof(struct cscfg_config_desc *), + GFP_KERNEL); + if (!desc_arrays->config_descs) + return -ENOMEM; + desc_arrays->feat_descs = kcalloc(nr_features + 1, sizeof(struct cscfg_feature_desc *), + GFP_KERNEL); + if (!desc_arrays->feat_descs) + return -ENOMEM; + return 0; +} + +/* free up the data allocated to a config desc */ +static void cscfg_file_free_config_desc(struct cscfg_config_desc *config_desc) +{ + int i; + + if (!config_desc) + return; + + /* free presets */ + kfree(config_desc->presets); + + /* free feat ref strings */ + if (config_desc->nr_feat_refs) { + /* each string */ + for (i = 0; i < config_desc->nr_feat_refs; i++) + kfree(config_desc->feat_ref_names[i]); + + /* and the char * array */ + kfree(config_desc->feat_ref_names); + } + + /* next the strings */ + kfree(config_desc->name); + kfree(config_desc->description); + + /* finally the struct itself */ + kfree(config_desc); +} + +static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *buf_used, + struct cscfg_fs_load_descs *desc_arrays, + const int cfg_index) +{ + 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 = kzalloc(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 = kcalloc(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 = kcalloc(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[cfg_index] = config_desc; + *buf_used = used; + return 0; +} + +/* + * Read a config name - if there is a config at this position. + * + * Reads the element header at the current position. + * If it is a configuration header (type = CSCFG_FILE_ELEM_TYPE_CFG), + * then continue and read the configuration name into @elem_str and update the + * @buf_used pointers. + * + * Otherwise return 0, without updating the used pointers. + */ +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 void cscfg_file_free_feat_desc(struct cscfg_feature_desc *feat_desc) +{ + if (!feat_desc) + return; + + /* free up the register descriptor array */ + kfree(feat_desc->regs_desc); + + /* free up the parameters array */ + kfree(feat_desc->params_desc); + + /* name and description strings */ + kfree(feat_desc->name); + kfree(feat_desc->description); + + /* finally the struct itself */ + kfree(feat_desc); +} + +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 = kzalloc(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 = kcalloc(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 = kcalloc(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; +} + +/* + * Read a feature name. + * + * Check the element header to ensure that a feature (type = CSCFG_FILE_ELEM_TYPE_FEAT) + * is at this position and read the following string & update @buf_used. + * + * If not a feature then return -EINVAL. + */ +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 feature, 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, hdr.nr_configs); + if (err) + return err; + + /* read elements */ + + /* first elements are configurations */ + for (i = 0; i < hdr.nr_configs; i++) { + err = cscfg_file_read_elem_config(buffer, buflen, &used, desc_arrays, i); + 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 0; +} + +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; +} + +/* + * Need to free up the dynamically allocated descriptor arrays on unload + * as the memory used could be significant if many configurations are loaded + * and unloaded while the machine is operational. + * + * This frees up all the memory allocated by this file during the load process. + */ +void cscfg_file_free_load_descs(struct cscfg_fs_load_descs *desc_arrays) +{ + int i = 0; + + if (!desc_arrays) + return; + + /* free up each of the config descriptors */ + while (desc_arrays->config_descs[i]) { + cscfg_file_free_config_desc(desc_arrays->config_descs[i]); + i++; + } + + /* free up each of the feature descriptors */ + i = 0; + while (desc_arrays->feat_descs[i]) { + cscfg_file_free_feat_desc(desc_arrays->feat_descs[i]); + i++; + } + + /* finally free up the load descs pointer arrays */ + kfree(desc_arrays->config_descs); + kfree(desc_arrays->feat_descs); +} diff --git a/drivers/hwtracing/coresight/coresight-config-file.h b/drivers/hwtracing/coresight/coresight-config-file.h new file mode 100644 index 000000000000..6e8d259dfaaa --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-config-file.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CORESIGHT_CONFIG_FILE_H +#define _CORESIGHT_CORESIGHT_CONFIG_FILE_H + +#include + +#include "coresight-config.h" + +/* + * Structures to represent configuration descriptors in a memory buffer + * to serialise to and from files + * + * File structure - for loading configuration(s) + feature(s) + * from configfs. + * + * [cscfg_file_header] - mandatory + * [CONFIG_ELEM] * [cscfg_file_header.nr_configs] - optional. + * [FEATURE_ELEM] * [cscfg_file_header.nr_features] - optional. + * + * File valid if it has both config(s) and feature(s), only config(s) + * or only feature(s). + * 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] - number of sets of presets supplied + * [u32 value - nr_total_params] - total of all params in referenced features + * [u16 value - nr_feat_refs] - number of features selected by this configuration + * [u64 values] * (nr_presets * nr_total_params) + * [cscfg_file_elem_str] * nr_feat_refs - names of features selected by configuration. + * + * A configuration must reference at least one feature. + * Referenced features may be in this file, or have been loaded previously. + * + * 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, as an internal buffer is declared, + * and will not be exceeded to prevent kernel OOM errors / attacks. + * + * Use a value that will reasonably cover all the usable & programmable registers in + * an ETM, the most complex device we have. + */ +#define CSCFG_FILE_MAXSIZE SZ_16K + +/* limit string sizes - used for descriptions and names. */ +#define CSCFG_FILE_STR_MAXSIZE SZ_1K + +/** + * file header. + * + * @magic_version: magic number / version for file/buffer format. + * @length : total length of all data in the buffer. + * @nr_configs : total number of configs in the buffer. + * @nr_features : total number of features in the buffer. + */ +struct cscfg_file_header { + u32 magic_version; + u16 length; + u16 nr_configs; + 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; +}; + +/* 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); +/* on unload we need to free up memory allocated on read */ +void cscfg_file_free_load_descs(struct cscfg_fs_load_descs *desc_arrays); + +#endif /* _CORESIGHT_CORESIGHT_CONFIG_FILE_H */ diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 6ba013975741..ad212954f99e 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -85,6 +85,21 @@ struct cscfg_regval_desc { }; }; +/** + * 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. + * + * @config_descs: array of config descriptor pointers. + * @feat_descs: array of feature descriptor pointers. + */ +struct cscfg_fs_load_descs { + struct cscfg_config_desc **config_descs; + struct cscfg_feature_desc **feat_descs; +}; + /** * Device feature descriptor - combination of registers and parameters to * program a device to implement a specific complex function. diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index 66e2db890d82..d0c9543850c0 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -79,6 +79,7 @@ struct cscfg_registered_csdev { enum cscfg_load_owner_type { CSCFG_OWNER_PRELOAD, CSCFG_OWNER_MODULE, + CSCFG_OWNER_CONFIGFS, }; /** From patchwork Mon Jul 4 15:42:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905532 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 538EFC433EF for ; Mon, 4 Jul 2022 15:44:44 +0000 (UTC) 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=Rs+IEhWcDYKFXD3zV537Ke3yDh0dY4+KShd2LZOI0WI=; b=AfdhMjYlohNHbV 8jhiT9PvsHHQMKcTEIZcnNMWZm6DP/CJuxMLtHPVhoUnkLXJHVNWPikXfAn9VZTuRfLA+ht4AKd1d 3QMeBnFw20exn1QUwYJbJu0e/Ebrd2J7C+BXCTGEHyLmHmM/uOOuqPyiF7UJn3vGuz+IKWJ5tGGja hEU/CNkjN1dISLx8dA96x57YtJlGo2rzbTvedcZLaRrVTTRg0U/hMtJEIy6V6RQXjllBZFxUoLBtM +rbUbn87sgZaS9deVn7QwA429zQidiy7XuZIpPLq0KixACrz2w5NQVu3pnGF/R2j2VA4/omljiSzD hlaJHGa3FWFjLDpzFcQg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OEc-009m0g-9f; Mon, 04 Jul 2022 15:43:38 +0000 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8ODy-009ljD-21 for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:43:00 +0000 Received: by mail-wr1-x431.google.com with SMTP id o4so14041779wrh.3 for ; Mon, 04 Jul 2022 08:42:55 -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=a0Rzbb8icmC8RVtc3T8ErljDbsFF9Mc0JN0kql2Oo9Q=; b=Pxww1B52DFqHrvI6Li6YrvFsbywuSSQBUHn2M1ArN0nw6ZEr0gXWNjeLpHj1OVlj3x GT5gZ072Zt48e69tHpK66BdwE8Vf3oRA8gCRU4EM4ZGRY8jz9mCmapkFniUVgGaffA8/ D27AacQW8GnHTx/4A5gjaxO3/C/KUDQz5tcPYeHwY4Xy4WXAujqIzYOgTePogYeH0+Ww bbXyE4DELCKxm32fj4gP4fFeROsEJ4hTECdUFsjb9xo6NIA6l819MfzYqD+HW8WRvF1p hqpZypx9JphH07VaiaLMLhL6Ei04sf9GOPckeXSwZ0ZlILIgVFERrUKxsgbViJ6u8Xct /HIA== 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=a0Rzbb8icmC8RVtc3T8ErljDbsFF9Mc0JN0kql2Oo9Q=; b=mGYfK7sSzWeqR0c3dCAbSyXWyb4XsFP7sU6DgekPIzB010aK3G04zboRMCvEIn/vfY n6ZfugayMbKonuYdDN7gBvC0+9gkZSwdWVZkK25oT73/rBXIAt1BWwL6OioGqmYOinV8 I8zjI2Ksr+7RzxXdVzzkv9aoRdCvJA/8bDpjJ+eJsOTimQ6CuaibzuHk1lWiBrMK421i 22f944Qt4oUk1wf8F8kxrU7f9tMLTmkjlnd57dLJaBeXzwNRYqzRdJeVVUDWW6pg4IrF bp6lEDIF/xwE4LZGJsV8jD8pKbIpKWR/rNGLljdCh89yn8Vqqpq0iLZDrkIMGdxjQikC KLUQ== X-Gm-Message-State: AJIora8F3QRbHNyqgdyPrL2xBfbwne1gp7/kB+1VRbg+6PGgvEpvh1n4 YNqO0VRL6H4iwu3IAP7SzbTJqdT7aOoq6A== X-Google-Smtp-Source: AGRyM1vs/yz829mXAuTX5+fl6iGpF2UoW6b7NwQVrAGP3z+qDp1pvJgJRch42C9YTV7ymyTvGQuAag== X-Received: by 2002:adf:dece:0:b0:21b:a4b0:f7e3 with SMTP id i14-20020adfdece000000b0021ba4b0f7e3mr28028244wrn.197.1656949374267; Mon, 04 Jul 2022 08:42:54 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:53 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach Subject: [PATCH v4 3/7] coresight: configfs: Add in binary attributes to load files Date: Mon, 4 Jul 2022 16:42:45 +0100 Message-Id: <20220704154249.11501-4-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084258_154244_69335885 X-CRM114-Status: GOOD ( 33.60 ) 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 in functionality and binary attribute to load and unload configurations as binary data. Files are loaded via the 'load' binary attribute. System reads the incoming file, which must be formatted correctly as defined in the file reader code. This will create configuration(s) and/or feature(s) and load them into the system. These will then appear in configfs, in the 'configurations' and 'features' directories, ready for use. A mutex is used to prevent load and unload operations from happening simultaneously. Further, a flag enabling configfs load/unload is provided, along with API calls to allow this functionality to be controlled during start-up and shut-down, and when configurations are loaded via loadable modules. This ensures that load/unload operations are strictly serialised. Signed-off-by: Mike Leach --- .../coresight/coresight-syscfg-configfs.c | 181 +++++++++++++++++- .../coresight/coresight-syscfg-configfs.h | 3 + .../hwtracing/coresight/coresight-syscfg.c | 107 +++++++++++ .../hwtracing/coresight/coresight-syscfg.h | 1 + 4 files changed, 285 insertions(+), 7 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c index 6e8c8db52d39..16c20598198e 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c @@ -7,8 +7,33 @@ #include #include "coresight-config.h" +#include "coresight-config-file.h" #include "coresight-syscfg-configfs.h" +/* prevent race in load / unload operations */ +static DEFINE_MUTEX(cfs_mutex); + +/* + * need to enable / disable load via configfs when + * initialising / shutting down the subsystem, or + * loading / unloading module. + */ +static bool cscfg_fs_load_enabled; + +void cscfg_configfs_enable_fs_load(void) +{ + mutex_lock(&cfs_mutex); + cscfg_fs_load_enabled = true; + mutex_unlock(&cfs_mutex); +} + +void cscfg_configfs_disable_fs_load(void) +{ + mutex_lock(&cfs_mutex); + cscfg_fs_load_enabled = false; + mutex_unlock(&cfs_mutex); +} + /* create a default ci_type. */ static inline struct config_item_type *cscfg_create_ci_type(void) { @@ -431,14 +456,157 @@ static void cscfg_destroy_feature_group(struct config_group *feat_group) kfree(feat_view); } -static struct config_item_type cscfg_configs_type = { +/* Attributes in configfs that allow load and unload of configuration binary files */ + +/* free memory associated with a configfs loaded configuration file & descriptors */ +void cscfg_configfs_free_owner_info(struct cscfg_load_owner_info *owner_info) +{ + struct cscfg_fs_load_descs *load_descs = 0; + + if (!owner_info) + return; + + load_descs = (struct cscfg_fs_load_descs *)(owner_info->owner_handle); + + if (load_descs) { + /* free the data allocated on file load, pointed to by load_descs */ + cscfg_file_free_load_descs(load_descs); + kfree(load_descs); + } + + kfree(owner_info); +} + + +/* 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_load_descs *load_descs = 0; + struct cscfg_load_owner_info *owner_info = 0; + int err = 0; + + /* ensure we cannot simultaneously load and unload */ + if (!mutex_trylock(&cfs_mutex)) + return -EBUSY; + + /* check configfs load / unload ops are permitted */ + if (!cscfg_fs_load_enabled) { + err = -EBUSY; + goto exit_unlock; + } + + if (size > CSCFG_FILE_MAXSIZE) { + pr_err("cscfg: Load error - Input file too large.\n"); + err = -EINVAL; + goto exit_unlock; + } + + 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; + } + + owner_info->owner_handle = load_descs; + owner_info->type = CSCFG_OWNER_CONFIGFS; + + err = cscfg_file_read_buffer(buffer, size, load_descs); + if (err) { + pr_err("cscfg: 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) { + pr_err("cscfg: Load error - Failed to load configuaration file.\n"); + goto exit_memfree; + } + + mutex_unlock(&cfs_mutex); + return size; + +exit_memfree: + cscfg_configfs_free_owner_info(owner_info); + +exit_unlock: + mutex_unlock(&cfs_mutex); + 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_load_owner_info *owner_info = 0; + const char *name; + int err = 0; + + /* ensure we cannot simultaneously load and unload */ + if (!mutex_trylock(&cfs_mutex)) + return -EBUSY; + + /* check configfs load / unload ops are permitted */ + if (!cscfg_fs_load_enabled) { + err = -EBUSY; + goto exit_unlock; + } + + if (size > CSCFG_FILE_MAXSIZE) { + pr_err("cscfg: Unload error - Input file too large\n"); + err = -EINVAL; + goto exit_unlock; + } + + err = cscfg_file_read_buffer_first_name(buffer, size, &name); + if (err) { + pr_err("cscfg: Unload error - Failed to read input file\n"); + goto exit_unlock; + } + + owner_info = cscfg_find_fs_owned_cfg_by_name(name); + if (!owner_info) { + pr_err("cscfg: Unload error: Failed to find %s from input file\n", + name); + goto exit_unlock; + } + err = cscfg_unload_config_sets(owner_info); + if (err) { + pr_err("cscfg: Unload error: Cannot unload configuration %s\n", + name); + goto exit_unlock; + } + + cscfg_configfs_free_owner_info(owner_info); + + err = size; + +exit_unlock: + mutex_unlock(&cfs_mutex); + return err; +} +CONFIGFS_BIN_ATTR_WO(cscfg_cfg_, unload, NULL, CSCFG_FILE_MAXSIZE); + +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_load_type = { .ct_owner = THIS_MODULE, + .ct_bin_attrs = cscfg_config_configfs_bin_attrs, }; +static struct config_item_type cscfg_configs_grp_type = { + .ct_owner = THIS_MODULE, +}; + +/* group for configurations dir */ static struct config_group cscfg_configs_grp = { .cg_item = { .ci_namebuf = "configurations", - .ci_type = &cscfg_configs_type, + .ci_type = &cscfg_configs_grp_type, }, }; @@ -508,18 +676,17 @@ void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc) int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr) { struct configfs_subsystem *subsys; - struct config_item_type *ci_type; if (!cscfg_mgr) return -EINVAL; - ci_type = cscfg_create_ci_type(); - if (!ci_type) - return -ENOMEM; + /* load and unload by configfs initially disabled */ + cscfg_fs_load_enabled = false; + /* init subsystem group - with load and unload attributes */ subsys = &cscfg_mgr->cfgfs_subsys; config_item_set_name(&subsys->su_group.cg_item, CSCFG_FS_SUBSYS_NAME); - subsys->su_group.cg_item.ci_type = ci_type; + subsys->su_group.cg_item.ci_type = &cscfg_configs_load_type; config_group_init(&subsys->su_group); mutex_init(&subsys->su_mutex); diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h index 373d84d43268..decc96842ade 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h @@ -45,5 +45,8 @@ int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc); int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc); void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc); void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc); +void cscfg_configfs_free_owner_info(struct cscfg_load_owner_info *owner_info); +void cscfg_configfs_enable_fs_load(void); +void cscfg_configfs_disable_fs_load(void); #endif /* CORESIGHT_SYSCFG_CONFIGFS_H */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 11138a9762b0..fcb885ba5084 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -554,6 +554,22 @@ static int cscfg_fs_register_cfgs_feats(struct cscfg_config_desc **config_descs, return 0; } +/* + * check owner info and if module owner, disable / enable + * configfs load ops. + */ +static void cscfg_check_disable_fs_load(struct cscfg_load_owner_info *owner_info) +{ + if (owner_info->type == CSCFG_OWNER_MODULE) + cscfg_configfs_disable_fs_load(); +} + +static void cscfg_check_enable_fs_load(struct cscfg_load_owner_info *owner_info) +{ + if (owner_info->type == CSCFG_OWNER_MODULE) + cscfg_configfs_enable_fs_load(); +} + /** * cscfg_load_config_sets - API function to load feature and config sets. * @@ -578,6 +594,9 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, { int err = 0; + /* if this load is by module owner, need to disable configfs load/unload */ + cscfg_check_disable_fs_load(owner_info); + mutex_lock(&cscfg_mutex); if (cscfg_mgr->load_state != CSCFG_NONE) { mutex_unlock(&cscfg_mutex); @@ -634,6 +653,8 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, exit_unlock: cscfg_mgr->load_state = CSCFG_NONE; mutex_unlock(&cscfg_mutex); + + cscfg_check_enable_fs_load(owner_info); return err; } EXPORT_SYMBOL_GPL(cscfg_load_config_sets); @@ -659,6 +680,9 @@ int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) int err = 0; struct cscfg_load_owner_info *load_list_item = NULL; + /* if this unload is by module owner, need to disable configfs load/unload */ + cscfg_check_disable_fs_load(owner_info); + mutex_lock(&cscfg_mutex); if (cscfg_mgr->load_state != CSCFG_NONE) { mutex_unlock(&cscfg_mutex); @@ -705,10 +729,65 @@ int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) exit_unlock: cscfg_mgr->load_state = CSCFG_NONE; mutex_unlock(&cscfg_mutex); + + cscfg_check_enable_fs_load(owner_info); return err; } EXPORT_SYMBOL_GPL(cscfg_unload_config_sets); +/* find a configuration owned by configfs by name of config / first feature */ +struct cscfg_load_owner_info *cscfg_find_fs_owned_cfg_by_name(const char *name) +{ + struct cscfg_load_owner_info *owner_info = NULL; + struct cscfg_fs_load_descs *fs_load_cfg; + 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; + } + } + } + + /* not found */ + owner_info = NULL; + +exit_unlock: + mutex_unlock(&cscfg_mutex); + return owner_info; +} + +/* get configfs config load name from configfs type owner */ +static const char *cscfg_find_load_name_fs_owned_cfg(struct cscfg_load_owner_info *owner_info) +{ + struct cscfg_fs_load_descs *fs_load_cfg; + const char *name = "unknown"; + + if (owner_info->type == CSCFG_OWNER_CONFIGFS) { + fs_load_cfg = (struct cscfg_fs_load_descs *)owner_info->owner_handle; + if (fs_load_cfg->config_descs[0]) + name = fs_load_cfg->config_descs[0]->name; + else if (fs_load_cfg->feat_descs[0]) + name = fs_load_cfg->feat_descs[0]->name; + } + return name; +} + /* Handle coresight device registration and add configs and features to devices */ /* iterate through config lists and load matching configs to device */ @@ -1206,6 +1285,7 @@ static int cscfg_create_device(void) static void cscfg_unload_cfgs_on_exit(void) { struct cscfg_load_owner_info *owner_info = NULL; + bool free_configfs_owner = false; /* * grab the mutex - even though we are exiting, some configfs files @@ -1240,6 +1320,23 @@ static void cscfg_unload_cfgs_on_exit(void) */ pr_err("cscfg: ERROR: prior module failed to unload configuration\n"); goto list_remove; + + case CSCFG_OWNER_CONFIGFS: + /* + * configfs loaded items may still be present if the user did not + * unload them during the session. These have dynamically allocated + * descriptor tables (unlike the two types above that are statically + * allocated at compile time) + */ + pr_info("cscfg: unloading configfs loaded configuration %s\n", + cscfg_find_load_name_fs_owned_cfg(owner_info)); + + /* + * as this is not being unloaded by configfs, need to flag the + * requirement to free up the descriptors. + */ + free_configfs_owner = true; + break; } /* remove from configfs - outside the scope of the list mutex */ @@ -1253,6 +1350,12 @@ static void cscfg_unload_cfgs_on_exit(void) list_remove: /* remove from load order list */ list_del(&owner_info->item); + + /* configfs owned dynamic loaded config, free memory now */ + if (free_configfs_owner) { + cscfg_configfs_free_owner_info(owner_info); + free_configfs_owner = false; + } } mutex_unlock(&cscfg_mutex); } @@ -1284,6 +1387,9 @@ int __init cscfg_init(void) if (err) goto exit_err; + /* can now allow load / unload from configfs */ + cscfg_configfs_enable_fs_load(); + dev_info(cscfg_device(), "CoreSight Configuration manager initialised"); return 0; @@ -1294,5 +1400,6 @@ int __init cscfg_init(void) void cscfg_exit(void) { + cscfg_configfs_disable_fs_load(); cscfg_clear_device(); } diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index d0c9543850c0..752ffcd1eee8 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -108,6 +108,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_load_owner_info *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, From patchwork Mon Jul 4 15:42:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905531 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 38C4CCCA47C for ; Mon, 4 Jul 2022 15:44:32 +0000 (UTC) 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=T8/2Fjcc7B3ageeQRacxv+wAXNna3J5swS3TrE+b/Dk=; b=HLEYdF5dOoQV9p CelyIqSDWKMparbbXana5IryU/YExmMOkn4cjCLpsJpXt18pGma02BZ1Wx9Te2gWcSqMhQjCWKmMi FKAri3jfo1oF0NWdQzD8vwzKTAtmXe8e1EABr0UMqCsu1HZzHRwukUAMfV/y9QLog2UmD7waHgEe+ UvZ/cVcMMJViRmag3DzostB00bNjnETtGd2JZCMMUcq+f3tVcUiexON1eNCSYG8JQy0+gr+b3UPee fkHNWS5TXrfXMp2iuE/6L9xWlTqEMvS4SwD2pBinsMeiwitB2inH//bFEEjas0AKgWElcluN2bSwX ErqpQdvhOv22d29lRmiQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OER-009lvc-UW; Mon, 04 Jul 2022 15:43:28 +0000 Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8ODw-009ljw-AG for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:43:00 +0000 Received: by mail-wm1-x32a.google.com with SMTP id u12-20020a05600c210c00b003a02b16d2b8so5898042wml.2 for ; Mon, 04 Jul 2022 08:42:56 -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=U/nQc9F2ybSBykdgEFS8tw/oKByW2ekwPZG/Qs1Xn9Q=; b=eyUViZvvFjDQRPYHdqM1Ivukdx4hzI8IMQ8xguzmyDe3uvMew3y7Lc+Fbe2ZCb6jrR 5J+GemZlulcHl66lcY/lmNJgpksERwu/gOUeBTUjiUR8t7tSLKM79rYjmQFPpGpnOxvR GwEOYUH7xmkHIBqBWnDhsdzXxcK6xbC/C0XQanrP8rVQ88ddQrHaz1S29O2VSlDgita4 NNjGhHmPqzdh1eXWaf1qCdzqgs3JC2ThmsrKyIFDS1eP0hniPeHhJ0f/XRSK4XjORCI6 +k7q7iWRZvrlwuhGdXVGZIf/gED9JggvJy2gnmsv0aF52Yb2/T6So4vZVY30W8JE6HpC Kz4w== 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=U/nQc9F2ybSBykdgEFS8tw/oKByW2ekwPZG/Qs1Xn9Q=; b=m+y2HLzDWS8Q5i3u65Pz0uLueiXyUjXgU2ShoVTx4O/h3ovnbfhz8QKwIx5QZD+FNu HEqn2XOGYj3K4mDC05cJtU/pLXJNcFjz0cORY4/gO3ZA/TgbQsU6Ln0yjdnkGmGFbBKd 6WGpqz9SozBw7VOkyQl1DP5zHYo2es/k0QPnuqJrIGZNzNn6OMnt9z8YUbJ44Nbp8koa 8xsNBCz4Jue69o5rcMYqPozrGFMaOdkxKqn+8FLF39xBrDKBu4/+MEWGYTnCO11y0Oxk WbPV8q/EgiFbBPpxqkpGFReEKfiMeZBUslytiDKYEebwS/KIIO7SlkS8YExHFoaeg91e +Bvw== X-Gm-Message-State: AJIora/pvWoPqZRXOX1chAcoB4aTj4aM+xZL7mX/2dvb8WUiJyQ2zzQR 36C50nM99gtZKL+DUG5bPBLPc415gPtkWQ== X-Google-Smtp-Source: AGRyM1veMtv33VTPTrMB35ut1H+L7YBCkdZMGSx8GKqSuhDrh9LaSGZwrfEVJffFnCxLFU4pKE3WoQ== X-Received: by 2002:a05:600c:19c8:b0:3a1:792e:f913 with SMTP id u8-20020a05600c19c800b003a1792ef913mr28190562wmq.182.1656949375112; Mon, 04 Jul 2022 08:42:55 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:54 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach Subject: [PATCH v4 4/7] coresight: configfs: Modify config files to allow userspace use Date: Mon, 4 Jul 2022 16:42:46 +0100 Message-Id: <20220704154249.11501-5-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084256_493672_D65EB131 X-CRM114-Status: GOOD ( 27.89 ) 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 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 --- .../coresight/coresight-config-file.c | 117 +++++++++++++----- .../hwtracing/coresight/coresight-config.h | 12 ++ 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-config-file.c b/drivers/hwtracing/coresight/coresight-config-file.c index be11261e3a14..cf9f178eef97 100644 --- a/drivers/hwtracing/coresight/coresight-config-file.c +++ b/drivers/hwtracing/coresight/coresight-config-file.c @@ -7,6 +7,63 @@ #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__ + +static void *cscfg_calloc(size_t num, size_t size) +{ + return kcalloc(num, size, GFP_KERNEL); +} + +static char *cscfg_strdup(const char *str) +{ + return kstrdup(str, GFP_KERNEL); +} + +static void *cscfg_zalloc(size_t size) +{ + return kzalloc(size, GFP_KERNEL); +} + +static void cscfg_free(void *mem) +{ + kfree(mem); +} +#else + +#include +#include +#include + +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; +} + +static void cscfg_free(void *mem) +{ + free(mem); +} +#endif + #define cscfg_extract_u64(val64) { \ val64 = *(u64 *)(buffer + used); \ used += sizeof(u64); \ @@ -80,6 +137,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 +147,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[used + (elem_str->str_len - 1)] != 0) + if (str[elem_str->str_len - 1] != 0) return -EINVAL; - elem_str->str = kstrdup((char *)(buffer + used), GFP_KERNEL); + elem_str->str = cscfg_strdup((char *)str); used += elem_str->str_len; *buf_used = used; @@ -104,12 +164,13 @@ static int cscfg_file_alloc_desc_arrays(struct cscfg_fs_load_descs *desc_arrays, int nr_features, int nr_configs) { /* arrays are 0 terminated - nr_configs & nr_features elements */ - desc_arrays->config_descs = kcalloc(nr_configs + 1, sizeof(struct cscfg_config_desc *), - GFP_KERNEL); + desc_arrays->config_descs = cscfg_calloc(nr_configs + 1, + sizeof(struct cscfg_config_desc *)); if (!desc_arrays->config_descs) return -ENOMEM; - desc_arrays->feat_descs = kcalloc(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; @@ -124,24 +185,24 @@ static void cscfg_file_free_config_desc(struct cscfg_config_desc *config_desc) return; /* free presets */ - kfree(config_desc->presets); + cscfg_free((void *)config_desc->presets); /* free feat ref strings */ if (config_desc->nr_feat_refs) { /* each string */ for (i = 0; i < config_desc->nr_feat_refs; i++) - kfree(config_desc->feat_ref_names[i]); + cscfg_free((void *)config_desc->feat_ref_names[i]); /* and the char * array */ - kfree(config_desc->feat_ref_names); + cscfg_free((void *)config_desc->feat_ref_names); } /* next the strings */ - kfree(config_desc->name); - kfree(config_desc->description); + cscfg_free((void *)config_desc->name); + cscfg_free((void *)config_desc->description); /* finally the struct itself */ - kfree(config_desc); + cscfg_free((void *)config_desc); } static int cscfg_file_read_elem_config(const u8 *buffer, const int buflen, int *buf_used, @@ -166,7 +227,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 = kzalloc(sizeof(struct cscfg_config_desc), GFP_KERNEL); + config_desc = cscfg_zalloc(sizeof(struct cscfg_config_desc)); if (!config_desc) return -ENOMEM; @@ -192,7 +253,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 = kcalloc(nr_preset_vals, sizeof(u64), GFP_KERNEL); + presets = cscfg_calloc(nr_preset_vals, sizeof(u64)); if (!presets) return -ENOMEM; @@ -207,8 +268,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 = kcalloc(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; @@ -289,17 +350,17 @@ static void cscfg_file_free_feat_desc(struct cscfg_feature_desc *feat_desc) return; /* free up the register descriptor array */ - kfree(feat_desc->regs_desc); + cscfg_free((void *)feat_desc->regs_desc); /* free up the parameters array */ - kfree(feat_desc->params_desc); + cscfg_free((void *)feat_desc->params_desc); /* name and description strings */ - kfree(feat_desc->name); - kfree(feat_desc->description); + cscfg_free((void *)feat_desc->name); + cscfg_free((void *)feat_desc->description); /* finally the struct itself */ - kfree(feat_desc); + cscfg_free((void *)feat_desc); } static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int *buf_used, @@ -314,7 +375,7 @@ static int cscfg_file_read_elem_feature(const u8 *buffer, const int buflen, int u32 val32; /* allocate the feature descriptor object */ - feat_desc = kzalloc(sizeof(struct cscfg_feature_desc), GFP_KERNEL); + feat_desc = cscfg_zalloc(sizeof(struct cscfg_feature_desc)); if (!feat_desc) return -ENOMEM; @@ -353,8 +414,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 = kcalloc(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; @@ -368,8 +429,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 = kcalloc(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++) { @@ -515,6 +576,6 @@ void cscfg_file_free_load_descs(struct cscfg_fs_load_descs *desc_arrays) } /* finally free up the load descs pointer arrays */ - kfree(desc_arrays->config_descs); - kfree(desc_arrays->feat_descs); + cscfg_free(desc_arrays->config_descs); + cscfg_free(desc_arrays->feat_descs); } diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index ad212954f99e..58d4f179ff0d 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 +#endif + #include /* CoreSight Configuration Management - component and system wide configuration */ @@ -100,6 +107,10 @@ struct cscfg_fs_load_descs { struct cscfg_feature_desc **feat_descs; }; + +/* remainder of header is used by the kernel drivers only */ +#ifdef __KERNEL__ + /** * Device feature descriptor - combination of registers and parameters to * program a device to implement a specific complex function. @@ -274,4 +285,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 */ From patchwork Mon Jul 4 15:42:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905533 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C554DC433EF for ; Mon, 4 Jul 2022 15:45:05 +0000 (UTC) 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=vEvInzxQL2zSPRYFw6t5ujAGok1HB3UPHQX+pg08II4=; b=38PZV73huCWiMf 9hXCAOXtErOjibBVX7ITm8MXYzVOMqh9De/fdDOUMH8W1czJ77DCWjl48S+3Ym5zOx+UQUvNJclwX OdSmQu7DS+mPip10TPzL5mq/d1YeOKO8QJ3j415l+eczJDfU8GznwFT8UVq+EzvNeTbCr6bxPsL0V jCtPI6wEO39KdI92bEQ/HlpBNZ7jUk0vKzL0IJOFc/rI7uxQq2JlN1Z2oIqJ4PjxtNqL5R2YS/Nlm HBAx9/EwAHeYlr43VLc9lvEihDLKOrlBIuTCITO/aDDeNmotgTbbDcgacqCQlx40cR4pZHaygv/aG oau77NrDYYAsNnonFxQw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OEt-009m7Z-DK; Mon, 04 Jul 2022 15:43:55 +0000 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8ODx-009lkn-LE for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:43:02 +0000 Received: by mail-wm1-x32e.google.com with SMTP id u12-20020a05600c210c00b003a02b16d2b8so5898064wml.2 for ; Mon, 04 Jul 2022 08:42:57 -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=RmgxoFmAK1lGXsXs9iowY+s/Fw48xVbsAB2msMG7gcs=; b=CRAxHSZWECkI+8JmvQqg8gGqUoFj/OKwNtNcxNLbCUjTUgR73GcyLeFWdtbtUtV9UC v3MBNquVA1bghgZKr8NSanryX4+crXIiSTIz7C+c/f+zISaq6WBsAH/KHOl8l1bviDf9 /PGkHEoLDRYZypjXyMsSPi0ImxVndHc34/lFgoDrri5hlJsHdsxikq9YaiXNaL50lHrJ TsZ77kViZlzXRWJi+NWUG6Ste2rUfO+twzdq5RhA7Qd/eeB1JCzQntEfonqoaQAPOYkG 66YhGHRJLOAZLajiE/e7WlWpa1ZcfYA5vU4q2uHJwHO3icKaDT1LKbbeBcHzQBfJmlbG YTww== 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=RmgxoFmAK1lGXsXs9iowY+s/Fw48xVbsAB2msMG7gcs=; b=YGqPbmDTMos5lCwWG4/9Hfs+gcVFl8pF57mFtOuMmVjtTgoOKdetZT3pyyemFAsLDu PNBVo3GorB1AJ+LZGJt3GUwvPcO64KMYeBG1NoXn1vUqXPwFghsqbLsjVnwLJKd7gkJx 4WT62DPSETAJEIBUR7a57DzOisg6bGdq2ZdYHGOuCXJLdv5Y3B2kgYuWhuHixBkhWAeG 6rR2iq5oo/tj71XS6Pdxspw8wKFvk5k9/5Vbnf2d530NZq3X7uILiRsYqPQmr1SSpbLT Br43IskDlqcLEDCAJCWGSMkkQWhWOAv78CSQjcXbaXqu27AidDmlHLLU/3DkkNjLB34W Zkag== X-Gm-Message-State: AJIora+YXNWHDMLeEN8nb1mEfafYU5xUNfrOIOrNfhNtxyRnpe4wdEns n3yrydeU0VFo1DvRjzgE7gS0Un/qG0Zdzg== X-Google-Smtp-Source: AGRyM1sYDuxHlkafEGY1qCgU81DWHCguKFgZ0wXw0XVNsQ/6bqVT5gHDvgUBAEDrQwAt75L7JvjdxQ== X-Received: by 2002:a05:600c:1d95:b0:3a0:3cf1:5eb4 with SMTP id p21-20020a05600c1d9500b003a03cf15eb4mr31882325wms.50.1656949375949; Mon, 04 Jul 2022 08:42:55 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:55 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach Subject: [PATCH v4 5/7] coresight: tools: Add config file write and reader tools Date: Mon, 4 Jul 2022 16:42:47 +0100 Message-Id: <20220704154249.11501-6-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084257_797112_60319200 X-CRM114-Status: GOOD ( 32.42 ) 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. Add a config file reader and printer. Takes in config files and prints the contents. Uses file reader source from kernel driver. Signed-off-by: Mike Leach --- MAINTAINERS | 1 + .../coresight/coresight-config-file.c | 2 + tools/coresight/Makefile | 52 +++ tools/coresight/coresight-cfg-bufw.c | 309 ++++++++++++++++++ tools/coresight/coresight-cfg-bufw.h | 26 ++ tools/coresight/coresight-cfg-example1.c | 62 ++++ tools/coresight/coresight-cfg-example2.c | 95 ++++++ tools/coresight/coresight-cfg-examples.h | 22 ++ tools/coresight/coresight-cfg-file-gen.c | 61 ++++ tools/coresight/coresight-cfg-file-read.c | 227 +++++++++++++ tools/coresight/coresight-config-uapi.h | 76 +++++ 11 files changed, 933 insertions(+) create mode 100644 tools/coresight/Makefile create mode 100644 tools/coresight/coresight-cfg-bufw.c create mode 100644 tools/coresight/coresight-cfg-bufw.h create mode 100644 tools/coresight/coresight-cfg-example1.c create mode 100644 tools/coresight/coresight-cfg-example2.c create mode 100644 tools/coresight/coresight-cfg-examples.h create mode 100644 tools/coresight/coresight-cfg-file-gen.c create mode 100644 tools/coresight/coresight-cfg-file-read.c create mode 100644 tools/coresight/coresight-config-uapi.h diff --git a/MAINTAINERS b/MAINTAINERS index 171563d8dc14..0cb75b1186c7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1989,6 +1989,7 @@ F: drivers/hwtracing/coresight/* F: include/dt-bindings/arm/coresight-cti-dt.h F: include/linux/coresight* F: samples/coresight/* +F: tools/coresight/* F: tools/perf/arch/arm/util/auxtrace.c F: tools/perf/arch/arm/util/cs-etm.c F: tools/perf/arch/arm/util/cs-etm.h diff --git a/drivers/hwtracing/coresight/coresight-config-file.c b/drivers/hwtracing/coresight/coresight-config-file.c index cf9f178eef97..43aaa44e86d5 100644 --- a/drivers/hwtracing/coresight/coresight-config-file.c +++ b/drivers/hwtracing/coresight/coresight-config-file.c @@ -39,6 +39,8 @@ static void cscfg_free(void *mem) #include #include +#include "coresight-config-uapi.h" + static void *cscfg_calloc(size_t num, size_t size) { return calloc(num, size); diff --git a/tools/coresight/Makefile b/tools/coresight/Makefile new file mode 100644 index 000000000000..584e2271b0f5 --- /dev/null +++ b/tools/coresight/Makefile @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-only +include ../scripts/Makefile.include +include ../scripts/Makefile.arch + +# Makefile to build the coresight configuration file reader and generator tools + +this-makefile := $(lastword $(MAKEFILE_LIST)) +tools-src := $(realpath $(dir $(this-makefile))) +srctree := $(realpath $(dir $(tools-src)/../../.)) + +# ensure we use all as the default - skip anything in included Makefile +.DEFAULT_GOAL = all +# MAKECMDGOALS isn't set if there's no explicit goal in the +# command line, so set the default. +MAKECMDGOALS ?= $(.DEFAULT_GOAL) + +# compile flags +CFLAGS += $(CPPFLAGS) -c -Wall -DLINUX -Wno-switch -Wlogical-op -fPIC -I$(srctree)/drivers/hwtracing/coresight -I$(srctree)/tools/include/ -I$(srctree)/tools/include/uapi + +# object files +coresight-cfg-file-gen-objs := coresight-cfg-file-gen.o coresight-cfg-bufw.o \ + coresight-cfg-example1.o coresight-cfg-example2.o +coresight-cfg-file-read-objs := coresight-cfg-file-read.o coresight-config-file.o + +# debug variant +ifdef DEBUG +CFLAGS += -g -O0 -DDEBUG +else +CFLAGS += -O2 -DNDEBUG +endif + +.PHONY: all +all: coresight-cfg-file-gen coresight-cfg-file-read + +coresight-config-file.o: src_copy + $(CC) $(CFLAGS) coresight-config-file.c -o coresight-config-file.o + +.PHONY: src_copy +src_copy: + @cp $(srctree)/drivers/hwtracing/coresight/coresight-config-file.c $(srctree)/tools/coresight/. + +coresight-cfg-file-gen: $(coresight-cfg-file-gen-objs) + $(CC) $(LDFLAGS) $(coresight-cfg-file-gen-objs) -o coresight-cfg-file-gen + +coresight-cfg-file-read: $(coresight-cfg-file-read-objs) + $(CC) $(LDFLAGS) $(coresight-cfg-file-read-objs) -o coresight-cfg-file-read + +clean: + rm -f coresight-cfg-file-gen coresight-cfg-file-read + rm -f *.o + rm -f coresight-config-file.c + rm -f *.cscfg diff --git a/tools/coresight/coresight-cfg-bufw.c b/tools/coresight/coresight-cfg-bufw.c new file mode 100644 index 000000000000..891fff4e3264 --- /dev/null +++ b/tools/coresight/coresight-cfg-bufw.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include + +#include "coresight-cfg-bufw.h" +#include "coresight-config-uapi.h" + +/* + * Set of macros to make writing the buffer code easier. + *. + * Uses naming convention as 'buffer' for the buffer pointer and + * 'used' as the current bytes used by the encosing function. + */ +#define cscfg_write_u64(val64) { \ + *(u64 *)(buffer + used) = val64; \ + used += sizeof(u64); \ + } + +#define cscfg_write_u32(val32) { \ + *(u32 *)(buffer + used) = val32; \ + used += sizeof(u32); \ + } + +#define cscfg_write_u16(val16) { \ + *(u16 *)(buffer + used) = val16; \ + used += sizeof(u16); \ + } + +#define cscfg_write_u8(val8) { \ + *(buffer + used) = val8; \ + used++; \ + } + +#define CHECK_WRET(rval) { \ + if (rval < 0) \ + return rval; \ + used += rval; \ + } + +/* write the header at the start of the buffer */ +static int cscfg_file_write_fhdr(u8 *buffer, const int buflen, + const struct cscfg_file_header *fhdr) +{ + int used = 0; + + cscfg_write_u32(fhdr->magic_version); + cscfg_write_u16(fhdr->length); + cscfg_write_u16(fhdr->nr_configs); + 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_descs, + 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_configs = 0; + fhdr.nr_features = 0; + + /* count the configs */ + if (config_descs) { + while (config_descs[fhdr.nr_configs]) + fhdr.nr_configs++; + } + + /* 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 ((!fhdr.nr_configs && !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 configs */ + for (i = 0; i < fhdr.nr_configs; i++) { + bytes_w = cscfg_file_write_config(buffer + used, buflen - used, + config_descs[i]); + CHECK_WRET(bytes_w); + } + + /* write any features */ + for (i = 0; i < fhdr.nr_features; i++) { + bytes_w = cscfg_file_write_feat(buffer + used, buflen - used, + feat_descs[i]); + CHECK_WRET(bytes_w); + } + + /* finally re-write the header at the buffer start with the correct length */ + fhdr.length = (u16)used; + bytes_w = cscfg_file_write_fhdr(buffer, buflen, &fhdr); + /* no CHECK_WRET as used must not be updated */ + if (bytes_w < 0) + return bytes_w; + return used; +} diff --git a/tools/coresight/coresight-cfg-bufw.h b/tools/coresight/coresight-cfg-bufw.h new file mode 100644 index 000000000000..08e0e796bf2e --- /dev/null +++ b/tools/coresight/coresight-cfg-bufw.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CFG_BUFW_H +#define _CORESIGHT_CFG_BUFW_H + +#include + +#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_descs, + struct cscfg_feature_desc **feat_descs); + +#endif /* _CORESIGHT_CFG_BUFW_H */ diff --git a/tools/coresight/coresight-cfg-example1.c b/tools/coresight/coresight-cfg-example1.c new file mode 100644 index 000000000000..c562116ffc94 --- /dev/null +++ b/tools/coresight/coresight-cfg-example1.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ +#include +#include +#include +#include + +#include "coresight-cfg-examples.h" + +/* + * create a configuration only example using the strobing feature + */ + +/* we will provide 4 sets of preset parameter values */ +#define AFDO3_NR_PRESETS 4 +/* the total number of parameters in used features - strobing has 2 */ +#define AFDO3_NR_PARAM_SUM 2 + +static const char *afdo3_ref_names[] = { + "strobing", +}; + +/* + * set of presets leaves strobing window constant while varying period to allow + * experimentation with mark / space ratios for various workloads + */ +static u64 afdo3_presets[AFDO3_NR_PRESETS][AFDO3_NR_PARAM_SUM] = { + { 2000, 100 }, + { 2000, 1000 }, + { 2000, 5000 }, + { 2000, 10000 }, +}; + +struct cscfg_config_desc afdo3 = { + .name = "autofdo3", + .description = "Setup ETMs with strobing for autofdo\n" + "Supplied presets allow experimentation with mark-space ratio for various loads\n", + .nr_feat_refs = ARRAY_SIZE(afdo3_ref_names), + .feat_ref_names = afdo3_ref_names, + .nr_presets = AFDO3_NR_PRESETS, + .nr_total_params = AFDO3_NR_PARAM_SUM, + .presets = &afdo3_presets[0][0], +}; + +static struct cscfg_feature_desc *sample_feats[] = { + NULL +}; + +static struct cscfg_config_desc *sample_cfgs[] = { + &afdo3, + NULL +}; + +struct cscfg_file_eg_info file_info_eg1 = { + .example_name = "example1", + .filename = "example1.cscfg", + .config_descs = sample_cfgs, + .feat_descs = sample_feats, +}; diff --git a/tools/coresight/coresight-cfg-example2.c b/tools/coresight/coresight-cfg-example2.c new file mode 100644 index 000000000000..6312a185bd46 --- /dev/null +++ b/tools/coresight/coresight-cfg-example2.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ +#include +#include +#include +#include + +#include "coresight-cfg-examples.h" + +/* + * create a dual configuration only example using the strobing feature + */ + +/* we will provide 10 sets of preset parameter values */ +#define AFDO_NR_PRESETS 10 +/* the total number of parameters in used features - strobing has 2 */ +#define AFDO_NR_PARAM_SUM 2 + +static const char *afdo_ref_names[] = { + "strobing", +}; + +/* + * sets of presets leaves strobing window constant while varying period to allow + * experimentation with mark / space ratios for various workloads + */ +static u64 afdo_set_a_presets[AFDO_NR_PRESETS][AFDO_NR_PARAM_SUM] = { + { 2000, 100 }, + { 2000, 1000 }, + { 2000, 5000 }, + { 2000, 10000 }, + { 4000, 100 }, + { 4000, 1000 }, + { 4000, 5000 }, + { 4000, 10000 }, + { 6000, 100 }, + { 6000, 1000 }, +}; + + +static u64 afdo_set_b_presets[AFDO_NR_PRESETS][AFDO_NR_PARAM_SUM] = { + { 6000, 5000 }, + { 6000, 10000 }, + { 8000, 100 }, + { 8000, 1000 }, + { 8000, 5000 }, + { 8000, 10000 }, + { 12000, 100 }, + { 12000, 1000 }, + { 12000, 5000 }, + { 12000, 10000 }, +}; +/* two configurations with differing preset tables */ +struct cscfg_config_desc afdo_seta = { + .name = "autofdo_set_a", + .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(afdo_ref_names), + .feat_ref_names = afdo_ref_names, + .nr_presets = AFDO_NR_PRESETS, + .nr_total_params = AFDO_NR_PARAM_SUM, + .presets = &afdo_set_a_presets[0][0], +}; + +struct cscfg_config_desc afdo_setb = { + .name = "autofdo_set_b", + .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(afdo_ref_names), + .feat_ref_names = afdo_ref_names, + .nr_presets = AFDO_NR_PRESETS, + .nr_total_params = AFDO_NR_PARAM_SUM, + .presets = &afdo_set_b_presets[0][0], +}; + + +static struct cscfg_feature_desc *sample_feats[] = { + NULL +}; + +static struct cscfg_config_desc *sample_cfgs[] = { + &afdo_seta, + &afdo_setb, + NULL +}; + +struct cscfg_file_eg_info file_info_eg2 = { + .example_name = "example2", + .filename = "example2.cscfg", + .config_descs = sample_cfgs, + .feat_descs = sample_feats, +}; diff --git a/tools/coresight/coresight-cfg-examples.h b/tools/coresight/coresight-cfg-examples.h new file mode 100644 index 000000000000..a13e1553b271 --- /dev/null +++ b/tools/coresight/coresight-cfg-examples.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CFG_EXAMPLES_H +#define _CORESIGHT_CFG_EXAMPLES_H + +#include + +#include "coresight-config-uapi.h" + +/* structure to pass configuraiton information to generator program */ +struct cscfg_file_eg_info { + const char *example_name; + const char *filename; + struct cscfg_config_desc **config_descs; + struct cscfg_feature_desc **feat_descs; +}; + +#endif /* _CORESIGHT_CFG_EXAMPLES_H */ diff --git a/tools/coresight/coresight-cfg-file-gen.c b/tools/coresight/coresight-cfg-file-gen.c new file mode 100644 index 000000000000..0840732dbd50 --- /dev/null +++ b/tools/coresight/coresight-cfg-file-gen.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include +#include +#include +#include + +#include "coresight-cfg-examples.h" +#include "coresight-cfg-bufw.h" + +/* references to the configuration and feature example structures */ +extern struct cscfg_file_eg_info file_info_eg1; +extern struct cscfg_file_eg_info file_info_eg2; + +/* array of example files to generate */ +struct cscfg_file_eg_info *info_ptrs[] = { + &file_info_eg1, + &file_info_eg2, + NULL, +}; + +int main(int argc, char **argv) +{ + struct cscfg_config_desc **config_descs; + struct cscfg_feature_desc **feat_descs; + u8 buffer[CSCFG_FILE_MAXSIZE]; + int used, idx = 0; + FILE *fp; + const char *filename; + + printf("Coresight Configuration file Generator\n\n"); + + while (info_ptrs[idx]) { + printf("Generating %s example\n", info_ptrs[idx]->example_name); + config_descs = info_ptrs[idx]->config_descs; + feat_descs = info_ptrs[idx]->feat_descs; + filename = info_ptrs[idx]->filename; + used = cscfg_file_write_buffer(buffer, CSCFG_FILE_MAXSIZE, + config_descs, feat_descs); + + if (used < 0) { + printf("Error %d writing configuration %s into buffer\n", + used, info_ptrs[idx]->example_name); + return used; + } + + fp = fopen(filename, "wb"); + if (fp == NULL) { + printf("Error opening file %s\n", filename); + return -1; + } + fwrite(buffer, used, sizeof(u8), fp); + fclose(fp); + idx++; + } + return 0; +} diff --git a/tools/coresight/coresight-cfg-file-read.c b/tools/coresight/coresight-cfg-file-read.c new file mode 100644 index 000000000000..c808fb2747f9 --- /dev/null +++ b/tools/coresight/coresight-cfg-file-read.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020-2022 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "coresight-config-file.h" +#include "coresight-config-uapi.h" + +/* + * tool to read and print a generated configuration + * re-uses the read code source from the driver. + */ + +static void validate_config_name(const char *name) +{ + int i, len = strlen(name); + + for (i = 0; i < len; i++) { + if (!isalnum(name[i]) && !(name[i] == '_')) { + printf("\n************************************************\n"); + printf("ERROR: Configuration name %s invalid character(s)\n", name); + printf(" : must contain only alphanumeric and _ only\n"); + printf("************************************************\n"); + } + } +} + +static void print_configs(struct cscfg_fs_load_descs *load_descs) +{ + struct cscfg_config_desc *config_desc; + int i, j, p, cfg_idx = 0; + + config_desc = load_descs->config_descs[cfg_idx]; + if (!config_desc) { + printf("File contains no configurations.\n\n"); + return; + } + + while (config_desc) { + printf("Configuration %d\nName:- %s\n", cfg_idx + 1, config_desc->name); + validate_config_name(config_desc->name); + printf("Description:-\n%s\n", config_desc->description); + printf("Uses %d features:-\n", config_desc->nr_feat_refs); + for (i = 0; i < config_desc->nr_feat_refs; i++) + printf("Feature-%d: %s\n", i + 1, config_desc->feat_ref_names[i]); + + printf("\nProvides %d sets of preset values, %d presets per set\n", + config_desc->nr_presets, config_desc->nr_total_params); + if (config_desc->nr_presets) { + for (i = 0; i < config_desc->nr_presets; i++) { + printf("set[%d]: ", i); + for (j = 0; j < config_desc->nr_total_params; j++) { + p = (i * config_desc->nr_total_params) + j; + printf("0x%lx, ", config_desc->presets[p]); + } + printf("\n"); + } + } + printf("\n============================================\n"); + cfg_idx++; + config_desc = load_descs->config_descs[cfg_idx]; + } +} + +static void print_reg_type_info(u8 type) +{ + if (type & CS_CFG_REG_TYPE_STD) + printf("std_reg "); + if (type & CS_CFG_REG_TYPE_RESOURCE) + printf("resource "); + if (type & CS_CFG_REG_TYPE_VAL_PARAM) + printf("param_index "); + if (type & CS_CFG_REG_TYPE_VAL_64BIT) + printf("64_bit "); + else + printf("32_bit "); + if (type & CS_CFG_REG_TYPE_VAL_MASK) + printf("masked "); + if (type & CS_CFG_REG_TYPE_VAL_SAVE) + printf("save_on_disable "); + +} + +static void print_regs(int nr, struct cscfg_regval_desc *regs_desc_array) +{ + int i; + struct cscfg_regval_desc *reg_desc; + u8 type; + u16 offset; + u16 info; + + for (i = 0; i < nr; i++) { + reg_desc = ®s_desc_array[i]; + type = (u8)reg_desc->type; + offset = (u16)reg_desc->offset; + info = (u16)reg_desc->hw_info; + + printf("Reg(%d): Type 0x%x: ", i, type); + print_reg_type_info(type); + printf("\nOffset: 0x%03x; HW Info: 0x%03x\n", offset, info); + printf("Value: "); + if (type & CS_CFG_REG_TYPE_VAL_64BIT) + printf("0x%lx\n", reg_desc->val64); + else if (type & CS_CFG_REG_TYPE_VAL_PARAM) { + printf("param(%d) ", reg_desc->param_idx); + if (type & (CS_CFG_REG_TYPE_VAL_MASK)) + printf(" mask: 0x%x", reg_desc->mask32); + printf("\n"); + } else { + printf("0x%x ", reg_desc->val32); + if (type & (CS_CFG_REG_TYPE_VAL_MASK)) + printf(" mask: 0x%x", reg_desc->mask32); + printf("\n"); + } + } +} + +static void print_params(int nr, struct cscfg_parameter_desc *params_desc) +{ + int i; + + for (i = 0; i < nr; i++) + printf("Param(%d) : %s; Init value 0x%lx\n", i, + params_desc[i].name, params_desc[i].value); +} + +static void print_features(struct cscfg_fs_load_descs *load_descs) +{ + struct cscfg_feature_desc *feat_desc = 0; + int idx = 0; + + feat_desc = load_descs->feat_descs[idx]; + if (!feat_desc) { + printf("File contains no features\n\n"); + return; + } + + while (feat_desc) { + printf("Feature %d\nName:- %s\n\n", idx + 1, feat_desc->name); + printf("Description:- %s\n", feat_desc->description); + printf("Match flags: 0x%x\n", feat_desc->match_flags); + printf("\nNumber of Paraneters: %d\n", feat_desc->nr_params); + if (feat_desc->nr_params) + print_params(feat_desc->nr_params, feat_desc->params_desc); + printf("\nNumber 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"); + printf("\n============================================\n\n"); + + + /* need a filename */ + if (argc <= 1) { + printf("Please provide filename on command line\n"); + return -EINVAL; + } + + /* open file and read into the buffer. */ + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + printf("Error opening file %s\n", argv[1]); + return -EINVAL; + } + + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + rewind(fp); + if (fsize > CSCFG_FILE_MAXSIZE) { + printf("Error: Input file too large."); + fclose(fp); + return -EINVAL; + } + err = fread(buffer, sizeof(u8), fsize, fp); + fclose(fp); + + if (err < fsize) { + printf("Error reading file %s\n", argv[1]); + return -EINVAL; + } + + /* allocate the descriptor structures to be populated by read operation */ + load_descs = malloc(sizeof(struct cscfg_fs_load_descs)); + if (!load_descs) { + printf("Error allocating load descs structure.\n"); + return -ENOMEM; + } + + /* read the buffer and create the configuration and feature structures */ + err = cscfg_file_read_buffer(buffer, fsize, load_descs); + if (err) { + printf("Error reading configuration file\n"); + goto exit_free_mem; + } + + /* print the contents of the structures */ + print_configs(load_descs); + print_features(load_descs); + +exit_free_mem: + cscfg_file_free_load_descs(load_descs); + free(load_descs); + return err; +} diff --git a/tools/coresight/coresight-config-uapi.h b/tools/coresight/coresight-config-uapi.h new file mode 100644 index 000000000000..d051c01ea982 --- /dev/null +++ b/tools/coresight/coresight-config-uapi.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CORESIGHT_CONFIG_UAPI_H +#define _CORESIGHT_CORESIGHT_CONFIG_UAPI_H + +#include +#include + +#include "coresight-config.h" + +/* + * Userspace versions of the configuration and feature descriptors. + * Used in the tools/coresight programs. + * + * Compatible with structures in coresight-config.h for use in + * coresight-config-file.c common reader source file. + */ + +/** + * Device feature descriptor - combination of registers and parameters to + * program a device to implement a specific complex function. + * + * UAPI version - removed kernel constructs. + * + * @name: feature name. + * @description: brief description of the feature. + * @match_flags: matching information if loading into a device + * @nr_params: number of parameters used. + * @params_desc: array of parameters used. + * @nr_regs: number of registers used. + * @regs_desc: array of registers used. + */ +struct cscfg_feature_desc { + const char *name; + const char *description; + u32 match_flags; + int nr_params; + struct cscfg_parameter_desc *params_desc; + int nr_regs; + struct cscfg_regval_desc *regs_desc; +}; + +/** + * Configuration descriptor - describes selectable system configuration. + * + * A configuration describes device features in use, and may provide preset + * values for the parameters in those features. + * + * A single set of presets is the sum of the parameters declared by + * all the features in use - this value is @nr_total_params. + * + * UAPI version - removed kernel constructs. + * + * @name: name of the configuration - used for selection. + * @description: description of the purpose of the configuration. + * @nr_feat_refs: Number of features used in this configuration. + * @feat_ref_names: references to features used in this configuration. + * @nr_presets: Number of sets of presets supplied by this configuration. + * @nr_total_params: Sum of all parameters declared by used features + * @presets: Array of preset values. + */ +struct cscfg_config_desc { + const char *name; + const char *description; + int nr_feat_refs; + const char **feat_ref_names; + int nr_presets; + int nr_total_params; + const u64 *presets; /* nr_presets * nr_total_params */ +}; + +#endif /* _CORESIGHT_CORESIGHT_CONFIG_UAPI_H */ From patchwork Mon Jul 4 15:42:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905534 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 897CCC433EF for ; Mon, 4 Jul 2022 15:45:22 +0000 (UTC) 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=4f9zADPKO5i5D5dHSy37yrhMEz0owjnTjvo2VC7voB0=; b=oC/lKuMHaI7HvE UrTbUm9Qf8dEaeSey/oLquHowYkt0QnzlZLo7/x4Onk+rk6Cxmh6VT6NQdUa3n8vF+IlCq5wezt16 5epakqEARlPIz/3rWrMVxRwKR2bVs36QpB9pwzOAQD3PevTbU6QYraB3xxmvwhE2mtiWQ2W+uDxug U28PRnZf1o0S0U0Q2vDumNPpoOiNeeq6o6lSyK85E1pHovpve6j+WvzlaG6soR4GUvaP3FhOMboyz Ydlji2SW9UQgC6PpCqMn+NwvufzpB3orncqEv5028g2N4K3U8/ZftkWMHAZdcvxbpRFWiTYgqD3bg tqW2b63FUrfCmqTG15Cg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OFC-009mEw-0W; Mon, 04 Jul 2022 15:44:14 +0000 Received: from mail-wm1-x334.google.com ([2a00:1450:4864:20::334]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OE0-009llB-KX for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:43:02 +0000 Received: by mail-wm1-x334.google.com with SMTP id f190so5618132wma.5 for ; Mon, 04 Jul 2022 08:42:58 -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=20URghUEhnd48vVWNIo4NcdPqwWP3OApoVFQSqBizbk=; b=aI3lRra6RdQgQW5qVEVV5qlEQowVjQERD7fgGhTtzuE/AmB3oMX+os4xQAq386fKru XFlR4A+6LCUB/3OaOFjnlTkqeI0S4M9m/ktLBvCfB7Y8rbT7ZHIBb8UgUeGm1gWgH6vj N6W4bgFtoleVPetp9BFJmBq2/7CO1DfIO2SHjVIAfo8SVErRET/CKirJSEyDXTP47Nu/ MbW0yRNIOCIIncUQBpnKT3AKQHm9DN78X9rQAppvrpmScv1tSjAk2wpoZ/ztbaT5KYFb OwU62eZcvq/RA1AlMNghv8jnZhTVuvx1Q1DpllIW4il0Ps37GQFka58CiZPn7CI6BCoo U6Fg== 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=20URghUEhnd48vVWNIo4NcdPqwWP3OApoVFQSqBizbk=; b=ug45GRCl4Ymwi4nf+MBtBCl/cWEiG3yu20QHT2uFtpd/o48u60p6lYAGxmH96XBTFN jVuUY8T/tkRuuGbXRKH6kggo/hqPjMDLz+vl3V8t32I2NbYXUHMSjNvMSqN+wxNPt69g yx8r7/KyXPdBRbxULM9KJVGkduNQEOtlZO3UgfCwlhHrsmxY3AwozfjJBr5zwLoYCOd0 WRbJSA13C1G3d57vTv4vQLOlWBNgP7ugl+xHRgy6qQIzrLcloQNXUxfdE+q1Wyvf8Ya7 lIYPtuQRBWuqtREPCQ0ij/P3j4X7J/CegseGJ/pg+O1R+crTpF+8yhWajOivzUek7r3o Tflg== X-Gm-Message-State: AJIora869iLS7VCpJ09Mc/IAtKbj3PMwGw+zch7XvNllQjiRSJeVV0U+ wJ2IAV1JWksSfgACMt0btKW97Ed32vyqAQ== X-Google-Smtp-Source: AGRyM1vUjayhhF9itLimifgtEv6TFBAqsWs030GZ+veu/QlNS9RMYOI8pn0VnSnKvh+Jcj/nrXmwhw== X-Received: by 2002:a05:600c:3592:b0:3a0:4c17:5ec1 with SMTP id p18-20020a05600c359200b003a04c175ec1mr33230222wmq.4.1656949376903; Mon, 04 Jul 2022 08:42:56 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:56 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach , Jonathan Corbet , linux-doc@vger.kernel.org Subject: [PATCH v4 6/7] Documentation: coresight: docs for config load via configfs Date: Mon, 4 Jul 2022 16:42:48 +0100 Message-Id: <20220704154249.11501-7-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084300_765083_466B1BA0 X-CRM114-Status: GOOD ( 30.55 ) 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 documentation covering the configfs updates that allow binary configuration files to be loaded and unloaded via configfs, along with the demonstration programs in samples. Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Signed-off-by: Mike Leach --- .../trace/coresight/coresight-config.rst | 202 +++++++++++++++++- 1 file changed, 195 insertions(+), 7 deletions(-) diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst index 6d5ffa6f7347..109053eb1b93 100644 --- a/Documentation/trace/coresight/coresight-config.rst +++ b/Documentation/trace/coresight/coresight-config.rst @@ -141,11 +141,11 @@ Mount configfs as normal and the 'cs-syscfg' subsystem will appear:: $ ls /config cs-syscfg stp-policy -This has two sub-directories:: +This has two sub-directories, with the load and unload attribute files:: $ cd cs-syscfg/ $ ls - configurations features + configurations features load unload The system has the configuration 'autofdo' built in. It may be examined as follows:: @@ -278,9 +278,16 @@ 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. -An example of a custom configuration is found in ./samples/coresight. +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. + + +Using a Loadable Module +----------------------- This creates a new configuration that uses the existing built in strobing feature, but provides a different set of presets. @@ -289,6 +296,187 @@ 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. + +An example of a custom configuration module is found in './samples/coresight'. + +Using a Binary Configuration File +--------------------------------- + +The './tools/coresight' directory contains example programs to generate and +read and print binary configuration files. + +Building the tools creates the 'coresight-cfg-file-gen' 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-example1.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. Alternatively, addition examples can be added to the +'coresight-cfg-file-gen' program:: + + $ ./coresight-cfg-file-gen + Coresight Configuration file Generator + + Generating example1 example + Generating example2 example + +The program 'coresight-cfg-file-read' can read back and print a configuration +binary. This is built using the file reader from the driver code +(coresight-config-file.c), which is copied over into './tools/coresight' at +build time.:: + + ./coresight-cfg-file-read example1.cscfg + CoreSight Configuration file reader + ============================================ + + Configuration 1 + Name:- autofdo3 + Description:- + Setup ETMs with strobing for autofdo + Supplied presets allow experimentation with mark-space ratio for various loads + + Uses 1 features:- + Feature-1: strobing + + Provides 4 sets of preset values, 2 presets per set + set[0]: 0x7d0, 0x64, + set[1]: 0x7d0, 0x3e8, + set[2]: 0x7d0, 0x1388, + set[3]: 0x7d0, 0x2710, + + ============================================ + File contains no features + +There are additional attributes in the cs-syscfg directory - load and +unload 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 features load unload + $ cat example1.cscfg > /config/cs-syscfg/load + $ ls /config/cs-syscfg/configurations/ + autofdo autofdo3 + +To unload, use the same file in the unload attribute:: + + $ cat example1.cscfg > /config/cs-syscfg/unload + ls /config/cs-syscfg/configurations/ + autofdo + + + +Binary Configuration File Format +-------------------------------- + +The file format is defined in the source file **coresight-config-file.h** + +The source reader and generator examples produce a binary of this format. + +This arrangement is reproduced below:- + +Overall File structure +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + [cscfg_file_header] // Mandatory + [CONFIG_ELEM]* // Optional - multiple, defined by cscfg_file_header.nr_configs + [FEATURE_ELEM]* // Optional - multiple, defined by cscfg_file_header.nr_features + +File is invalid if both [CONFIG_ELEM] and [FEATURE_ELEM] are omitted. + +A file that contains only [FEATURE_ELEM] may be loaded, and the features used +by subsequently loaded files with [CONFIG_ELEM] elements. + +Element Name Strings +~~~~~~~~~~~~~~~~~~~~ + +Configuration name strings are required to consist of alphanumeric characters and '_' only. Other special characters are not permitted. + +:: + my_config_2 // is a valid name. + this-bad-config#5 // this will not work + +This is in order to comply with the requirements of the perf command line. + +It is recommended that Feature and Parameter names use the same convention to allow for future enhancements to the command line syntax. + +CONFIG_ELEM element +~~~~~~~~~~~~~~~~~~~ + +:: + + [cscfg_file_elem_header] // header length value to end of feature strings. + [cscfg_file_elem_str] // name of the configuration. + // (see element string name requirements) + [cscfg_file_elem_str] // description of configuration. + [u16 value](nr_presets) // number of defined sets presets values. + [u32 value](nr_total_params) // total parameters defined by all used features. + [u16 value](nr_feat_refs) // number of features referenced by the configuration + [u64 values] * (nr_presets * nr_total_params) // the preset values. + [cscfg_file_elem_str] * (nr_feat_refs) // names of features used in the configurations. + +FEATURE_ELEM element +~~~~~~~~~~~~~~~~~~~~ + +:: + + [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) // flags to associate the feature with a device. + [u16 value](nr_regs) // number of registers. + [u16 value](nr_params) // number of parameters. + [cscfg_regval_desc struct] * (nr_regs) // register definitions + [PARAM_ELEM] * (nr_params) // parameters definitions + +PARAM_ELEM element +~~~~~~~~~~~~~~~~~~ + +:: + + [cscfg_file_elem_str] // parameter name. + [u64 value](param_value) // initial value. + +Additional definitions. +~~~~~~~~~~~~~~~~~~~~~~~ + +The following structures are defined in **coresight-config-file.h** + + * **struct cscfg_file_header** : This structure contains an initial magic number, the total + length of the file, and the number of configurations and features in the file. + * **struct cscfg_file_elem_header**: This defines the total length and type of a CONFIG_ELEM + or a FEATURE_ELEM. + * **struct cscfg_file_elem_str**: This defines a string and its length. + +The magic number in cscfg_file_header is defined as two bitfields:: + + [31:8] Fixed magic number to identify file type. + [7:0] Current file format version. + +The following defines determine the maximum overall file size and maximum individual +string size:: + + CSCFG_FILE_MAXSIZE // maximum overall file size. + CSCFG_FILE_STR_MAXSIZE // maximum individual string size. + +Load Dependencies. +~~~~~~~~~~~~~~~~~~ + +Files may be unloaded only in the strict reverse order of loading. This is enforced by the +configuration system. + +This is to ensure that any load dependencies are maintained. + +A configuration file that contains a CONFIG_ELEM that references named features "feat_A" and "feat_B" will load only if either:- +a) "feat_A" and/or "feat_B" has been loaded previously, or are present as built-in / module loaded features. +b) "feat_A" and/or "feat_B" are declared as FEAT_ELEM in the same file as the CONFIG_ELEM. + +Files that contain features or configurations with the same names as those already loaded will fail to load. From patchwork Mon Jul 4 15:42:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12905535 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 9A786C433EF for ; Mon, 4 Jul 2022 15:45:51 +0000 (UTC) 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=4pBHwwGROL+xG5BwSu45ntdnmH68CcKGQrJnrOchLb8=; b=Mn3701jXV328t9 I7ns1452L1SsHs0Y03BeoMjANXAw39YwDmEmeszy6NFBH1DRbv7FgS3rkdg/8qdnGg+MDfoD7Ac/H 3EPKrCSjklp4LPhgpJl3XhylvQQs0ov8s75hPkMksl9rpRnfdL/ulgaH7iT8YT/i9ZNABxdUJuhlA hdO0BhUxlj2kA3oyBkExXsXzJf4mdiXVTiqotlW1qUQpALgMEGp4h0daSGCBicz3hXeXn5nCoqfdK ptQ1qt5gxDv7G2aWza5OndGg74O7E+XVZ56RRmG8B2Cg4edHKigz+kW2MrBl7OmHCV4/2RHsrqrdb 7aWlKA9Ukg1aved3J3tg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OFV-009mPC-Pt; Mon, 04 Jul 2022 15:44:33 +0000 Received: from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1o8OE1-009lla-Cm for linux-arm-kernel@lists.infradead.org; Mon, 04 Jul 2022 15:43:03 +0000 Received: by mail-wr1-x42c.google.com with SMTP id q9so14020924wrd.8 for ; Mon, 04 Jul 2022 08:42:58 -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=46SlzW74GIiHvhVWuQrLRhWnlm69Aurjg5UhCuYh8/k=; b=tJ2R8cV0GXu4lJJxtQOskBniE5SCBOJmzYLF6g+YoBM/ND2oaDYMEI12eU1iSR9CB4 kvtjlQ03jzaTxrEoYN5/aNfDr9XavyViWb20b4VFUAS1XHWfqzfjyD3z4r1SOkuUNaRa bUOxuErvNKBqRfHNwhbnwp/3s6uOUsjcdmyHa0gEXTAKzsdvaP4kl1mQGd23V9us2mVH EuT1SuhwPAymWdXQk6BOZS0MMf9sNso2+l5EI3Z2JSeaGtNQguYinMWTXHrrB61ExiTv qh89lVbfcWz3YjCTsfxfOmEB52+iQwYUyRvDWrFUXJAv3tszFTd7YeARbSapGoQsKudK /LBA== 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=46SlzW74GIiHvhVWuQrLRhWnlm69Aurjg5UhCuYh8/k=; b=HDB5G3rwvrGtvUD0HXgsMXfsG1OYYVNSohb6zdBwBFJDW3hAmRvELB6uVGvN++OSL4 pIbhdhEHw9Ksste9UZXZGTFmm7eRxdjrTu0dWKmGY4V/9DEUaqsWZ4gSxygx1A8G2zJy cZCDkyNka572Z3oOHWffl3cOvPfyjinHfmYv7Yii08Wlp83LMo4bYdC3JgNlBGFVKA7G +u1zhzz0R+O2hQkUX/RHOoxthIeauQqAMrTE3sTrqqRNFzzsEWpV1N8Ms2LKf/WI+UdL IpvJQ+ksy9qgxYXl+bL1Tnr0Mhm3ki7G2XT6PYm/uF8RCkyuG9slSwjRkiCEIz8QqQ8W Qr3Q== X-Gm-Message-State: AJIora9/j7VxirHcXaHJwriSsnsypR63Ccp6vZxl3wpHkL1OOIBvGmgr ksv6buuAkgTngAK/ncn5OD7mwyDq57c6bw== X-Google-Smtp-Source: AGRyM1s/hggudqgbsLZO5A9418cfpoWQrC3JDVJB1TU5WdQcG/6N+DuyzVdbMA7ftjSlm+QVDzET6g== X-Received: by 2002:adf:d1c2:0:b0:21b:e465:1e36 with SMTP id b2-20020adfd1c2000000b0021be4651e36mr28864769wrd.271.1656949377791; Mon, 04 Jul 2022 08:42:57 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:a9e8:9fdd:fa2d:1c72]) by smtp.gmail.com with ESMTPSA id j6-20020adfff86000000b0021d6b851ca1sm2763749wrr.111.2022.07.04.08.42.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 08:42:57 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, linux-kernel@vger.kernel.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, acme@kernel.org, james.clark@arm.com, Mike Leach , Joel Becker , Christoph Hellwig Subject: [PATCH v4 7/7] configfs: Fix LOCKDEP nesting issues with fragment semaphores Date: Mon, 4 Jul 2022 16:42:49 +0100 Message-Id: <20220704154249.11501-8-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220704154249.11501-1-mike.leach@linaro.org> References: <20220704154249.11501-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220704_084301_481581_B821802B X-CRM114-Status: GOOD ( 22.82 ) 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 CoreSight uses configfs to represent the user interface to programmed configurations, which can be loaded and unloaded dynamically via configfs. These add and remove configurations using register/unregister group calls. It has been found that if CONFIG_LOCKDEP is enabled, then it appears to be confused by the nesting inherent in the fragment semaphores used by groups and the underlying subsystem. This patch sets up a mechanism to use separate classes for the fragment semaphores, in a similar way to that already in place to fix nesting issues with the i_mutexes. Cc: Joel Becker Cc: Christoph Hellwig Signed-off-by: Mike Leach --- fs/configfs/configfs_internal.h | 3 +++ fs/configfs/dir.c | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index c0395363eab9..736c74ec4b7a 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h @@ -22,6 +22,9 @@ struct configfs_fragment { atomic_t frag_count; struct rw_semaphore frag_sem; bool frag_dead; +#ifdef CONFIG_LOCKDEP + int frag_depth; +#endif }; void put_fragment(struct configfs_fragment *); diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index d1f9d2632202..6ecd8961afc3 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -133,6 +133,41 @@ configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd) sd->s_depth = -1; } +/* fragment semaphore needs some lockdep handling */ +static struct lock_class_key default_frag_class[MAX_LOCK_DEPTH]; + +/* + * Set the lockdep depth for a new fragment based on the parent frag depth. + * Called from register_subsystem() with NULL parent group to set root subsystem + * depth which defaults to 0 in a new fragment, and from register_group() with the + * parent group to set a new group fragment based on the parent fragment depth. + * + * Prevents lockdep getting upset on the unregister_group() call if it cannot + * understand the hierarchy of fragments. + */ +static void configfs_adjust_frag_depth(struct configfs_fragment *frag, + struct config_group *parent_group) +{ + struct configfs_dirent *parent_dirent; + + if (parent_group) { + // find parent frag + parent_dirent = parent_group->cg_item.ci_dentry->d_fsdata; + frag->frag_depth = parent_dirent->s_frag->frag_depth + 1; + } + + if (frag->frag_depth < ARRAY_SIZE(default_frag_class)) { + lockdep_set_class(&frag->frag_sem, + &default_frag_class[frag->frag_depth]); + } else { + /* + * In practice the maximum level of locking depth is + * already reached. Just inform about possible reasons. + */ + pr_info("Too many levels of fragments for the locking correctness validator.\n"); + } +} + #else /* CONFIG_LOCKDEP */ static void configfs_init_dirent_depth(struct configfs_dirent *sd) @@ -154,6 +189,11 @@ configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd) { } +static void configfs_adjust_frag_depth(struct configfs_fragment *frag, + struct config_group *parent_group) +{ +} + #endif /* CONFIG_LOCKDEP */ static struct configfs_fragment *new_fragment(void) @@ -165,6 +205,9 @@ static struct configfs_fragment *new_fragment(void) atomic_set(&p->frag_count, 1); init_rwsem(&p->frag_sem); p->frag_dead = false; +#ifdef CONFIG_LOCKDEP + p->frag_depth = 0; +#endif } return p; } @@ -1742,6 +1785,7 @@ int configfs_register_group(struct config_group *parent_group, parent = parent_group->cg_item.ci_dentry; inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); + configfs_adjust_frag_depth(frag, parent_group); ret = create_default_group(parent_group, group, frag); if (ret) goto err_out; @@ -1872,6 +1916,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) mutex_unlock(&configfs_subsystem_mutex); inode_lock_nested(d_inode(root), I_MUTEX_PARENT); + configfs_adjust_frag_depth(frag, NULL); err = -ENOMEM; dentry = d_alloc_name(root, group->cg_item.ci_name);