lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <db839f86-6749-e15b-a084-d8a4a6735f1c@loongson.cn>
Date: Tue, 7 May 2024 14:10:47 +0800
From: maobibo <maobibo@...ngson.cn>
To: Huacai Chen <chenhuacai@...nel.org>, Peter Zijlstra
 <peterz@...radead.org>, Ian Rogers <irogers@...gle.com>
Cc: Ming Wang <wangming01@...ngson.cn>, Ingo Molnar <mingo@...hat.com>,
 linux-kernel@...r.kernel.org, linux-perf-users@...r.kernel.org
Subject: Re: [PATCH v3] perf kvm: Add kvm-stat for loongarch64

Hi Peter/Ian/Huacai,

This patch stays one month without response, I know you are busy and 
look through thousands of patch every day.

Just one question, who has permission to merge perf kvm patch for 
LoongArch. Is it LoongArch maintainer or perf kvm maintainer?

Regards
Bibo Mao


On 2024/4/11 下午8:10, Bibo Mao wrote:
> Add support for 'perf kvm stat' on loongarch64 platform, now only
> kvm exit event is supported.
> 
> Here is example output about "perf kvm --host stat report" command
> 
>     Event name   Samples   Sample%     Time (ns)   Time%   Mean Time (ns)
>      Mem store     83969    51.00%     625697070   8.00%             7451
>       Mem read     37641    22.00%     112485730   1.00%             2988
>      Interrupt     15542     9.00%      20620190   0.00%             1326
>          Iocsr     15207     9.00%      94296190   1.00%             6200
>      Hypercall      4873     2.00%      12265280   0.00%             2516
>           Idle      3713     2.00%    6322055860  87.00%          1702681
>            FPU      1819     1.00%       2750300   0.00%             1511
>         Ifecth       502     0.00%       1341740   0.00%             2672
>     Mem modify       324     0.00%        602240   0.00%             1858
>         Cpucfg        55     0.00%         77610   0.00%             1411
>            Csr        12     0.00%         19690   0.00%             1640
>           LASX         3     0.00%          4870   0.00%             1623
>            LSX         2     0.00%          2100   0.00%             1050
> 
> Signed-off-by: Bibo Mao <maobibo@...ngson.cn>
> ---
> v2 --- v3:
>    1. Add NULL check with cpuid in function get_cpuid()
>    2. Add example output from /proc/cpuinfo before function get_cpuid()
> v1 --- v2:
>    1. Add child_ops for kvm exit event, split kvm:kvm_exit_gspr events
> into cpucfg/csr/iocsr/idle child events by decoding detailed gspr
> instruction.
>    2. Remove some exception code type which does not happen in current
> kvm implementation, such as meomry NR/NX/priviledge exception.
> ---
>   tools/perf/arch/loongarch/Makefile        |   1 +
>   tools/perf/arch/loongarch/util/Build      |   2 +
>   tools/perf/arch/loongarch/util/header.c   |  88 ++++++++++++++
>   tools/perf/arch/loongarch/util/kvm-stat.c | 135 ++++++++++++++++++++++
>   4 files changed, 226 insertions(+)
>   create mode 100644 tools/perf/arch/loongarch/util/header.c
>   create mode 100644 tools/perf/arch/loongarch/util/kvm-stat.c
> 
> diff --git a/tools/perf/arch/loongarch/Makefile b/tools/perf/arch/loongarch/Makefile
> index 3992a67a87d9..c89d6bb6b184 100644
> --- a/tools/perf/arch/loongarch/Makefile
> +++ b/tools/perf/arch/loongarch/Makefile
> @@ -4,6 +4,7 @@ PERF_HAVE_DWARF_REGS := 1
>   endif
>   PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
>   PERF_HAVE_JITDUMP := 1
> +HAVE_KVM_STAT_SUPPORT := 1
>   
>   #
>   # Syscall table generation for perf
> diff --git a/tools/perf/arch/loongarch/util/Build b/tools/perf/arch/loongarch/util/Build
> index d776125a2d06..b12d374d7096 100644
> --- a/tools/perf/arch/loongarch/util/Build
> +++ b/tools/perf/arch/loongarch/util/Build
> @@ -1,5 +1,7 @@
> +perf-y += header.o
>   perf-y += perf_regs.o
>   
>   perf-$(CONFIG_DWARF)     += dwarf-regs.o
>   perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
>   perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
> +perf-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o
> diff --git a/tools/perf/arch/loongarch/util/header.c b/tools/perf/arch/loongarch/util/header.c
> new file mode 100644
> index 000000000000..a4ed732b49c6
> --- /dev/null
> +++ b/tools/perf/arch/loongarch/util/header.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Implementation of get_cpuid().
> + *
> + * Author: Nikita Shubin <n.shubin@...ro.com>
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <api/fs/fs.h>
> +#include <errno.h>
> +#include "util/debug.h"
> +#include "util/header.h"
> +
> +/*
> + * Output example from /proc/cpuinfo
> + *   CPU Family              : Loongson-64bit
> + *   Model Name              : Loongson-3C5000
> + *   CPU Revision            : 0x11
> + */
> +#define CPUINFO_MODEL	"Model Name"
> +#define CPUINFO		"/proc/cpuinfo"
> +static char *_get_field(const char *line)
> +{
> +	char *line2, *nl;
> +
> +	line2 = strrchr(line, ' ');
> +	if (!line2)
> +		return NULL;
> +
> +	line2++;
> +	nl = strrchr(line, '\n');
> +	if (!nl)
> +		return NULL;
> +
> +	return strndup(line2, nl - line2);
> +}
> +
> +static char *__get_cpuid(void)
> +{
> +	char *line, *model, *cpuid;
> +	unsigned long line_sz;
> +	FILE *file;
> +
> +	file = fopen(CPUINFO, "r");
> +	if (file == NULL)
> +		return cpuid;
> +
> +	line = model = cpuid = NULL;
> +	while (getline(&line, &line_sz, file) != -1) {
> +		if (strncmp(line, CPUINFO_MODEL, strlen(CPUINFO_MODEL)))
> +			continue;
> +
> +		model = _get_field(line);
> +		if (!model)
> +			goto free;
> +		break;
> +	}
> +
> +	if (model && (asprintf(&cpuid, "%s", model) < 0))
> +		cpuid = NULL;
> +
> +free:
> +	fclose(file);
> +	free(model);
> +	return cpuid;
> +}
> +
> +int get_cpuid(char *buffer, size_t sz)
> +{
> +	char *cpuid = __get_cpuid();
> +	int ret = 0;
> +
> +	if (!cpuid)
> +		return EINVAL;
> +
> +	if (sz >= strlen(cpuid))
> +		scnprintf(buffer, sz, "%s", cpuid);
> +	else
> +		ret = ENOBUFS;
> +	free(cpuid);
> +	return ret;
> +}
> +
> +char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
> +{
> +	return __get_cpuid();
> +}
> diff --git a/tools/perf/arch/loongarch/util/kvm-stat.c b/tools/perf/arch/loongarch/util/kvm-stat.c
> new file mode 100644
> index 000000000000..cc50adb0835a
> --- /dev/null
> +++ b/tools/perf/arch/loongarch/util/kvm-stat.c
> @@ -0,0 +1,135 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <errno.h>
> +#include <memory.h>
> +#include <errno.h>
> +#include "util/kvm-stat.h"
> +#include "util/parse-events.h"
> +#include "util/debug.h"
> +#include "util/evsel.h"
> +#include "util/evlist.h"
> +#include "util/pmus.h"
> +
> +#define LOONGARCH_EXCEPTION_INT		0
> +#define LOONGARCH_EXCEPTION_PIL		1
> +#define LOONGARCH_EXCEPTION_PIS		2
> +#define LOONGARCH_EXCEPTION_PIF		3
> +#define LOONGARCH_EXCEPTION_PME		4
> +#define LOONGARCH_EXCEPTION_FPD		15
> +#define LOONGARCH_EXCEPTION_SXD		16
> +#define LOONGARCH_EXCEPTION_ASXD	17
> +#define LOONGARCH_EXCEPTION_GSPR	22
> +#define  LOONGARCH_EXCEPTION_CPUCFG	100
> +#define  LOONGARCH_EXCEPTION_CSR	101
> +#define  LOONGARCH_EXCEPTION_IOCSR	102
> +#define  LOONGARCH_EXCEPTION_IDLE	103
> +#define  LOONGARCH_EXCEPTION_OTHERS	104
> +#define LOONGARCH_EXCEPTION_HVC		23
> +
> +#define loongarch_exception_type				\
> +	{LOONGARCH_EXCEPTION_INT,  "Interrupt" },		\
> +	{LOONGARCH_EXCEPTION_PIL,  "Mem read" },		\
> +	{LOONGARCH_EXCEPTION_PIS,  "Mem store" },		\
> +	{LOONGARCH_EXCEPTION_PIF,  "Ifecth" },			\
> +	{LOONGARCH_EXCEPTION_PME,  "Mem modify" },		\
> +	{LOONGARCH_EXCEPTION_FPD,  "FPU" },			\
> +	{LOONGARCH_EXCEPTION_SXD,  "LSX" },			\
> +	{LOONGARCH_EXCEPTION_ASXD, "LASX" },			\
> +	{LOONGARCH_EXCEPTION_GSPR, "Privilege Error" },		\
> +	{LOONGARCH_EXCEPTION_HVC,  "Hypercall" },		\
> +	{LOONGARCH_EXCEPTION_CPUCFG, "Cpucfg" },		\
> +	{LOONGARCH_EXCEPTION_CSR,    "Csr" },			\
> +	{LOONGARCH_EXCEPTION_IOCSR,  "Iocsr" },			\
> +	{LOONGARCH_EXCEPTION_IDLE,   "Idle" },			\
> +	{LOONGARCH_EXCEPTION_OTHERS, "Others" }
> +
> +define_exit_reasons_table(loongarch_exit_reasons, loongarch_exception_type);
> +
> +const char *vcpu_id_str = "vcpu_id";
> +const char *kvm_exit_reason = "reason";
> +const char *kvm_entry_trace = "kvm:kvm_enter";
> +const char *kvm_reenter_trace = "kvm:kvm_reenter";
> +const char *kvm_exit_trace = "kvm:kvm_exit";
> +const char *kvm_events_tp[] = {
> +	"kvm:kvm_enter",
> +	"kvm:kvm_reenter",
> +	"kvm:kvm_exit",
> +	"kvm:kvm_exit_gspr",
> +	NULL,
> +};
> +
> +static bool event_end(struct evsel *evsel,
> +		struct perf_sample *sample __maybe_unused,
> +		struct event_key *key __maybe_unused)
> +{
> +	/*
> +	 * LoongArch kvm is different with other architectures
> +	 *
> +	 * There is kvm:kvm_reenter or kvm:kvm_enter event adjacent with
> +	 * kvm:kvm_exit event.
> +	 *   kvm:kvm_reenter means returning to guest immediately
> +	 *   kvm:kvm_enter   means returning to vmm and then to guest
> +	 */
> +	return evsel__name_is(evsel, kvm_entry_trace) ||
> +		evsel__name_is(evsel, kvm_reenter_trace);
> +}
> +
> +static void event_gspr_get_key(struct evsel *evsel,
> +			struct perf_sample *sample,
> +			struct event_key *key)
> +{
> +	unsigned int insn;
> +
> +	key->key = LOONGARCH_EXCEPTION_OTHERS;
> +	insn = evsel__intval(evsel, sample, "inst_word");
> +	switch (insn >> 24) {
> +	case 0:
> +		/* cpucfg inst trap */
> +		if ((insn >> 10) == 0x1b)
> +			key->key = LOONGARCH_EXCEPTION_CPUCFG;
> +		break;
> +	case 4:
> +		/* csr inst trap */
> +		key->key = LOONGARCH_EXCEPTION_CSR;
> +		break;
> +	case 6:
> +		/* iocsr inst trap */
> +		if ((insn >> 15) == 0xc90)
> +			key->key = LOONGARCH_EXCEPTION_IOCSR;
> +		else if ((insn >> 15) == 0xc91)
> +			/* idle inst trap */
> +			key->key = LOONGARCH_EXCEPTION_IDLE;
> +		break;
> +	default:
> +		key->key = LOONGARCH_EXCEPTION_OTHERS;
> +		break;
> +	}
> +}
> +
> +static struct child_event_ops child_events[] = {
> +	{ .name = "kvm:kvm_exit_gspr", .get_key = event_gspr_get_key },
> +	{ NULL, NULL },
> +};
> +
> +static struct kvm_events_ops exit_events = {
> +	.is_begin_event = exit_event_begin,
> +	.is_end_event = event_end,
> +	.child_ops = child_events,
> +	.decode_key = exit_event_decode_key,
> +	.name = "VM-EXIT"
> +};
> +
> +struct kvm_reg_events_ops kvm_reg_events_ops[] = {
> +	{ .name	= "vmexit", .ops = &exit_events, },
> +	{ NULL, NULL },
> +};
> +
> +const char * const kvm_skip_events[] = {
> +	NULL,
> +};
> +
> +int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
> +{
> +	kvm->exit_reasons_isa = "loongarch64";
> +	kvm->exit_reasons = loongarch_exit_reasons;
> +	return 0;
> +}
> 
> base-commit: 2c71fdf02a95b3dd425b42f28fd47fb2b1d22702
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ