From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C480B33CEBB; Thu, 7 May 2026 06:37:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135864; cv=none; b=gpZX788+MiwmpFW0Pdoug911W+uE9ZFiLtR1rOfql9T30YI6nJZ2ohD3YPlu0q75XoZHmAMN3IYQXa2/zr4fnurkI8d1uh+uwFeIg1QftJh+ZLmNRflmRFEU0b/TJdyCSWDXxV7Wg6uUztCA1m5Al59xcEmh91H7j10WPjifcAI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135864; c=relaxed/simple; bh=nfa03i+Qj4pJ1N+xjnYP3nk1MAeudgQ/KvyaeooiSvs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NwBEMAEJCSwJ9JiK4gpQZNirIrzmVsbyNu3Z5WKaSnKqUajjsQwdpsLPnsel2hXtJRWI3M0LXSdIz0t/Ecw/U0WyNzJOy5Nf8LgQxmVth6qVIaZ7gGerG+cZQHplomDceUr6+PCT+EwMBnDCL1RIPJpsgMPFQIdePefJhQFYNyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=QAaXfvgf; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="QAaXfvgf" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=tavSIncRGrNJHQl5vLDBA/vQ3CjL1RwZuizxVlTGWb4=; b=QAaXfvgfLZBcV5BuOemObCVuRQ+f+oq8VPQg5mps2gajMvSf9mdtLduIsVnJfz+o4v/Nr1phE AUWDc1lq1tm8/oggeKyIt97d0NaMkNg9NlRQsqwuswGsrdWXu2kCj5/gkZjoB+3gE9yelqv/2rZ vdelzoC3s8JiXrWP6eVM0JM= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4gB2SS3HJYzpT04; Thu, 7 May 2026 14:30:48 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 310A020226; Thu, 7 May 2026 14:37:39 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:38 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:38 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 1/7] perf stat: Check color's length instead of the pointer Date: Thu, 7 May 2026 14:37:31 +0800 Message-ID: <20260507063737.3542950-2-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" Color string returned by metric_threshold_classify__color() is never NULL, check the presence of *color will always return true. Fix this by change the checks against length of *color. Fixes: 37b77ae95416 ("perf stat: Change color to threshold in print_metric") Signed-off-by: Yushan Wang Reviewed-by: Ian Rogers --- tools/perf/builtin-script.c | 2 +- tools/perf/util/stat-display.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c8ac9f01a36b..58cd5cd377a6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2111,7 +2111,7 @@ static void script_print_metric(struct perf_stat_conf= ig *config __maybe_unused, perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel, PERF_RECORD_SAMPLE, mctx->fp); fputs("\tmetric: ", mctx->fp); - if (color) + if (strlen(color)) color_fprintf(mctx->fp, color, fmt, val); else printf(fmt, val); diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 993f4c4b8f44..74cba80c24b0 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -474,7 +474,7 @@ static void print_metric_std(struct perf_stat_config *c= onfig, do_new_line_std(config, os); =20 n =3D fprintf(out, " # "); - if (color) + if (strlen(color)) n +=3D color_fprintf(out, color, fmt, val); else n +=3D fprintf(out, fmt, val); @@ -607,7 +607,7 @@ static void print_metric_only(struct perf_stat_config *= config, if (mlen < strlen(unit)) mlen =3D strlen(unit) + 1; =20 - if (color) + if (strlen(color)) mlen +=3D strlen(color) + sizeof(PERF_COLOR_RESET) - 1; =20 color_snprintf(str, sizeof(str), color ?: "", fmt ?: "", val); --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C475940DFA3; Thu, 7 May 2026 06:37:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135865; cv=none; b=TlnsR7BZi0KGcarQ4EIKWzxbnFS0kbCkmLW3LDWiTymWiGfrACIJ8VoS9a7TxQfElzm0hufPQkEcbDIAwfRNy/n8X4GE2vC/dm9tX4wRZX89M229g0yOk7VeFj+ADHVEWfS0fHb/n2IY7q4vSJGGZ8yVWaIkWW1rGmuKiLVYl0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135865; c=relaxed/simple; bh=BA3yfDoTE56T6V36c7TmPzfWAPRNU4dgZGsNcEGGPq0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qoUR7YoRGcql8uzfgB1tH5Ty+L+7Ivcw+ld22xDVtCOoqR/yXZBHggNANci0R4B6G0vnw0rUyMoURw4z5/3YZsTwg5pghNMlJc4mrKpmDLCT9FbizTg7rfvtfahsGzB0YBGWSAcKpkMLapwrCdzTBZKhnQSL8Suao6+KaizWA8c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=SF/6Bwyt; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="SF/6Bwyt" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=7vylduoRqDFT0UfMrXqN7Cq3Y6aHaFoZdwPyFBkNlNc=; b=SF/6BwytKNbEng1rjg9RClqKxkiniUMzMR7duX9fWb1/Z4m8nFu4+Q6D1ixRo24BKb5lmMXah Qfi5iqGThupAa5s9yDTunjXoN2Hz7myl89mOhD2ebidVKp/N5PWuMvjeKQnBBD5dXUXR1OIiqP5 MgKI5fAyKsE1XgOQaSgXJ1o= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4gB2ST0t05zpSx8; Thu, 7 May 2026 14:30:49 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id D10AC40561; Thu, 7 May 2026 14:37:39 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:39 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:38 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 2/7] perf stat: Save unnecessary print_metric() call Date: Thu, 7 May 2026 14:37:32 +0800 Message-ID: <20260507063737.3542950-3-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" The patch listed under Fixes removed the other branch of iostat_run, and changed num to 0 since it is the default behavior of it. But during iostat_run, default value 1 of num is required to avoid print_metric() call later. Set num as 1 to avoid redundant print_metric() call that causes unaligned blank printed. Before this patch: root@localhost$ ./perf stat --iostat=3D0000:20:0f.0 --timeout 100 Performance counter stats for 'system wide': port Inbound MWR(MB) Inbound MRD(MB) Inbound CPL= (MB) Outbound MWR(MB) Outbound MRD(MB) Outbound CPL(MB) 0000:20:0f.0 0.00 0.00= 0.00 = 0.00 0.00 0.01 0.100138030 seconds time elapsed After this patch: root@localhost$ ./perf stat --iostat=3D0000:20:0f.0 --timeout 100 Performance counter stats for 'system wide': port Inbound MWR(MB) Inbound MRD(MB) Inbound CPL= (MB) Outbound MWR(MB) Outbound MRD(MB) Outbound CPL(MB) 0000:20:0f.0 0.00 0.00 0.00= 0.00 0.00 0.01 0.100127590 seconds time elapsed Fixes: b71f46a6a708 ("perf stat: Remove hard coded shadow metrics") Signed-off-by: Yushan Wang Reviewed-by: Ian Rogers --- tools/perf/util/stat-shadow.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index bc2d44df7baf..0056444523d6 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -326,8 +326,10 @@ void perf_stat__print_shadow_stats(struct perf_stat_co= nfig *config, void *ctxp =3D out->ctx; int num =3D 0; =20 - if (config->iostat_run) + if (config->iostat_run) { iostat_print_metric(config, evsel, out); + num =3D 1; + } =20 perf_stat__print_shadow_stats_metricgroup(config, evsel, aggr_idx, &num, NULL, out); --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout12.his.huawei.com (canpmsgout12.his.huawei.com [113.46.200.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3B1033CEA9; Thu, 7 May 2026 06:37:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135877; cv=none; b=tSAmsHO7X4qa1grkuWwyiSQrij1et7any6U5m7g/C6OK40/JN+yCeuPE+bGth5MMWU3Vj7BnqtKFjBzP8Do2keiMyqdmT+4Sb6QIZZjDoPm/4Cen204eo0uqGCVM7SYAa4O/X0n3J4xm/8aNgXmWESK3Siz/JqeMzL0YCMVWwHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135877; c=relaxed/simple; bh=q6OkRdzLG4KekcM1Oi9hSQ1rdfNRo5m8Ds0bfJicBIY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZzE0bU2ecfm8RSvCQgUDd3uGbkqW6BdWJ/4/FQXw2rPMjEXi7+KYwi1PlOwq4jG1KDC3D5ifG50aSViIrhm7dvR5sBpjpU7cCoh0wZsac8eEjMdhPpfniombYWFXmNSVC5CzzMbIX1OgBsmX9B7g2Q6KRuPpT45NaDcu3WlADDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=4m+577lW; arc=none smtp.client-ip=113.46.200.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="4m+577lW" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=GGcKzy66/ad1dSIdtq5qJ/h9XgDG1eOVLqadNHxudqA=; b=4m+577lWR5gkOuN+DcEO0u76lmZh/FEg8XWwUCRBNLHe3+Fkr/jMFI6wBZjVxuRGyEGEV2i0y t11UmY0UQkaKwhTFfRv8DLGWCArHAYNvBzyy9woAwTdNzaskAC3aEvMaCyF9FrRjvWKE8ie5vZ8 mwEIJATP2BBh0h+2CzcX2co= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4gB2SB1sn7znTV5; Thu, 7 May 2026 14:30:34 +0800 (CST) Received: from dggemv705-chm.china.huawei.com (unknown [10.3.19.32]) by mail.maildlp.com (Postfix) with ESMTPS id 89E5F402AB; Thu, 7 May 2026 14:37:40 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv705-chm.china.huawei.com (10.3.19.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:40 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:39 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 3/7] perf-x86: iostat: Move iostat arch-specific implementation to util Date: Thu, 7 May 2026 14:37:33 +0800 Message-ID: <20260507063737.3542950-4-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" To support cross-platform iostat capabilities, like record/report on different platforms, architecture-specific implementation of iostat should be moved out of arch directory to get built. Build scripts are changed accordingly. Signed-off-by: Yushan Wang --- tools/perf/arch/x86/util/Build | 1 - tools/perf/util/Build | 1 + tools/perf/{arch/x86/util/iostat.c =3D> util/x86-iostat.c} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename tools/perf/{arch/x86/util/iostat.c =3D> util/x86-iostat.c} (100%) diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index b94c91984c66..358541beaa0f 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -7,7 +7,6 @@ perf-util-y +=3D event.o perf-util-y +=3D evlist.o perf-util-y +=3D mem-events.o perf-util-y +=3D evsel.o -perf-util-y +=3D iostat.o =20 perf-util-$(CONFIG_LOCAL_LIBUNWIND) +=3D unwind-libunwind.o =20 diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 70cc91d00804..c7e5ada3800d 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -127,6 +127,7 @@ perf-util-y +=3D thread-stack.o perf-util-y +=3D spark.o perf-util-y +=3D topdown.o perf-util-y +=3D iostat.o +perf-util-y +=3D x86-iostat.o perf-util-y +=3D stream.o perf-util-$(CONFIG_LIBTRACEEVENT) +=3D kvm-stat.o perf-util-y +=3D kvm-stat-arch/ diff --git a/tools/perf/arch/x86/util/iostat.c b/tools/perf/util/x86-iostat= .c similarity index 100% rename from tools/perf/arch/x86/util/iostat.c rename to tools/perf/util/x86-iostat.c --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C68033F5BE; Thu, 7 May 2026 06:37:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135873; cv=none; b=YVDhbncKRfnHcXUr9DAfs2HuX6CO9DEAoiWETc3AjRJd7/XuBLdqSsrPNAs82xAb8J2CRxlbK47EK3OOfgBJs5lTCPEsv3zURvcdJN3RBPzK8GEMMF2bqgXmI5g/3Ug9oaPVWFxjGWahEA/mIAYXry3L3HhctVAK3+f/R/seYb0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135873; c=relaxed/simple; bh=1fdXuaEL7cj+fs1O7LyClBsePDWrL6Fv62mg0gLyK+A=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OpMPRznKB5m8B5wKdZF9UAwv4N8+tZIcMvv+YhTG9TrXnl+vJCnrL9e3bHwkiPP45HC4eblAag98YWBX4msjjcC+HolO7wcozMHRKJ8amy71CqCC9mMvTAfJT22wP2NvhEObAx6xAf60auylS24XAjozqCUZsi1g+CCX88BEPFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=3i51/4hv; arc=none smtp.client-ip=113.46.200.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="3i51/4hv" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=s+UPfLYxep2lFqvQU2QLO+VRgoTiunn3ERhHANe0PMk=; b=3i51/4hvx2/B2QTb3i5CkNCcIB6oIuZTRnVX6uzEdhuExpJ6tr5zJgrpZM5ofV7z4xnI6lkur O8oGRL7SfM17nPlAqG/QDB7FLSU5lHzay7C8DqznDQzUqFG9mi2kPte+mqVl2+vSEFuaaoZhduj YS/3QQ15jXJVwOxzGsW7EOY= Received: from mail.maildlp.com (unknown [172.19.162.144]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4gB2Sp57yGz1prPP; Thu, 7 May 2026 14:31:06 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 25ACF4056D; Thu, 7 May 2026 14:37:41 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:41 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:40 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 4/7] perf-x86: iostat: Change iostat_prefix() to static Date: Thu, 7 May 2026 14:37:34 +0800 Message-ID: <20260507063737.3542950-5-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" Change iostat_prefix() to static function, since it is not used outside. Signed-off-by: Yushan Wang Reviewed-by: Ian Rogers --- tools/perf/util/iostat.c | 7 ------ tools/perf/util/iostat.h | 2 -- tools/perf/util/x86-iostat.c | 44 ++++++++++++++++++------------------ 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/tools/perf/util/iostat.c b/tools/perf/util/iostat.c index b770bd473af7..a68ab100780d 100644 --- a/tools/perf/util/iostat.c +++ b/tools/perf/util/iostat.c @@ -37,13 +37,6 @@ __weak void iostat_print_metric(struct perf_stat_config = *config __maybe_unused, { } =20 -__weak void iostat_prefix(struct evlist *evlist __maybe_unused, - struct perf_stat_config *config __maybe_unused, - char *prefix __maybe_unused, - struct timespec *ts __maybe_unused) -{ -} - __weak void iostat_print_counters(struct evlist *evlist __maybe_unused, struct perf_stat_config *config __maybe_unused, struct timespec *ts __maybe_unused, diff --git a/tools/perf/util/iostat.h b/tools/perf/util/iostat.h index a4e7299c5c2f..820930a096d9 100644 --- a/tools/perf/util/iostat.h +++ b/tools/perf/util/iostat.h @@ -35,8 +35,6 @@ int iostat_parse(const struct option *opt, const char *st= r, int unset __maybe_unused); void iostat_list(struct evlist *evlist, struct perf_stat_config *config); void iostat_release(struct evlist *evlist); -void iostat_prefix(struct evlist *evlist, struct perf_stat_config *config, - char *prefix, struct timespec *ts); void iostat_print_header_prefix(struct perf_stat_config *config); void iostat_print_metric(struct perf_stat_config *config, struct evsel *ev= sel, struct perf_stat_output_ctx *out); diff --git a/tools/perf/util/x86-iostat.c b/tools/perf/util/x86-iostat.c index 7442a2cd87ed..f8d4c9718594 100644 --- a/tools/perf/util/x86-iostat.c +++ b/tools/perf/util/x86-iostat.c @@ -332,6 +332,28 @@ static int iostat_event_group(struct evlist *evl, return ret; } =20 +static void iostat_prefix(struct evlist *evlist, + struct perf_stat_config *config, + char *prefix, struct timespec *ts) +{ + struct iio_root_port *rp =3D evlist->selected->priv; + + if (rp) { + /* + * TODO: This is the incorrect format in JSON mode. + * See prepare_timestamp() + */ + if (ts) + sprintf(prefix, "%6lu.%09lu%s%04x:%02x%s", + ts->tv_sec, ts->tv_nsec, + config->csv_sep, rp->domain, rp->bus, + config->csv_sep); + else + sprintf(prefix, "%04x:%02x%s", rp->domain, rp->bus, + config->csv_sep); + } +} + int iostat_prepare(struct evlist *evlist, struct perf_stat_config *config) { if (evlist->core.nr_entries > 0) { @@ -396,28 +418,6 @@ void iostat_release(struct evlist *evlist) } } =20 -void iostat_prefix(struct evlist *evlist, - struct perf_stat_config *config, - char *prefix, struct timespec *ts) -{ - struct iio_root_port *rp =3D evlist->selected->priv; - - if (rp) { - /* - * TODO: This is the incorrect format in JSON mode. - * See prepare_timestamp() - */ - if (ts) - sprintf(prefix, "%6lu.%09lu%s%04x:%02x%s", - ts->tv_sec, ts->tv_nsec, - config->csv_sep, rp->domain, rp->bus, - config->csv_sep); - else - sprintf(prefix, "%04x:%02x%s", rp->domain, rp->bus, - config->csv_sep); - } -} - void iostat_print_header_prefix(struct perf_stat_config *config) { if (config->csv_output) --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9BA3032D7F8; Thu, 7 May 2026 06:37:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135865; cv=none; b=XALc8cAN3qT5T4m/hPGBgd7mSpSFPA2Vr4AU9U1EHONUH0yiKUVriSOcT4fUxPsYhOQ8ovzYnLQAsRFZmcFW9PoDhq6HhRlZkYVtBeHOTdGa3sPKbsov1Zxwp+wxCuSj258DFv4hCLh66KkLoyHQqOza75DJXqWqB/G0dQsEdZ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135865; c=relaxed/simple; bh=oojAeG5H3pW9Ppnf1YNd2kT7A7Xa313INUdoqNbpIRg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KiuCbr+qt9U5h4ppqyGAWzHJqlja5cFpChVsu+tm7KstAOkrjhOp8jqy4FIIKMdQg+JPdzeJd935Ue8HBAQBiDR6SNSMRfodzo1UVs+qSkc6egwstDo6/Tym1vlwHROI73EJB5r9v1Uv7fCXFrUCns3jodegSYqgSbQi0D2Muuc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=4T6e9NGJ; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="4T6e9NGJ" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=l16reIjru4M+K09e8ccjfVDCtpBwMJxYZ+RYe9nuL5g=; b=4T6e9NGJvAtkQ59NxHNjugt48JsLs2u8IcR5TDGTJmQx+KN2SNxSQKNVLzwlxZjD7Y0cj9ska Jd7Ps7aJ8jytyR16Jj+mLi5tri2L30Qzp3Q7L/i93Yu/PiSCUoHDdjUU2EHsd3L3tu5AEXWSB3j i4nhVRUFDcai3u8o77SGOxc= Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4gB2SW0rnqzpSx4; Thu, 7 May 2026 14:30:51 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id D152540576; Thu, 7 May 2026 14:37:41 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:41 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:40 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 5/7] perf-iostat: Extend iostat interface to support different iostat PMUs Date: Thu, 7 May 2026 14:37:35 +0800 Message-ID: <20260507063737.3542950-6-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" From: Shiju Jose Currently, platform-specific iostat code for PMUs is implemented as a common iostat callback interface and linked during build. This approach limits support for iostat across different implementations of PMU of the same architecture. To address this, extend common iostat interface to provide support for different PMUs by allowing each PMU to register itself and receive callbacks to its PMU-specific functions through the unified iostat framework. Signed-off-by: Shiju Jose Co-developed-by: Yushan Wang Signed-off-by: Yushan Wang --- tools/perf/util/iostat.c | 88 ++++++++++++++++++++++++++++++---------- tools/perf/util/iostat.h | 38 ++++++++++++++++- 2 files changed, 102 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/iostat.c b/tools/perf/util/iostat.c index a68ab100780d..90607d1cf3fa 100644 --- a/tools/perf/util/iostat.c +++ b/tools/perf/util/iostat.c @@ -1,47 +1,91 @@ // SPDX-License-Identifier: GPL-2.0 #include "util/iostat.h" -#include "util/debug.h" + +/* + * Below iostat_* function calls are scattered through out perf stat proce= ss, + * allowing multiple iostat PMUs and iterated them in following functions = may + * violate calling conventions or cause incorrect display. + * + * Default to register the first PMU device that matches any of the specif= ied + * iostat pmu name wildcards. + */ +static struct iostat_pmu *iostat_pmu; =20 enum iostat_mode_t iostat_mode =3D IOSTAT_NONE; =20 -__weak int iostat_prepare(struct evlist *evlist __maybe_unused, - struct perf_stat_config *config __maybe_unused) +__weak int iostat_prepare(struct evlist *evlist, struct perf_stat_config *= config) +{ + if (!iostat_pmu) + return -1; + + return iostat_pmu->prepare(evlist, config); +} + +__weak int iostat_parse(const struct option *opt, const char *str, int uns= et) { - return -1; + if (!iostat_pmu) + return -1; + + return iostat_pmu->parse(opt, str, unset); } =20 -__weak int iostat_parse(const struct option *opt __maybe_unused, - const char *str __maybe_unused, - int unset __maybe_unused) +__weak void iostat_list(struct evlist *evlist, struct perf_stat_config *co= nfig) { - pr_err("iostat mode is not supported on current platform\n"); - return -1; + iostat_pmu->list(evlist, config); } =20 -__weak void iostat_list(struct evlist *evlist __maybe_unused, - struct perf_stat_config *config __maybe_unused) +__weak void iostat_release(struct evlist *evlist) { + iostat_pmu->release(evlist); } =20 -__weak void iostat_release(struct evlist *evlist __maybe_unused) +__weak void iostat_print_header_prefix(struct perf_stat_config *config) { + iostat_pmu->print_header_prefix(config); } =20 -__weak void iostat_print_header_prefix(struct perf_stat_config *config __m= aybe_unused) +__weak void iostat_print_metric(struct perf_stat_config *config, + struct evsel *evsel, + struct perf_stat_output_ctx *out) { + iostat_pmu->print_metric(config, evsel, out); } =20 -__weak void iostat_print_metric(struct perf_stat_config *config __maybe_un= used, - struct evsel *evsel __maybe_unused, - struct perf_stat_output_ctx *out __maybe_unused) +__weak void iostat_print_counters(struct evlist *evlist, + struct perf_stat_config *config, + struct timespec *ts, char *prefix, + iostat_print_counter_t print_cnt_cb, + void *arg) { + iostat_pmu->print_counters(evlist, config, ts, prefix, + print_cnt_cb, arg); +} + +void register_iostat_pmu(struct iostat_pmu *pmu) +{ + if (!pmu || !pmu->match) + return; + + if (iostat_pmu || !pmu->match(pmu)) + return; + + iostat_pmu =3D pmu; +} + +static void unregister_iostat_pmu(void) +{ + if (!iostat_pmu) + return; + + /* + * Release function of iostat_pmu is called on the exit of cmd_stat, we + * don't need to call release function here. + */ + iostat_pmu =3D NULL; } =20 -__weak void iostat_print_counters(struct evlist *evlist __maybe_unused, - struct perf_stat_config *config __maybe_unused, - struct timespec *ts __maybe_unused, - char *prefix __maybe_unused, - iostat_print_counter_t print_cnt_cb __maybe_unused, - void *arg __maybe_unused) +__attribute__((destructor)) +static void iostat_exit(void) { + unregister_iostat_pmu(); } diff --git a/tools/perf/util/iostat.h b/tools/perf/util/iostat.h index 820930a096d9..5cc8963c6122 100644 --- a/tools/perf/util/iostat.h +++ b/tools/perf/util/iostat.h @@ -10,6 +10,7 @@ #ifndef _IOSTAT_H #define _IOSTAT_H =20 +#include #include #include "util/stat.h" #include "util/parse-events.h" @@ -31,8 +32,7 @@ extern enum iostat_mode_t iostat_mode; typedef void (*iostat_print_counter_t)(struct perf_stat_config *, struct e= vsel *, void *); =20 int iostat_prepare(struct evlist *evlist, struct perf_stat_config *config); -int iostat_parse(const struct option *opt, const char *str, - int unset __maybe_unused); +int iostat_parse(const struct option *opt, const char *str, int unset); void iostat_list(struct evlist *evlist, struct perf_stat_config *config); void iostat_release(struct evlist *evlist); void iostat_print_header_prefix(struct perf_stat_config *config); @@ -42,4 +42,38 @@ void iostat_print_counters(struct evlist *evlist, struct perf_stat_config *config, struct timespec *ts, char *prefix, iostat_print_counter_t print_cnt_cb, void *arg); =20 +/** + * struct iostat_pmu - Callbacks for an iostat-capable PMU backend. + * @pmu_name_wildcard: Glob pattern to identify the PMU (e.g. "uncore_iio*= "). + * @match: Detect whether matching PMUs exist on this system. + * @prepare: Set up events and config for iostat collection. + * @parse: Parse the --iostat option argument. + * @list: Display available iostat PMU instances. + * @print_header_prefix: Print the column header prefix. + * @print_metric: Format and print one metric value. + * @print_counters: Iterate over counters and print per-port results. + * @release: Clean up PMU-specific resources. + */ +struct iostat_pmu { + const char *pmu_name_wildcard; + bool (*match)(struct iostat_pmu *iostat_pmu); + int (*prepare)(struct evlist *evlist, struct perf_stat_config *config); + int (*parse)(const struct option *opt, const char *str, int unset); + void (*list)(struct evlist *evlist, struct perf_stat_config *config); + void (*print_header_prefix)(struct perf_stat_config *config); + void (*print_metric)(struct perf_stat_config *config, struct evsel *evsel, + struct perf_stat_output_ctx *out); + void (*print_counters)(struct evlist *evlist, + struct perf_stat_config *config, struct timespec *ts, + char *prefix, iostat_print_counter_t print_cnt_cb, void *arg); + void (*release)(struct evlist *evlist __maybe_unused); +}; + +/* + * Register an iostat PMU handler. Called from __attribute__((constructor)) + * functions in each backend's translation unit. + * + * Only the first matched backend is activated. + */ +void register_iostat_pmu(struct iostat_pmu *iostat_pmu); #endif /* _IOSTAT_H */ --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C7BF33D6FD; Thu, 7 May 2026 06:37:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135867; cv=none; b=jiKXZ3ZRDmt/y/dnqjDe8Tf7Obex8jqlWZE475ZNzSiMGX3lwWzuGRYBpHHzK69GaSdD/hRpkenkgl6n8W+HKTFqg2d6gG2XnTnyWBJjXVZxwP8HBpHLHuulTmvH54Xo+ZJrgyZfY6SJ92soKnQBOy/fLAH0vfBaPPRoLdIvZRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135867; c=relaxed/simple; bh=ip4IKH7OVmJzOwGVH3GxZTAde1VVc95rlyKd03bzRsw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CLghtEorpGWqJNyw7X8FhbQ39+tXtxMNwmuXsjZVDpBwLaPb620kah0dNed4lcMxXTR9N+IPQcdBAF1debKnVDDW7GVnJLNOOAm1hvBAKJGEe24YRAM+BmN/m6rt7Et7V3TkoMZzfyb9OHMBkWybx8eq3Wf9hFxHzUwS3WHiRHI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=jOq507Nx; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="jOq507Nx" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=a0ggBqVmcw6Sz5ULd2AGvpHsgqkgVFigalO47pfKWvo=; b=jOq507Nx+rCyT+fTYeHHq2e9Y57CJKlJkuJ+HlX/j7LX+vFjmh0l9Rtxct0NVhgeYkjzkF/md +QgTElBZEAN0kIocDOFdInP0KEQA+OVU6tv2/pH4plc6H7XLbzETBDXkB7a+O7ZiDkQHC91xOs1 FbfpmPXaZU2LgZjSvWV3/nA= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4gB2SW5s33zpSxL; Thu, 7 May 2026 14:30:51 +0800 (CST) Received: from dggemv705-chm.china.huawei.com (unknown [10.3.19.32]) by mail.maildlp.com (Postfix) with ESMTPS id 8876C4056A; Thu, 7 May 2026 14:37:42 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv705-chm.china.huawei.com (10.3.19.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:42 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:41 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 6/7] perf-iostat: Make x86 iostat compatible with new iostat framework Date: Thu, 7 May 2026 14:37:36 +0800 Message-ID: <20260507063737.3542950-7-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" From: Shiju Jose Change the original x86 iio iostat supporter to be compatible with the set of iostat frameworks. The matching function of x86 iio may not be correct. Signed-off-by: Shiju Jose Co-developed-by: Yushan Wang Signed-off-by: Yushan Wang --- tools/perf/util/iostat.c | 26 +++++++-------- tools/perf/util/x86-iostat.c | 62 ++++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/tools/perf/util/iostat.c b/tools/perf/util/iostat.c index 90607d1cf3fa..6c51f4a521af 100644 --- a/tools/perf/util/iostat.c +++ b/tools/perf/util/iostat.c @@ -13,7 +13,7 @@ static struct iostat_pmu *iostat_pmu; =20 enum iostat_mode_t iostat_mode =3D IOSTAT_NONE; =20 -__weak int iostat_prepare(struct evlist *evlist, struct perf_stat_config *= config) +int iostat_prepare(struct evlist *evlist, struct perf_stat_config *config) { if (!iostat_pmu) return -1; @@ -21,7 +21,7 @@ __weak int iostat_prepare(struct evlist *evlist, struct p= erf_stat_config *config return iostat_pmu->prepare(evlist, config); } =20 -__weak int iostat_parse(const struct option *opt, const char *str, int uns= et) +int iostat_parse(const struct option *opt, const char *str, int unset) { if (!iostat_pmu) return -1; @@ -29,33 +29,33 @@ __weak int iostat_parse(const struct option *opt, const= char *str, int unset) return iostat_pmu->parse(opt, str, unset); } =20 -__weak void iostat_list(struct evlist *evlist, struct perf_stat_config *co= nfig) +void iostat_list(struct evlist *evlist, struct perf_stat_config *config) { iostat_pmu->list(evlist, config); } =20 -__weak void iostat_release(struct evlist *evlist) +void iostat_release(struct evlist *evlist) { iostat_pmu->release(evlist); } =20 -__weak void iostat_print_header_prefix(struct perf_stat_config *config) +void iostat_print_header_prefix(struct perf_stat_config *config) { iostat_pmu->print_header_prefix(config); } =20 -__weak void iostat_print_metric(struct perf_stat_config *config, - struct evsel *evsel, - struct perf_stat_output_ctx *out) +void iostat_print_metric(struct perf_stat_config *config, + struct evsel *evsel, + struct perf_stat_output_ctx *out) { iostat_pmu->print_metric(config, evsel, out); } =20 -__weak void iostat_print_counters(struct evlist *evlist, - struct perf_stat_config *config, - struct timespec *ts, char *prefix, - iostat_print_counter_t print_cnt_cb, - void *arg) +void iostat_print_counters(struct evlist *evlist, + struct perf_stat_config *config, + struct timespec *ts, char *prefix, + iostat_print_counter_t print_cnt_cb, + void *arg) { iostat_pmu->print_counters(evlist, config, ts, prefix, print_cnt_cb, arg); diff --git a/tools/perf/util/x86-iostat.c b/tools/perf/util/x86-iostat.c index f8d4c9718594..778655cbc2a0 100644 --- a/tools/perf/util/x86-iostat.c +++ b/tools/perf/util/x86-iostat.c @@ -332,9 +332,9 @@ static int iostat_event_group(struct evlist *evl, return ret; } =20 -static void iostat_prefix(struct evlist *evlist, - struct perf_stat_config *config, - char *prefix, struct timespec *ts) +static void iio_iostat_prefix(struct evlist *evlist, + struct perf_stat_config *config, + char *prefix, struct timespec *ts) { struct iio_root_port *rp =3D evlist->selected->priv; =20 @@ -354,7 +354,7 @@ static void iostat_prefix(struct evlist *evlist, } } =20 -int iostat_prepare(struct evlist *evlist, struct perf_stat_config *config) +static int iio_iostat_prepare(struct evlist *evlist, struct perf_stat_conf= ig *config) { if (evlist->core.nr_entries > 0) { pr_warning("The -e and -M options are not supported." @@ -371,8 +371,8 @@ int iostat_prepare(struct evlist *evlist, struct perf_s= tat_config *config) return iostat_event_group(evlist, root_ports); } =20 -int iostat_parse(const struct option *opt, const char *str, - int unset __maybe_unused) +static int iio_iostat_parse(const struct option *opt, const char *str, + int unset __maybe_unused) { int ret; struct perf_stat_config *config =3D (struct perf_stat_config *)opt->data; @@ -392,7 +392,7 @@ int iostat_parse(const struct option *opt, const char *= str, return ret; } =20 -void iostat_list(struct evlist *evlist, struct perf_stat_config *config) +static void iio_iostat_list(struct evlist *evlist, struct perf_stat_config= *config) { struct evsel *evsel; struct iio_root_port *rp =3D NULL; @@ -405,7 +405,7 @@ void iostat_list(struct evlist *evlist, struct perf_sta= t_config *config) } } =20 -void iostat_release(struct evlist *evlist) +static void iio_iostat_release(struct evlist *evlist) { struct evsel *evsel; struct iio_root_port *rp =3D NULL; @@ -418,7 +418,7 @@ void iostat_release(struct evlist *evlist) } } =20 -void iostat_print_header_prefix(struct perf_stat_config *config) +static void iio_iostat_print_header_prefix(struct perf_stat_config *config) { if (config->csv_output) fputs("port,", config->output); @@ -428,8 +428,8 @@ void iostat_print_header_prefix(struct perf_stat_config= *config) fprintf(config->output, " port "); } =20 -void iostat_print_metric(struct perf_stat_config *config, struct evsel *ev= sel, - struct perf_stat_output_ctx *out) +static void iio_iostat_print_metric(struct perf_stat_config *config, struc= t evsel *evsel, + struct perf_stat_output_ctx *out) { double iostat_value =3D 0; u64 prev_count_val =3D 0; @@ -452,24 +452,54 @@ void iostat_print_metric(struct perf_stat_config *con= fig, struct evsel *evsel, iostat_value / (256 * 1024)); } =20 -void iostat_print_counters(struct evlist *evlist, - struct perf_stat_config *config, struct timespec *ts, - char *prefix, iostat_print_counter_t print_cnt_cb, void *arg) +static void iio_iostat_print_counters(struct evlist *evlist, + struct perf_stat_config *config, struct timespec *ts, + char *prefix, iostat_print_counter_t print_cnt_cb, void *arg) { void *perf_device =3D NULL; struct evsel *counter =3D evlist__first(evlist); =20 evlist__set_selected(evlist, counter); - iostat_prefix(evlist, config, prefix, ts); + iio_iostat_prefix(evlist, config, prefix, ts); fprintf(config->output, "%s", prefix); evlist__for_each_entry(evlist, counter) { perf_device =3D evlist->selected->priv; if (perf_device && perf_device !=3D counter->priv) { evlist__set_selected(evlist, counter); - iostat_prefix(evlist, config, prefix, ts); + iio_iostat_prefix(evlist, config, prefix, ts); fprintf(config->output, "\n%s", prefix); } print_cnt_cb(config, counter, arg); } fputc('\n', config->output); } + +/* + * FIXME: pmu name prefix match might not work for x86 iio. + */ +static bool iio_iostat_probe(struct iostat_pmu *iostat_pmu) +{ + return perf_pmus__scan_matching_wildcard(NULL, iostat_pmu->pmu_name_wildc= ard); +} + +static struct iostat_pmu x86_iio_iostat_pmu_list[] =3D { + { + .pmu_name_wildcard =3D "uncore_iio*", + .match =3D iio_iostat_probe, + .prepare =3D iio_iostat_prepare, + .parse =3D iio_iostat_parse, + .list =3D iio_iostat_list, + .print_header_prefix =3D iio_iostat_print_header_prefix, + .print_metric =3D iio_iostat_print_metric, + .print_counters =3D iio_iostat_print_counters, + .release =3D iio_iostat_release, + }, +}; + +static void __attribute__((constructor)) x86_iio_iostat_pmu_init(void) +{ + unsigned int i; + + for (i =3D 0; i < ARRAY_SIZE(x86_iio_iostat_pmu_list); i++) + register_iostat_pmu(&x86_iio_iostat_pmu_list[i]); +} --=20 2.33.0 From nobody Sat Jun 13 14:05:19 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B2DF33FE15; Thu, 7 May 2026 06:37:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135873; cv=none; b=Zr4p2ztcoAnx3ljpEXJYgHcCYrP7iE5Uhb+YuhkKC6wtIC7JTUcjyI5wgQzcRKoF2NA8AeqYHsgTnLU8pWR1bp4vgCrJkKU2hVN444Svi4qQuhu+qaPIBx0VbOGVeF02PDyFUt7T/iEt9ontlSbA6RtF9kyPFzQcUD7R+FeZySM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778135873; c=relaxed/simple; bh=oEcTQcKLvGB5AyBANtKcXjHU2cbID8Z5R8vqiu5ojkY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uMHUenblpO7GGSvUPRQCxEjnkskvoT53DqFdtVoUrCjqSn5isInGyUMGfHVf4aq4gQumbkvW34nnTnYYKCetsuv70/GD7IJG/nRL4weJHuc/QHkuvnbfSEeANw1BV0K2iT9yjrRa8OMqt/y+knSquUw0KemNEVx0en04Otmzxg0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=36qIw/JH; arc=none smtp.client-ip=113.46.200.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="36qIw/JH" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=+7BtQih2nQeoFC7zgs9Php1wZHaZ0m/JdrDGYCi/tXc=; b=36qIw/JHrhAUHZyZT2dEpkhb2OrKKvkX2TaubisfmbX7HmvTM4LNmU/fKaPs4LqnUCFOnNL/q 6Q8XRavxU94DBUQZ+HC2+vW6YIvD3zfdtgxAghZ9RLEb6nEUyvCKBR4xkptgF/uSHVHUd1FEZRo AJq+Qv/8kq3/beGkSWJshU0= Received: from mail.maildlp.com (unknown [172.19.162.223]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4gB2Rk3xlbz1T4Fx; Thu, 7 May 2026 14:30:10 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 426A240571; Thu, 7 May 2026 14:37:43 +0800 (CST) Received: from kwepemn100008.china.huawei.com (7.202.194.111) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 7 May 2026 14:37:43 +0800 Received: from localhost.huawei.com (10.90.31.46) by kwepemn100008.china.huawei.com (7.202.194.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 7 May 2026 14:37:42 +0800 From: Yushan Wang To: , , , , , , , , , , , , , , , CC: , , , , , , , , Subject: [RFT PATCH v2 7/7] perf-iostat: Enable iostat mode for HiSilicon PCIe PMU Date: Thu, 7 May 2026 14:37:37 +0800 Message-ID: <20260507063737.3542950-8-wangyushan12@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20260507063737.3542950-1-wangyushan12@huawei.com> References: <20260507063737.3542950-1-wangyushan12@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To kwepemn100008.china.huawei.com (7.202.194.111) Content-Type: text/plain; charset="utf-8" From: Yicong Yang Some HiSilicon platforms provide PCIe PMU devices for monitoring the throughput and latency of PCIe traffic. With the support of PCIe PMU we can enable the perf iostat mode. The HiSilicon PCIe PMU can support measuring the throughput of certain TLP types and of certain root port. Totally 6 metrics are provided in the unit of MB: - Inbound MWR: Memory write TLPs from downstream devices to root port - Inbound MRD: Memory read TLPs from downstream devices to root port - Inbound CPL: Completion TLPs from downstream devices to root port - Outbound MWR: Memory write TLPs from CPU to downstream devices - Outbound MRD: Memory read TLPs from CPU to downstream devices - Outbound CPL: Completions TLPs from CPU to downstream devices Since the PMU measures the throughput in DWords, we need to calculate the throughput in MB like: Count * 4B / 1024 / 1024 Some of the display of the `perf iostat` will be like: [root@localhost tmp]# ./perf iostat list hisi_pcie0_core2<0000:40:00.0> hisi_pcie2_core2<0000:5f:00.0> hisi_pcie0_core1<0000:16:00.0> hisi_pcie0_core1<0000:16:04.0> [root@localhost tmp]# ./perf iostat --timeout 10000 Performance counter stats for 'system wide': port Inbound MWR(MB) Inbound MRD(MB) Inbound CPL= (MB) Outbound MWR(MB) Outbound MRD(MB) Outbound CPL(MB) 0000:40:00.0 0 0 0= 0 0 0 0000:5f:00.0 0 0 0= 0 0 0 0000:16:00.0 16272.99 366.58 0= 15.09 0 16156.85 0000:16:04.0 0 0 0= 0 0 0 10.008227512 seconds time elapsed [root@localhost tmp]# ./perf iostat 0000:16:00.0 -- fio -name=3Drw -numjobs= =3D30 -filename=3D/dev/nvme0n1 -rw=3Drw -iodepth=3D128 -direct=3D1 -sync=3D= 0 -norandommap -group_reporting -runtime=3D10 -time_based -bs=3D64k 2>&1 > = /dev/null Performance counter stats for 'system wide': port Inbound MWR(MB) Inbound MRD(MB) Inbound CPL= (MB) Outbound MWR(MB) Outbound MRD(MB) Outbound CPL(MB) 0000:16:00.0 16614 379 0= 16 0 16721 10.180349717 seconds time elapsed 0.558810000 seconds user 2.495016000 seconds sys More information of the HiSilicon PCIe PMU can be found at Documentation/admin-guide/perf/hisi-pcie-pmu.rst. Signed-off-by: Yicong Yang Signed-off-by: Shiju Jose Signed-off-by: Yushan Wang --- tools/perf/util/Build | 1 + tools/perf/util/hisi-iostat.c | 478 ++++++++++++++++++++++++++++++++++ 2 files changed, 479 insertions(+) create mode 100644 tools/perf/util/hisi-iostat.c diff --git a/tools/perf/util/Build b/tools/perf/util/Build index c7e5ada3800d..fee9980cee77 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -128,6 +128,7 @@ perf-util-y +=3D spark.o perf-util-y +=3D topdown.o perf-util-y +=3D iostat.o perf-util-y +=3D x86-iostat.o +perf-util-y +=3D hisi-iostat.o perf-util-y +=3D stream.o perf-util-$(CONFIG_LIBTRACEEVENT) +=3D kvm-stat.o perf-util-y +=3D kvm-stat-arch/ diff --git a/tools/perf/util/hisi-iostat.c b/tools/perf/util/hisi-iostat.c new file mode 100644 index 000000000000..30041fd08614 --- /dev/null +++ b/tools/perf/util/hisi-iostat.c @@ -0,0 +1,478 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * perf iostat support for HiSilicon PCIe PMU. + * Partly derived from tools/perf/arch/x86/util/iostat.c. + * + * Copyright (c) 2024 HiSilicon Technologies Co., Ltd. + * Author: Yicong Yang + * Author: Yushan Wang + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "util/counts.h" +#include "util/debug.h" +#include "util/iostat.h" +#include "util/pmu.h" + +/* From include/uapi/linux/pci.h */ +#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) + +#define PCI_DEVICE_NAME_PATTERN "%04x:%02hhx:%02hhx.%hhu" +#define PCI_ROOT_BUS_DEVICES_PATH "bus/pci/devices" + +static const char * const hisi_iostat_metrics[] =3D { + "Inbound MWR(MB)", + "Inbound MRD(MB)", + "Inbound CPL(MB)", + "Outbound MWR(MB)", + "Outbound MRD(MB)", + "Outbound CPL(MB)", +}; + +static const char * const hisi_iostat_cmd_template[] =3D { + /* Inbound Memory Write */ + "hisi_pcie%hu_core%hu/event=3D0x0104,port=3D0x%hx/", + /* Inbound Memory Read */ + "hisi_pcie%hu_core%hu/event=3D0x0804,port=3D0x%hx/", + /* Inbound Memory Completion */ + "hisi_pcie%hu_core%hu/event=3D0x2004,port=3D0x%hx/", + /* Outbound Memory Write */ + "hisi_pcie%hu_core%hu/event=3D0x0105,port=3D0x%hx/", + /* Outbound Memory Read */ + "hisi_pcie%hu_core%hu/event=3D0x0405,port=3D0x%hx/", + /* Outbound Memory Completion */ + "hisi_pcie%hu_core%hu/event=3D0x1005,port=3D0x%hx/", +}; + +struct hisi_pcie_root_port { + struct list_head list; + /* Is this Root Port selected for monitoring */ + bool selected; + /* IDs to locate the PMU */ + u16 sicl_id; + u16 core_id; + /* Filter mask for this Root Port */ + u16 mask; + /* PCIe Root Port's ::. */ + u32 domain; + u8 bus; + u8 dev; + u8 fn; +}; + +static LIST_HEAD(hisi_pcie_root_ports_list); + +/* + * Select specific Root Port to monitor. Return 0 if successfully find the + * Root Port, Otherwise -EINVAL. + */ +static int hisi_pcie_root_ports_select_one(u32 domain, u8 bus, u8 dev, u8 = fn) +{ + struct hisi_pcie_root_port *rp; + + list_for_each_entry(rp, &hisi_pcie_root_ports_list, list) + if (domain =3D=3D rp->domain && bus =3D=3D rp->bus && + dev =3D=3D rp->dev && fn =3D=3D rp->fn) { + rp->selected =3D true; + return 0; + } + + return -EINVAL; +} + +static void hisi_pcie_root_ports_select_all(void) +{ + struct hisi_pcie_root_port *rp; + + list_for_each_entry(rp, &hisi_pcie_root_ports_list, list) + rp->selected =3D true; +} + +static void hisi_pcie_root_ports_add(u16 sicl_id, u16 core_id, u8 target_b= us, + u16 bdf_min, u16 bdf_max) +{ + const char *sysfs =3D sysfs__mountpoint(); + struct hisi_pcie_root_port *rp; + unsigned long path_len; + struct dirent *dent; + char path[PATH_MAX]; + u8 bus, dev, fn; + u32 domain; + DIR *dir; + u16 bdf; + int ret; + + path_len =3D snprintf(path, PATH_MAX, "%s/%s", sysfs, PCI_ROOT_BUS_DEVICE= S_PATH); + if (path_len > PATH_MAX) + return; + + dir =3D opendir(path); + if (!dir) + return; + + /* Scan the PCI root bus to find the match root port on @target_bus */ + while ((dent =3D readdir(dir))) { + ret =3D sscanf(dent->d_name, PCI_DEVICE_NAME_PATTERN, + &domain, &bus, &dev, &fn); + if (ret !=3D 4 || bus !=3D target_bus) + continue; + + bdf =3D (bus << 8) | PCI_DEVFN(dev, fn); + if (bdf < bdf_min || bdf > bdf_max) + continue; + + rp =3D zalloc(sizeof(*rp)); + if (!rp) + continue; + + rp->selected =3D false; + rp->sicl_id =3D sicl_id; + rp->core_id =3D core_id; + rp->domain =3D domain; + rp->bus =3D bus; + rp->dev =3D dev; + rp->fn =3D fn; + + rp->mask =3D BIT((rp->dev - PCI_SLOT(bdf_min)) << 1); + + list_add(&rp->list, &hisi_pcie_root_ports_list); + + pr_debug3("Found root port %s\n", dent->d_name); + } + + closedir(dir); +} + +/* Scan the PMUs and build the mapping of the Root Ports to the PMU */ +static int hisi_pcie_root_ports_init(void) +{ + char event_source[PATH_MAX], bus_path[PATH_MAX]; + unsigned long long bus, bdf_max, bdf_min; + u16 sicl_id, core_id; + struct dirent *dent; + DIR *dir; + + perf_pmu__event_source_devices_scnprintf(event_source, sizeof(event_sourc= e)); + dir =3D opendir(event_source); + if (!dir) + return -ENOENT; + + while ((dent =3D readdir(dir))) { + /* + * This HiSilicon PCIe PMU will be named as: + * hisi_pcie_core + */ + if ((sscanf(dent->d_name, "hisi_pcie%hu_core%hu", &sicl_id, &core_id)) != =3D 2) + continue; + + /* + * Driver will export the root port it can monitor through + * the "bus" sysfs attribute. + */ + scnprintf(bus_path, sizeof(bus_path), "%s/hisi_pcie%hu_core%hu/bus", + event_source, sicl_id, core_id); + + /* + * Per PCIe spec the bus should be 8bit, use unsigned long long + * for the convenience of the library function. + */ + if (filename__read_ull(bus_path, &bus)) + continue; + + scnprintf(bus_path, sizeof(bus_path), "%s/hisi_pcie%hu_core%hu/bdf_max", + event_source, sicl_id, core_id); + if (filename__read_xll(bus_path, &bdf_max)) + bdf_max =3D -1; + + scnprintf(bus_path, sizeof(bus_path), "%s/hisi_pcie%hu_core%hu/bdf_min", + event_source, sicl_id, core_id); + if (filename__read_xll(bus_path, &bdf_min)) + bdf_min =3D 0; + + pr_debug3("Found pmu %s bus 0x%llx\n", dent->d_name, bus); + + hisi_pcie_root_ports_add(sicl_id, core_id, (u8)bus, (u16)bdf_min, (u16)b= df_max); + } + + closedir(dir); + return !list_empty(&hisi_pcie_root_ports_list) ? 0 : -ENOENT; +} + +static void hisi_pcie_root_ports_free(void) +{ + struct hisi_pcie_root_port *rp, *tmp; + + if (list_empty(&hisi_pcie_root_ports_list)) + return; + + list_for_each_entry_safe(rp, tmp, &hisi_pcie_root_ports_list, list) { + list_del(&rp->list); + zfree(&rp); + } +} + +static int hisi_iostat_add_events(struct evlist *evl) +{ + struct hisi_pcie_root_port *rp; + struct evsel *evsel; + unsigned int i, j; + char *iostat_cmd; + int pos =3D 0; + int ret; + + if (list_empty(&hisi_pcie_root_ports_list)) + return -ENOENT; + + iostat_cmd =3D zalloc(PATH_MAX); + if (!iostat_cmd) + return -ENOMEM; + + list_for_each_entry(rp, &hisi_pcie_root_ports_list, list) { + if (!rp->selected) + continue; + + iostat_cmd[pos++] =3D '{'; + for (j =3D 0; j < ARRAY_SIZE(hisi_iostat_cmd_template); j++) { + pos +=3D snprintf(iostat_cmd + pos, ARG_MAX - pos - 1, + hisi_iostat_cmd_template[j], + rp->sicl_id, rp->core_id, rp->mask); + + if (j =3D=3D ARRAY_SIZE(hisi_iostat_cmd_template) - 1) + iostat_cmd[pos++] =3D '}'; + else + iostat_cmd[pos++] =3D ','; + } + + ret =3D parse_event(evl, iostat_cmd); + if (ret) + break; + + i =3D 0; + evlist__for_each_entry_reverse(evl, evsel) { + if (i =3D=3D ARRAY_SIZE(hisi_iostat_cmd_template)) + break; + + evsel->priv =3D rp; + i++; + } + + memset(iostat_cmd, 0, PATH_MAX); + pos =3D 0; + } + + zfree(&iostat_cmd); + return ret; +} + +static int hisi_iostat_prepare(struct evlist *evlist, + struct perf_stat_config *config) +{ + if (evlist->core.nr_entries > 0) { + pr_warning("The -e and -M options are not supported." + "All chosen events/metrics will be dropped\n"); + evlist__delete(evlist); + evlist =3D evlist__new(); + if (!evlist) + return -ENOMEM; + } + + config->metric_only =3D true; + config->aggr_mode =3D AGGR_GLOBAL; + + return hisi_iostat_add_events(evlist); +} + +static int hisi_pcie_root_ports_list_filter(const char *str) +{ + char *tok, *tmp, *copy =3D NULL; + u8 bus, dev, fn; + u32 domain; + int ret; + + copy =3D strdup(str); + if (!copy) + return -ENOMEM; + + for (tok =3D strtok_r(copy, ",", &tmp); tok; tok =3D strtok_r(NULL, ",", = &tmp)) { + ret =3D sscanf(tok, PCI_DEVICE_NAME_PATTERN, &domain, &bus, &dev, &fn); + if (ret !=3D 4) { + ret =3D -EINVAL; + break; + } + + ret =3D hisi_pcie_root_ports_select_one(domain, bus, dev, fn); + if (ret) + break; + } + + zfree(©); + return ret; +} + +static int hisi_iostat_parse(const struct option *opt, const char *str, in= t unset __maybe_unused) +{ + struct perf_stat_config *config =3D (struct perf_stat_config *)opt->data; + int ret; + + ret =3D hisi_pcie_root_ports_init(); + if (ret) + return ret; + + config->iostat_run =3D true; + + if (!str) { + iostat_mode =3D IOSTAT_RUN; + hisi_pcie_root_ports_select_all(); + } else if (!strcmp(str, "list")) { + iostat_mode =3D IOSTAT_LIST; + hisi_pcie_root_ports_select_all(); + } else { + iostat_mode =3D IOSTAT_RUN; + ret =3D hisi_pcie_root_ports_list_filter(str); + } + + if (ret) + hisi_pcie_root_ports_free(); + + return ret; +} + +static void hisi_pcie_root_port_show(FILE *output, + const struct hisi_pcie_root_port * const rp) +{ + if (output && rp) + fprintf(output, "hisi_pcie%hu_core%hu<" PCI_DEVICE_NAME_PATTERN ">\n", + rp->sicl_id, rp->core_id, rp->domain, rp->bus, rp->dev, rp->fn); +} + +static void hisi_iostat_list(struct evlist *evlist __maybe_unused, struct = perf_stat_config *config) +{ + struct hisi_pcie_root_port *rp =3D NULL; + struct evsel *evsel; + + evlist__for_each_entry(evlist, evsel) { + if (rp !=3D evsel->priv) { + hisi_pcie_root_port_show(config->output, evsel->priv); + rp =3D evsel->priv; + } + } +} + +static void hisi_iostat_release(struct evlist *evlist) +{ + struct evsel *evsel; + + evlist__for_each_entry(evlist, evsel) + evsel->priv =3D NULL; + + hisi_pcie_root_ports_free(); +} + +static void hisi_iostat_print_header_prefix(struct perf_stat_config *confi= g) +{ + if (config->csv_output) + fputs("port,", config->output); + else if (config->interval) + fprintf(config->output, "# time port "); + else + fprintf(config->output, " port "); +} + +static void hisi_iostat_print_metric(struct perf_stat_config *config, stru= ct evsel *evsel, + struct perf_stat_output_ctx *out) +{ + const char *iostat_metric =3D hisi_iostat_metrics[evsel->core.idx % ARRAY= _SIZE(hisi_iostat_metrics)]; + struct perf_counts_values *count; + double iostat_value; + + /* We're using AGGR_GLOBAL so there's only one aggr counts aggr[0]. */ + count =3D &evsel->stats->aggr[0].counts; + + /* The counts has been scaled, we can use it directly. */ + iostat_value =3D (double)count->val; + + /* + * Display two digits after decimal point for better accuracy if the + * value is non-zero. + */ + out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, + iostat_value > 0 ? "%8.2f" : "%8.0f", + iostat_metric, iostat_value / (256 * 1024)); +} + +static void hisi_iostat_prefix(struct evlist *evlist, struct perf_stat_con= fig *config, + char *prefix, struct timespec *ts) +{ + struct hisi_pcie_root_port *rp =3D evlist->selected->priv; + + if (!rp) + return; + + if (ts) + sprintf(prefix, "%6lu.%09lu%s" PCI_DEVICE_NAME_PATTERN "%s", + ts->tv_sec, ts->tv_nsec, config->csv_sep, + rp->domain, rp->bus, rp->dev, rp->fn, + config->csv_sep); + else + sprintf(prefix, PCI_DEVICE_NAME_PATTERN "%s", + rp->domain, rp->bus, rp->dev, rp->fn, + config->csv_sep); +} + +static void hisi_iostat_print_counters(struct evlist *evlist, struct perf_= stat_config *config, + struct timespec *ts, char *prefix, + iostat_print_counter_t print_cnt_cb, void *arg) +{ + struct evsel *counter =3D evlist__first(evlist); + void *perf_device; + + evlist__set_selected(evlist, counter); + hisi_iostat_prefix(evlist, config, prefix, ts); + fprintf(config->output, "%s", prefix); + evlist__for_each_entry(evlist, counter) { + perf_device =3D evlist->selected->priv; + if (perf_device && perf_device !=3D counter->priv) { + evlist__set_selected(evlist, counter); + hisi_iostat_prefix(evlist, config, prefix, ts); + fprintf(config->output, "\n%s", prefix); + } + print_cnt_cb(config, counter, arg); + } + fputc('\n', config->output); +} + +static bool hisi_iostat_match(struct iostat_pmu *iostat_pmu) +{ + return perf_pmus__scan_matching_wildcard(NULL, iostat_pmu->pmu_name_wildc= ard); +} + +static struct iostat_pmu hisi_iostat_pmu_list[] =3D { + { + .pmu_name_wildcard =3D "hisi_pcie*", + .match =3D hisi_iostat_match, + .prepare =3D hisi_iostat_prepare, + .parse =3D hisi_iostat_parse, + .list =3D hisi_iostat_list, + .print_header_prefix =3D hisi_iostat_print_header_prefix, + .print_metric =3D hisi_iostat_print_metric, + .print_counters =3D hisi_iostat_print_counters, + .release =3D hisi_iostat_release, + }, +}; + +static void __attribute__((constructor)) hisi_iostat_pmu_init(void) +{ + unsigned int i; + + for (i =3D 0; i < ARRAY_SIZE(hisi_iostat_pmu_list); i++) + register_iostat_pmu(&hisi_iostat_pmu_list[i]); +} --=20 2.33.0