From: Atish Patra <atishp@rivosinc.com>
To: kvm-riscv@lists.infradead.org
Subject: [PATCH v4 13/15] KVM: riscv: selftests: Add SBI PMU selftest
Date: Wed, 28 Feb 2024 17:01:28 -0800 [thread overview]
Message-ID: <20240229010130.1380926-14-atishp@rivosinc.com> (raw)
In-Reply-To: <20240229010130.1380926-1-atishp@rivosinc.com>
This test implements basic sanity test and cycle/instret event
counting tests.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
tools/testing/selftests/kvm/Makefile | 1 +
tools/testing/selftests/kvm/riscv/sbi_pmu.c | 340 ++++++++++++++++++++
2 files changed, 341 insertions(+)
create mode 100644 tools/testing/selftests/kvm/riscv/sbi_pmu.c
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 426f85798aea..b2dce6843b9e 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -195,6 +195,7 @@ TEST_GEN_PROGS_riscv += kvm_create_max_vcpus
TEST_GEN_PROGS_riscv += kvm_page_table_test
TEST_GEN_PROGS_riscv += set_memory_region_test
TEST_GEN_PROGS_riscv += steal_time
+TEST_GEN_PROGS_riscv += riscv/sbi_pmu
SPLIT_TESTS += arch_timer
SPLIT_TESTS += get-reg-list
diff --git a/tools/testing/selftests/kvm/riscv/sbi_pmu.c b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
new file mode 100644
index 000000000000..fc1fc5eea99e
--- /dev/null
+++ b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * arch_timer.c - Tests the riscv64 sstc timer IRQ functionality
+ *
+ * The test validates the sstc timer IRQs using vstimecmp registers.
+ * It's ported from the aarch64 arch_timer test.
+ *
+ * Copyright (c) 2024, Rivos Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "kvm_util.h"
+#include "test_util.h"
+#include "processor.h"
+
+/* Maximum counters (firmware + hardware)*/
+#define RISCV_MAX_PMU_COUNTERS 64
+union sbi_pmu_ctr_info ctrinfo_arr[RISCV_MAX_PMU_COUNTERS];
+
+/* Cache the available counters in a bitmask */
+static unsigned long counter_mask_available;
+
+unsigned long pmu_csr_read_num(int csr_num)
+{
+#define switchcase_csr_read(__csr_num, __val) {\
+ case __csr_num: \
+ __val = csr_read(__csr_num); \
+ break; }
+#define switchcase_csr_read_2(__csr_num, __val) {\
+ switchcase_csr_read(__csr_num + 0, __val) \
+ switchcase_csr_read(__csr_num + 1, __val)}
+#define switchcase_csr_read_4(__csr_num, __val) {\
+ switchcase_csr_read_2(__csr_num + 0, __val) \
+ switchcase_csr_read_2(__csr_num + 2, __val)}
+#define switchcase_csr_read_8(__csr_num, __val) {\
+ switchcase_csr_read_4(__csr_num + 0, __val) \
+ switchcase_csr_read_4(__csr_num + 4, __val)}
+#define switchcase_csr_read_16(__csr_num, __val) {\
+ switchcase_csr_read_8(__csr_num + 0, __val) \
+ switchcase_csr_read_8(__csr_num + 8, __val)}
+#define switchcase_csr_read_32(__csr_num, __val) {\
+ switchcase_csr_read_16(__csr_num + 0, __val) \
+ switchcase_csr_read_16(__csr_num + 16, __val)}
+
+ unsigned long ret = 0;
+
+ switch (csr_num) {
+ switchcase_csr_read_32(CSR_CYCLE, ret)
+ switchcase_csr_read_32(CSR_CYCLEH, ret)
+ default :
+ break;
+ }
+
+ return ret;
+#undef switchcase_csr_read_32
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+
+static inline void dummy_func_loop(int iter)
+{
+ int i = 0;
+
+ while (i < iter) {
+ asm volatile("nop");
+ i++;
+ }
+}
+
+static void guest_illegal_exception_handler(struct ex_regs *regs)
+{
+ __GUEST_ASSERT(regs->cause == EXC_INST_ILLEGAL,
+ "Unexpected exception handler %lx\n", regs->cause);
+
+ /* skip the trapping instruction */
+ regs->epc += 4;
+}
+
+static unsigned long get_counter_index(unsigned long cbase, unsigned long cmask,
+ unsigned long cflags,
+ unsigned long event)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
+ cflags, event, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "config matching failed %ld\n", ret.error);
+ GUEST_ASSERT((ret.value < RISCV_MAX_PMU_COUNTERS) &&
+ ((1UL << ret.value) & counter_mask_available));
+
+ return ret.value;
+}
+
+static unsigned long get_num_counters(void)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0);
+
+ __GUEST_ASSERT(ret.error == 0, "Unable to retrieve number of counters from SBI PMU");
+
+ __GUEST_ASSERT(ret.value < RISCV_MAX_PMU_COUNTERS,
+ "Invalid number of counters %ld\n", ret.value);
+
+ return ret.value;
+}
+
+static void update_counter_info(int num_counters)
+{
+ int i = 0;
+ struct sbiret ret;
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+
+ ctrinfo_arr[i].value = ret.value;
+ counter_mask_available |= BIT(i);
+ }
+
+ GUEST_ASSERT(counter_mask_available > 0);
+}
+
+static unsigned long read_counter(int idx, union sbi_pmu_ctr_info ctrinfo)
+{
+ unsigned long counter_val = 0;
+ struct sbiret ret;
+
+ __GUEST_ASSERT(ctrinfo.type < 2, "Invalid counter type %d", ctrinfo.type);
+
+ if (ctrinfo.type == SBI_PMU_CTR_TYPE_HW) {
+ counter_val = pmu_csr_read_num(ctrinfo.csr);
+ } else if (ctrinfo.type == SBI_PMU_CTR_TYPE_FW) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ, idx, 0, 0, 0, 0, 0);
+ GUEST_ASSERT(ret.error == 0);
+ counter_val = ret.value;
+ }
+
+ return counter_val;
+}
+
+static void start_counter(unsigned long counter, unsigned long start_flags,
+ unsigned long ival)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, counter, 1, start_flags,
+ ival, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "Unable to start counter %ld\n", counter);
+}
+
+static void stop_counter(unsigned long counter, unsigned long stop_flags)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, counter, 1, stop_flags,
+ 0, 0, 0);
+ if (stop_flags & SBI_PMU_STOP_FLAG_RESET)
+ __GUEST_ASSERT(ret.error == SBI_ERR_ALREADY_STOPPED,
+ "Unable to stop counter %ld\n", counter);
+ else
+ __GUEST_ASSERT(ret.error == 0, "Unable to stop counter %ld error %ld\n",
+ counter, ret.error);
+}
+
+static void test_pmu_event(unsigned long event)
+{
+ unsigned long counter;
+ unsigned long counter_value_pre, counter_value_post;
+ unsigned long counter_init_value = 100;
+
+ counter = get_counter_index(0, counter_mask_available, 0, event);
+ counter_value_pre = read_counter(counter, ctrinfo_arr[counter]);
+
+ /* Do not set the initial value */
+ start_counter(counter, 0, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_value_pre,
+ "counter_value_post %lx counter_value_pre %lx\n",
+ counter_value_post, counter_value_pre);
+
+ /* Now set the initial value and compare */
+ start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_init_value,
+ "counter_value_post %lx counter_init_value %lx\n",
+ counter_value_post, counter_init_value);
+
+ stop_counter(counter, SBI_PMU_STOP_FLAG_RESET);
+}
+
+static void test_invalid_event(void)
+{
+ struct sbiret ret;
+ unsigned long event = 0x1234; /* A random event */
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, 0,
+ counter_mask_available, 0, event, 0, 0);
+ GUEST_ASSERT_EQ(ret.error, SBI_ERR_NOT_SUPPORTED);
+}
+
+static void test_pmu_events(int cpu)
+{
+ int num_counters = 0;
+
+ /* Get the counter details */
+ num_counters = get_num_counters();
+ update_counter_info(num_counters);
+
+ /* Sanity testing for any random invalid event */
+ test_invalid_event();
+
+ /* Only these two events are guranteed to be present */
+ test_pmu_event(SBI_PMU_HW_CPU_CYCLES);
+ test_pmu_event(SBI_PMU_HW_INSTRUCTIONS);
+
+ GUEST_DONE();
+}
+
+static void test_pmu_basic_sanity(int cpu)
+{
+ long out_val = 0;
+ bool probe;
+ struct sbiret ret;
+ int num_counters = 0, i;
+ unsigned long counter_val = -1;
+ union sbi_pmu_ctr_info ctrinfo;
+
+ probe = guest_sbi_probe_extension(SBI_EXT_PMU, &out_val);
+ GUEST_ASSERT(probe && out_val == 1);
+
+ num_counters = get_num_counters();
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i,
+ 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+ else
+ continue;
+
+ ctrinfo.value = ret.value;
+
+ /* Accesibility check of hardware and read capability of firmware counters */
+ counter_val = read_counter(i, ctrinfo);
+ /* The spec doesn't mandate any initial value. Verify if a sane value */
+ GUEST_ASSERT_NE(counter_val, -1);
+ }
+
+ GUEST_DONE();
+}
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ vcpu_run(vcpu);
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_DONE:
+ case UCALL_SYNC:
+ break;
+ default:
+ TEST_FAIL("Unknown ucall %lu", uc.cmd);
+ break;
+ }
+}
+
+void test_vm_destroy(struct kvm_vm *vm)
+{
+ memset(ctrinfo_arr, 0, sizeof(union sbi_pmu_ctr_info) * RISCV_MAX_PMU_COUNTERS);
+ counter_mask_available = 0;
+ kvm_vm_free(vm);
+}
+
+static void test_vm_basic_test(void *guest_code)
+{
+ struct kvm_vm *vm;
+ struct kvm_vcpu *vcpu;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vm_init_vector_tables(vm);
+ /* Illegal instruction handler is required to verify read access without configuration */
+ vm_install_exception_handler(vm, EXC_INST_ILLEGAL, guest_illegal_exception_handler);
+
+ vcpu_init_vector_tables(vcpu);
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+static void test_vm_events_test(void *guest_code)
+{
+ struct kvm_vm *vm = NULL;
+ struct kvm_vcpu *vcpu = NULL;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+int main(void)
+{
+ test_vm_basic_test(test_pmu_basic_sanity);
+ pr_info("SBI PMU basic test : PASS\n");
+
+ test_vm_events_test(test_pmu_events);
+ pr_info("SBI PMU event verification test : PASS\n");
+
+ return 0;
+}
--
2.34.1
WARNING: multiple messages have this Message-ID (diff)
From: Atish Patra <atishp@rivosinc.com>
To: linux-kernel@vger.kernel.org
Cc: Atish Patra <atishp@rivosinc.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alexghiti@rivosinc.com>,
Andrew Jones <ajones@ventanamicro.com>,
Anup Patel <anup@brainfault.org>,
Atish Patra <atishp@atishpatra.org>,
Conor Dooley <conor.dooley@microchip.com>,
Guo Ren <guoren@kernel.org>, Icenowy Zheng <uwu@icenowy.me>,
kvm-riscv@lists.infradead.org, kvm@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-riscv@lists.infradead.org,
Mark Rutland <mark.rutland@arm.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Paul Walmsley <paul.walmsley@sifive.com>,
Shuah Khan <shuah@kernel.org>, Will Deacon <will@kernel.org>
Subject: [PATCH v4 13/15] KVM: riscv: selftests: Add SBI PMU selftest
Date: Wed, 28 Feb 2024 17:01:28 -0800 [thread overview]
Message-ID: <20240229010130.1380926-14-atishp@rivosinc.com> (raw)
In-Reply-To: <20240229010130.1380926-1-atishp@rivosinc.com>
This test implements basic sanity test and cycle/instret event
counting tests.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
tools/testing/selftests/kvm/Makefile | 1 +
tools/testing/selftests/kvm/riscv/sbi_pmu.c | 340 ++++++++++++++++++++
2 files changed, 341 insertions(+)
create mode 100644 tools/testing/selftests/kvm/riscv/sbi_pmu.c
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 426f85798aea..b2dce6843b9e 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -195,6 +195,7 @@ TEST_GEN_PROGS_riscv += kvm_create_max_vcpus
TEST_GEN_PROGS_riscv += kvm_page_table_test
TEST_GEN_PROGS_riscv += set_memory_region_test
TEST_GEN_PROGS_riscv += steal_time
+TEST_GEN_PROGS_riscv += riscv/sbi_pmu
SPLIT_TESTS += arch_timer
SPLIT_TESTS += get-reg-list
diff --git a/tools/testing/selftests/kvm/riscv/sbi_pmu.c b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
new file mode 100644
index 000000000000..fc1fc5eea99e
--- /dev/null
+++ b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * arch_timer.c - Tests the riscv64 sstc timer IRQ functionality
+ *
+ * The test validates the sstc timer IRQs using vstimecmp registers.
+ * It's ported from the aarch64 arch_timer test.
+ *
+ * Copyright (c) 2024, Rivos Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "kvm_util.h"
+#include "test_util.h"
+#include "processor.h"
+
+/* Maximum counters (firmware + hardware)*/
+#define RISCV_MAX_PMU_COUNTERS 64
+union sbi_pmu_ctr_info ctrinfo_arr[RISCV_MAX_PMU_COUNTERS];
+
+/* Cache the available counters in a bitmask */
+static unsigned long counter_mask_available;
+
+unsigned long pmu_csr_read_num(int csr_num)
+{
+#define switchcase_csr_read(__csr_num, __val) {\
+ case __csr_num: \
+ __val = csr_read(__csr_num); \
+ break; }
+#define switchcase_csr_read_2(__csr_num, __val) {\
+ switchcase_csr_read(__csr_num + 0, __val) \
+ switchcase_csr_read(__csr_num + 1, __val)}
+#define switchcase_csr_read_4(__csr_num, __val) {\
+ switchcase_csr_read_2(__csr_num + 0, __val) \
+ switchcase_csr_read_2(__csr_num + 2, __val)}
+#define switchcase_csr_read_8(__csr_num, __val) {\
+ switchcase_csr_read_4(__csr_num + 0, __val) \
+ switchcase_csr_read_4(__csr_num + 4, __val)}
+#define switchcase_csr_read_16(__csr_num, __val) {\
+ switchcase_csr_read_8(__csr_num + 0, __val) \
+ switchcase_csr_read_8(__csr_num + 8, __val)}
+#define switchcase_csr_read_32(__csr_num, __val) {\
+ switchcase_csr_read_16(__csr_num + 0, __val) \
+ switchcase_csr_read_16(__csr_num + 16, __val)}
+
+ unsigned long ret = 0;
+
+ switch (csr_num) {
+ switchcase_csr_read_32(CSR_CYCLE, ret)
+ switchcase_csr_read_32(CSR_CYCLEH, ret)
+ default :
+ break;
+ }
+
+ return ret;
+#undef switchcase_csr_read_32
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+
+static inline void dummy_func_loop(int iter)
+{
+ int i = 0;
+
+ while (i < iter) {
+ asm volatile("nop");
+ i++;
+ }
+}
+
+static void guest_illegal_exception_handler(struct ex_regs *regs)
+{
+ __GUEST_ASSERT(regs->cause == EXC_INST_ILLEGAL,
+ "Unexpected exception handler %lx\n", regs->cause);
+
+ /* skip the trapping instruction */
+ regs->epc += 4;
+}
+
+static unsigned long get_counter_index(unsigned long cbase, unsigned long cmask,
+ unsigned long cflags,
+ unsigned long event)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
+ cflags, event, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "config matching failed %ld\n", ret.error);
+ GUEST_ASSERT((ret.value < RISCV_MAX_PMU_COUNTERS) &&
+ ((1UL << ret.value) & counter_mask_available));
+
+ return ret.value;
+}
+
+static unsigned long get_num_counters(void)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0);
+
+ __GUEST_ASSERT(ret.error == 0, "Unable to retrieve number of counters from SBI PMU");
+
+ __GUEST_ASSERT(ret.value < RISCV_MAX_PMU_COUNTERS,
+ "Invalid number of counters %ld\n", ret.value);
+
+ return ret.value;
+}
+
+static void update_counter_info(int num_counters)
+{
+ int i = 0;
+ struct sbiret ret;
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+
+ ctrinfo_arr[i].value = ret.value;
+ counter_mask_available |= BIT(i);
+ }
+
+ GUEST_ASSERT(counter_mask_available > 0);
+}
+
+static unsigned long read_counter(int idx, union sbi_pmu_ctr_info ctrinfo)
+{
+ unsigned long counter_val = 0;
+ struct sbiret ret;
+
+ __GUEST_ASSERT(ctrinfo.type < 2, "Invalid counter type %d", ctrinfo.type);
+
+ if (ctrinfo.type == SBI_PMU_CTR_TYPE_HW) {
+ counter_val = pmu_csr_read_num(ctrinfo.csr);
+ } else if (ctrinfo.type == SBI_PMU_CTR_TYPE_FW) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ, idx, 0, 0, 0, 0, 0);
+ GUEST_ASSERT(ret.error == 0);
+ counter_val = ret.value;
+ }
+
+ return counter_val;
+}
+
+static void start_counter(unsigned long counter, unsigned long start_flags,
+ unsigned long ival)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, counter, 1, start_flags,
+ ival, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "Unable to start counter %ld\n", counter);
+}
+
+static void stop_counter(unsigned long counter, unsigned long stop_flags)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, counter, 1, stop_flags,
+ 0, 0, 0);
+ if (stop_flags & SBI_PMU_STOP_FLAG_RESET)
+ __GUEST_ASSERT(ret.error == SBI_ERR_ALREADY_STOPPED,
+ "Unable to stop counter %ld\n", counter);
+ else
+ __GUEST_ASSERT(ret.error == 0, "Unable to stop counter %ld error %ld\n",
+ counter, ret.error);
+}
+
+static void test_pmu_event(unsigned long event)
+{
+ unsigned long counter;
+ unsigned long counter_value_pre, counter_value_post;
+ unsigned long counter_init_value = 100;
+
+ counter = get_counter_index(0, counter_mask_available, 0, event);
+ counter_value_pre = read_counter(counter, ctrinfo_arr[counter]);
+
+ /* Do not set the initial value */
+ start_counter(counter, 0, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_value_pre,
+ "counter_value_post %lx counter_value_pre %lx\n",
+ counter_value_post, counter_value_pre);
+
+ /* Now set the initial value and compare */
+ start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_init_value,
+ "counter_value_post %lx counter_init_value %lx\n",
+ counter_value_post, counter_init_value);
+
+ stop_counter(counter, SBI_PMU_STOP_FLAG_RESET);
+}
+
+static void test_invalid_event(void)
+{
+ struct sbiret ret;
+ unsigned long event = 0x1234; /* A random event */
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, 0,
+ counter_mask_available, 0, event, 0, 0);
+ GUEST_ASSERT_EQ(ret.error, SBI_ERR_NOT_SUPPORTED);
+}
+
+static void test_pmu_events(int cpu)
+{
+ int num_counters = 0;
+
+ /* Get the counter details */
+ num_counters = get_num_counters();
+ update_counter_info(num_counters);
+
+ /* Sanity testing for any random invalid event */
+ test_invalid_event();
+
+ /* Only these two events are guranteed to be present */
+ test_pmu_event(SBI_PMU_HW_CPU_CYCLES);
+ test_pmu_event(SBI_PMU_HW_INSTRUCTIONS);
+
+ GUEST_DONE();
+}
+
+static void test_pmu_basic_sanity(int cpu)
+{
+ long out_val = 0;
+ bool probe;
+ struct sbiret ret;
+ int num_counters = 0, i;
+ unsigned long counter_val = -1;
+ union sbi_pmu_ctr_info ctrinfo;
+
+ probe = guest_sbi_probe_extension(SBI_EXT_PMU, &out_val);
+ GUEST_ASSERT(probe && out_val == 1);
+
+ num_counters = get_num_counters();
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i,
+ 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+ else
+ continue;
+
+ ctrinfo.value = ret.value;
+
+ /* Accesibility check of hardware and read capability of firmware counters */
+ counter_val = read_counter(i, ctrinfo);
+ /* The spec doesn't mandate any initial value. Verify if a sane value */
+ GUEST_ASSERT_NE(counter_val, -1);
+ }
+
+ GUEST_DONE();
+}
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ vcpu_run(vcpu);
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_DONE:
+ case UCALL_SYNC:
+ break;
+ default:
+ TEST_FAIL("Unknown ucall %lu", uc.cmd);
+ break;
+ }
+}
+
+void test_vm_destroy(struct kvm_vm *vm)
+{
+ memset(ctrinfo_arr, 0, sizeof(union sbi_pmu_ctr_info) * RISCV_MAX_PMU_COUNTERS);
+ counter_mask_available = 0;
+ kvm_vm_free(vm);
+}
+
+static void test_vm_basic_test(void *guest_code)
+{
+ struct kvm_vm *vm;
+ struct kvm_vcpu *vcpu;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vm_init_vector_tables(vm);
+ /* Illegal instruction handler is required to verify read access without configuration */
+ vm_install_exception_handler(vm, EXC_INST_ILLEGAL, guest_illegal_exception_handler);
+
+ vcpu_init_vector_tables(vcpu);
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+static void test_vm_events_test(void *guest_code)
+{
+ struct kvm_vm *vm = NULL;
+ struct kvm_vcpu *vcpu = NULL;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+int main(void)
+{
+ test_vm_basic_test(test_pmu_basic_sanity);
+ pr_info("SBI PMU basic test : PASS\n");
+
+ test_vm_events_test(test_pmu_events);
+ pr_info("SBI PMU event verification test : PASS\n");
+
+ return 0;
+}
--
2.34.1
WARNING: multiple messages have this Message-ID (diff)
From: Atish Patra <atishp@rivosinc.com>
To: linux-kernel@vger.kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>,
linux-kselftest@vger.kernel.org,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alexghiti@rivosinc.com>,
kvm@vger.kernel.org, Will Deacon <will@kernel.org>,
Anup Patel <anup@brainfault.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
Atish Patra <atishp@rivosinc.com>,
Conor Dooley <conor.dooley@microchip.com>,
Paolo Bonzini <pbonzini@redhat.com>, Guo Ren <guoren@kernel.org>,
kvm-riscv@lists.infradead.org,
Atish Patra <atishp@atishpatra.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
linux-riscv@lists.infradead.org, Shuah Khan <shuah@kernel.org>,
Andrew Jones <ajones@ventanamicro.com>
Subject: [PATCH v4 13/15] KVM: riscv: selftests: Add SBI PMU selftest
Date: Wed, 28 Feb 2024 17:01:28 -0800 [thread overview]
Message-ID: <20240229010130.1380926-14-atishp@rivosinc.com> (raw)
In-Reply-To: <20240229010130.1380926-1-atishp@rivosinc.com>
This test implements basic sanity test and cycle/instret event
counting tests.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
tools/testing/selftests/kvm/Makefile | 1 +
tools/testing/selftests/kvm/riscv/sbi_pmu.c | 340 ++++++++++++++++++++
2 files changed, 341 insertions(+)
create mode 100644 tools/testing/selftests/kvm/riscv/sbi_pmu.c
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 426f85798aea..b2dce6843b9e 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -195,6 +195,7 @@ TEST_GEN_PROGS_riscv += kvm_create_max_vcpus
TEST_GEN_PROGS_riscv += kvm_page_table_test
TEST_GEN_PROGS_riscv += set_memory_region_test
TEST_GEN_PROGS_riscv += steal_time
+TEST_GEN_PROGS_riscv += riscv/sbi_pmu
SPLIT_TESTS += arch_timer
SPLIT_TESTS += get-reg-list
diff --git a/tools/testing/selftests/kvm/riscv/sbi_pmu.c b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
new file mode 100644
index 000000000000..fc1fc5eea99e
--- /dev/null
+++ b/tools/testing/selftests/kvm/riscv/sbi_pmu.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * arch_timer.c - Tests the riscv64 sstc timer IRQ functionality
+ *
+ * The test validates the sstc timer IRQs using vstimecmp registers.
+ * It's ported from the aarch64 arch_timer test.
+ *
+ * Copyright (c) 2024, Rivos Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "kvm_util.h"
+#include "test_util.h"
+#include "processor.h"
+
+/* Maximum counters (firmware + hardware)*/
+#define RISCV_MAX_PMU_COUNTERS 64
+union sbi_pmu_ctr_info ctrinfo_arr[RISCV_MAX_PMU_COUNTERS];
+
+/* Cache the available counters in a bitmask */
+static unsigned long counter_mask_available;
+
+unsigned long pmu_csr_read_num(int csr_num)
+{
+#define switchcase_csr_read(__csr_num, __val) {\
+ case __csr_num: \
+ __val = csr_read(__csr_num); \
+ break; }
+#define switchcase_csr_read_2(__csr_num, __val) {\
+ switchcase_csr_read(__csr_num + 0, __val) \
+ switchcase_csr_read(__csr_num + 1, __val)}
+#define switchcase_csr_read_4(__csr_num, __val) {\
+ switchcase_csr_read_2(__csr_num + 0, __val) \
+ switchcase_csr_read_2(__csr_num + 2, __val)}
+#define switchcase_csr_read_8(__csr_num, __val) {\
+ switchcase_csr_read_4(__csr_num + 0, __val) \
+ switchcase_csr_read_4(__csr_num + 4, __val)}
+#define switchcase_csr_read_16(__csr_num, __val) {\
+ switchcase_csr_read_8(__csr_num + 0, __val) \
+ switchcase_csr_read_8(__csr_num + 8, __val)}
+#define switchcase_csr_read_32(__csr_num, __val) {\
+ switchcase_csr_read_16(__csr_num + 0, __val) \
+ switchcase_csr_read_16(__csr_num + 16, __val)}
+
+ unsigned long ret = 0;
+
+ switch (csr_num) {
+ switchcase_csr_read_32(CSR_CYCLE, ret)
+ switchcase_csr_read_32(CSR_CYCLEH, ret)
+ default :
+ break;
+ }
+
+ return ret;
+#undef switchcase_csr_read_32
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+
+static inline void dummy_func_loop(int iter)
+{
+ int i = 0;
+
+ while (i < iter) {
+ asm volatile("nop");
+ i++;
+ }
+}
+
+static void guest_illegal_exception_handler(struct ex_regs *regs)
+{
+ __GUEST_ASSERT(regs->cause == EXC_INST_ILLEGAL,
+ "Unexpected exception handler %lx\n", regs->cause);
+
+ /* skip the trapping instruction */
+ regs->epc += 4;
+}
+
+static unsigned long get_counter_index(unsigned long cbase, unsigned long cmask,
+ unsigned long cflags,
+ unsigned long event)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask,
+ cflags, event, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "config matching failed %ld\n", ret.error);
+ GUEST_ASSERT((ret.value < RISCV_MAX_PMU_COUNTERS) &&
+ ((1UL << ret.value) & counter_mask_available));
+
+ return ret.value;
+}
+
+static unsigned long get_num_counters(void)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_NUM_COUNTERS, 0, 0, 0, 0, 0, 0);
+
+ __GUEST_ASSERT(ret.error == 0, "Unable to retrieve number of counters from SBI PMU");
+
+ __GUEST_ASSERT(ret.value < RISCV_MAX_PMU_COUNTERS,
+ "Invalid number of counters %ld\n", ret.value);
+
+ return ret.value;
+}
+
+static void update_counter_info(int num_counters)
+{
+ int i = 0;
+ struct sbiret ret;
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+
+ ctrinfo_arr[i].value = ret.value;
+ counter_mask_available |= BIT(i);
+ }
+
+ GUEST_ASSERT(counter_mask_available > 0);
+}
+
+static unsigned long read_counter(int idx, union sbi_pmu_ctr_info ctrinfo)
+{
+ unsigned long counter_val = 0;
+ struct sbiret ret;
+
+ __GUEST_ASSERT(ctrinfo.type < 2, "Invalid counter type %d", ctrinfo.type);
+
+ if (ctrinfo.type == SBI_PMU_CTR_TYPE_HW) {
+ counter_val = pmu_csr_read_num(ctrinfo.csr);
+ } else if (ctrinfo.type == SBI_PMU_CTR_TYPE_FW) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ, idx, 0, 0, 0, 0, 0);
+ GUEST_ASSERT(ret.error == 0);
+ counter_val = ret.value;
+ }
+
+ return counter_val;
+}
+
+static void start_counter(unsigned long counter, unsigned long start_flags,
+ unsigned long ival)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_START, counter, 1, start_flags,
+ ival, 0, 0);
+ __GUEST_ASSERT(ret.error == 0, "Unable to start counter %ld\n", counter);
+}
+
+static void stop_counter(unsigned long counter, unsigned long stop_flags)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, counter, 1, stop_flags,
+ 0, 0, 0);
+ if (stop_flags & SBI_PMU_STOP_FLAG_RESET)
+ __GUEST_ASSERT(ret.error == SBI_ERR_ALREADY_STOPPED,
+ "Unable to stop counter %ld\n", counter);
+ else
+ __GUEST_ASSERT(ret.error == 0, "Unable to stop counter %ld error %ld\n",
+ counter, ret.error);
+}
+
+static void test_pmu_event(unsigned long event)
+{
+ unsigned long counter;
+ unsigned long counter_value_pre, counter_value_post;
+ unsigned long counter_init_value = 100;
+
+ counter = get_counter_index(0, counter_mask_available, 0, event);
+ counter_value_pre = read_counter(counter, ctrinfo_arr[counter]);
+
+ /* Do not set the initial value */
+ start_counter(counter, 0, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_value_pre,
+ "counter_value_post %lx counter_value_pre %lx\n",
+ counter_value_post, counter_value_pre);
+
+ /* Now set the initial value and compare */
+ start_counter(counter, SBI_PMU_START_FLAG_SET_INIT_VALUE, counter_init_value);
+ dummy_func_loop(10000);
+
+ stop_counter(counter, 0);
+
+ counter_value_post = read_counter(counter, ctrinfo_arr[counter]);
+ __GUEST_ASSERT(counter_value_post > counter_init_value,
+ "counter_value_post %lx counter_init_value %lx\n",
+ counter_value_post, counter_init_value);
+
+ stop_counter(counter, SBI_PMU_STOP_FLAG_RESET);
+}
+
+static void test_invalid_event(void)
+{
+ struct sbiret ret;
+ unsigned long event = 0x1234; /* A random event */
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, 0,
+ counter_mask_available, 0, event, 0, 0);
+ GUEST_ASSERT_EQ(ret.error, SBI_ERR_NOT_SUPPORTED);
+}
+
+static void test_pmu_events(int cpu)
+{
+ int num_counters = 0;
+
+ /* Get the counter details */
+ num_counters = get_num_counters();
+ update_counter_info(num_counters);
+
+ /* Sanity testing for any random invalid event */
+ test_invalid_event();
+
+ /* Only these two events are guranteed to be present */
+ test_pmu_event(SBI_PMU_HW_CPU_CYCLES);
+ test_pmu_event(SBI_PMU_HW_INSTRUCTIONS);
+
+ GUEST_DONE();
+}
+
+static void test_pmu_basic_sanity(int cpu)
+{
+ long out_val = 0;
+ bool probe;
+ struct sbiret ret;
+ int num_counters = 0, i;
+ unsigned long counter_val = -1;
+ union sbi_pmu_ctr_info ctrinfo;
+
+ probe = guest_sbi_probe_extension(SBI_EXT_PMU, &out_val);
+ GUEST_ASSERT(probe && out_val == 1);
+
+ num_counters = get_num_counters();
+
+ for (i = 0; i < num_counters; i++) {
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i,
+ 0, 0, 0, 0, 0);
+
+ /* There can be gaps in logical counter indicies*/
+ if (!ret.error)
+ GUEST_ASSERT_NE(ret.value, 0);
+ else
+ continue;
+
+ ctrinfo.value = ret.value;
+
+ /* Accesibility check of hardware and read capability of firmware counters */
+ counter_val = read_counter(i, ctrinfo);
+ /* The spec doesn't mandate any initial value. Verify if a sane value */
+ GUEST_ASSERT_NE(counter_val, -1);
+ }
+
+ GUEST_DONE();
+}
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ vcpu_run(vcpu);
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_DONE:
+ case UCALL_SYNC:
+ break;
+ default:
+ TEST_FAIL("Unknown ucall %lu", uc.cmd);
+ break;
+ }
+}
+
+void test_vm_destroy(struct kvm_vm *vm)
+{
+ memset(ctrinfo_arr, 0, sizeof(union sbi_pmu_ctr_info) * RISCV_MAX_PMU_COUNTERS);
+ counter_mask_available = 0;
+ kvm_vm_free(vm);
+}
+
+static void test_vm_basic_test(void *guest_code)
+{
+ struct kvm_vm *vm;
+ struct kvm_vcpu *vcpu;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vm_init_vector_tables(vm);
+ /* Illegal instruction handler is required to verify read access without configuration */
+ vm_install_exception_handler(vm, EXC_INST_ILLEGAL, guest_illegal_exception_handler);
+
+ vcpu_init_vector_tables(vcpu);
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+static void test_vm_events_test(void *guest_code)
+{
+ struct kvm_vm *vm = NULL;
+ struct kvm_vcpu *vcpu = NULL;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ __TEST_REQUIRE(__vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(KVM_RISCV_SBI_EXT_PMU)),
+ "SBI PMU not available, skipping test");
+ vcpu_args_set(vcpu, 1, 0);
+ run_vcpu(vcpu);
+
+ test_vm_destroy(vm);
+}
+
+int main(void)
+{
+ test_vm_basic_test(test_pmu_basic_sanity);
+ pr_info("SBI PMU basic test : PASS\n");
+
+ test_vm_events_test(test_pmu_events);
+ pr_info("SBI PMU event verification test : PASS\n");
+
+ return 0;
+}
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2024-02-29 1:01 UTC|newest]
Thread overview: 168+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-29 1:01 [PATCH v4 00/15] RISC-V SBI v2.0 PMU improvements and Perf sampling in KVM guest Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` [PATCH v4 01/15] RISC-V: Fix the typo in Scountovf CSR name Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 8:25 ` Clément Léger
2024-03-01 8:25 ` Clément Léger
2024-03-01 8:25 ` Clément Léger
2024-02-29 1:01 ` [PATCH v4 02/15] RISC-V: Add FIRMWARE_READ_HI definition Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 8:27 ` Clément Léger
2024-03-01 8:27 ` Clément Léger
2024-03-01 8:27 ` Clément Léger
2024-02-29 1:01 ` [PATCH v4 03/15] drivers/perf: riscv: Read upper bits of a firmware counter Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 9:52 ` Andrew Jones
2024-03-01 9:52 ` Andrew Jones
2024-03-01 9:52 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 04/15] RISC-V: Add SBI PMU snapshot definitions Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 11:14 ` Andrew Jones
2024-03-01 11:14 ` Andrew Jones
2024-03-01 11:14 ` Andrew Jones
2024-03-01 19:30 ` Atish Kumar Patra
2024-03-01 19:30 ` Atish Kumar Patra
2024-03-01 19:30 ` Atish Kumar Patra
2024-02-29 1:01 ` [PATCH v4 05/15] drivers/perf: riscv: Implement SBI PMU snapshot function Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 14:40 ` Andrew Jones
2024-03-01 14:40 ` Andrew Jones
2024-03-01 14:40 ` Andrew Jones
2024-03-01 15:55 ` Alexandre Ghiti
2024-03-01 15:55 ` Alexandre Ghiti
2024-03-01 15:55 ` Alexandre Ghiti
2024-02-29 1:01 ` [PATCH v4 06/15] RISC-V: KVM: No need to update the counter value during reset Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-02 7:47 ` Andrew Jones
2024-03-02 7:47 ` Andrew Jones
2024-03-02 7:47 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 07/15] RISC-V: KVM: No need to exit to the user space if perf event failed Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-02 8:15 ` Andrew Jones
2024-03-02 8:15 ` Andrew Jones
2024-03-02 8:15 ` Andrew Jones
2024-04-01 22:37 ` Atish Patra
2024-04-01 22:37 ` Atish Patra
2024-04-01 22:37 ` Atish Patra
2024-04-04 12:16 ` Andrew Jones
2024-04-04 12:16 ` Andrew Jones
2024-04-04 12:16 ` Andrew Jones
2024-04-10 22:44 ` Atish Patra
2024-04-10 22:44 ` Atish Patra
2024-04-10 22:44 ` Atish Patra
2024-04-11 7:38 ` Andrew Jones
2024-04-11 7:38 ` Andrew Jones
2024-04-11 7:38 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 08/15] RISC-V: KVM: Implement SBI PMU Snapshot feature Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-02 9:49 ` Andrew Jones
2024-03-02 9:49 ` Andrew Jones
2024-03-02 9:49 ` Andrew Jones
2024-04-01 22:36 ` Atish Patra
2024-04-01 22:36 ` Atish Patra
2024-04-01 22:36 ` Atish Patra
2024-04-03 7:36 ` Atish Patra
2024-04-03 7:36 ` Atish Patra
2024-04-03 7:36 ` Atish Patra
2024-04-04 13:19 ` Andrew Jones
2024-04-04 13:19 ` Andrew Jones
2024-04-04 13:19 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 09/15] RISC-V: KVM: Add perf sampling support for guests Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-02 10:33 ` Andrew Jones
2024-03-02 10:33 ` Andrew Jones
2024-03-02 10:33 ` Andrew Jones
2024-04-02 8:33 ` Atish Patra
2024-04-02 8:33 ` Atish Patra
2024-04-02 8:33 ` Atish Patra
2024-04-05 12:05 ` Andrew Jones
2024-04-05 12:05 ` Andrew Jones
2024-04-05 12:05 ` Andrew Jones
2024-04-10 0:11 ` Atish Patra
2024-04-10 0:11 ` Atish Patra
2024-04-10 0:11 ` Atish Patra
2024-04-10 7:20 ` Andrew Jones
2024-04-10 7:20 ` Andrew Jones
2024-04-10 7:20 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 10/15] RISC-V: KVM: Support 64 bit firmware counters on RV32 Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-02 10:52 ` Andrew Jones
2024-03-02 10:52 ` Andrew Jones
2024-03-02 10:52 ` Andrew Jones
2024-04-02 0:03 ` Atish Patra
2024-04-02 0:03 ` Atish Patra
2024-04-02 0:03 ` Atish Patra
2024-02-29 1:01 ` [PATCH v4 11/15] KVM: riscv: selftests: Add Sscofpmf to get-reg-list test Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 4:42 ` Anup Patel
2024-03-01 4:42 ` Anup Patel
2024-03-01 4:42 ` Anup Patel
2024-03-02 10:52 ` Andrew Jones
2024-03-02 10:52 ` Andrew Jones
2024-03-02 10:52 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 12/15] KVM: riscv: selftests: Add SBI PMU extension definitions Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 4:43 ` Anup Patel
2024-03-01 4:43 ` Anup Patel
2024-03-01 4:43 ` Anup Patel
2024-03-02 11:00 ` Andrew Jones
2024-03-02 11:00 ` Andrew Jones
2024-03-02 11:00 ` Andrew Jones
2024-04-02 8:43 ` Atish Patra
2024-04-02 8:43 ` Atish Patra
2024-04-02 8:43 ` Atish Patra
2024-02-29 1:01 ` Atish Patra [this message]
2024-02-29 1:01 ` [PATCH v4 13/15] KVM: riscv: selftests: Add SBI PMU selftest Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 4:47 ` Anup Patel
2024-03-01 4:47 ` Anup Patel
2024-03-01 4:47 ` Anup Patel
2024-03-02 1:01 ` Atish Kumar Patra
2024-03-02 1:01 ` Atish Kumar Patra
2024-03-02 1:01 ` Atish Kumar Patra
2024-03-02 11:52 ` Andrew Jones
2024-03-02 11:52 ` Andrew Jones
2024-03-02 11:52 ` Andrew Jones
2024-04-02 8:34 ` Atish Patra
2024-04-02 8:34 ` Atish Patra
2024-04-02 8:34 ` Atish Patra
2024-04-05 12:48 ` Andrew Jones
2024-04-05 12:48 ` Andrew Jones
2024-04-05 12:48 ` Andrew Jones
2024-02-29 1:01 ` [PATCH v4 14/15] KVM: riscv: selftests: Add a test for PMU snapshot functionality Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 4:50 ` Anup Patel
2024-03-01 4:50 ` Anup Patel
2024-03-01 4:50 ` Anup Patel
2024-03-02 12:13 ` Andrew Jones
2024-03-02 12:13 ` Andrew Jones
2024-03-02 12:13 ` Andrew Jones
2024-04-02 8:35 ` Atish Patra
2024-04-02 8:35 ` Atish Patra
2024-04-02 8:35 ` Atish Patra
2024-02-29 1:01 ` [PATCH v4 15/15] KVM: riscv: selftests: Add a test for counter overflow Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-02-29 1:01 ` Atish Patra
2024-03-01 4:53 ` Anup Patel
2024-03-01 4:53 ` Anup Patel
2024-03-01 4:53 ` Anup Patel
2024-03-02 12:35 ` Andrew Jones
2024-03-02 12:35 ` Andrew Jones
2024-03-02 12:35 ` Andrew Jones
2024-04-02 8:42 ` Atish Patra
2024-04-02 8:42 ` Atish Patra
2024-04-02 8:42 ` Atish Patra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240229010130.1380926-14-atishp@rivosinc.com \
--to=atishp@rivosinc.com \
--cc=kvm-riscv@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.