[RFC PATCH v4 2/2] tests/qtest: QTest example for RISC-V CSR register

2024-07-03 Thread Ivan Klokov
Added demo for reading CSR register from qtest environment.

Signed-off-by: Ivan Klokov 
---
 tests/qtest/meson.build  |  2 +
 tests/qtest/riscv-csr-test.c | 86 
 2 files changed, 88 insertions(+)
 create mode 100644 tests/qtest/riscv-csr-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 12792948ff..45d651da99 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -259,6 +259,8 @@ qtests_s390x = \
 qtests_riscv32 = \
   (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? 
['sifive-e-aon-watchdog-test'] : [])
 
+qtests_riscv32 += ['riscv-csr-test']
+
 qos_test_ss = ss.source_set()
 qos_test_ss.add(
   'ac97-test.c',
diff --git a/tests/qtest/riscv-csr-test.c b/tests/qtest/riscv-csr-test.c
new file mode 100644
index 00..e9af9ca724
--- /dev/null
+++ b/tests/qtest/riscv-csr-test.c
@@ -0,0 +1,86 @@
+/*
+ * QTest testcase for RISC-V CSRs
+ *
+ * Copyright (c) 2024 Syntacore.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "libqtest.h"
+
+static uint64_t qcsr_call(QTestState *qts, const char *name, uint64_t cpu,
+   int csrno, uint64_t *val)
+{
+uint64_t res = 0;
+
+res = qtest_csr_call(qts, name, cpu, csrno, val);
+
+return res;
+}
+
+static int qcsr_get_csr(QTestState *qts, uint64_t cpu,
+int csrno, uint64_t *val)
+{
+int res;
+
+res = qcsr_call(qts, "get_csr", cpu, csrno, val);
+
+return res;
+}
+
+static int qcsr_set_csr(QTestState *qts, uint64_t cpu,
+int csrno, uint64_t *val)
+{
+int res;
+
+res = qcsr_call(qts, "set_csr", cpu, csrno, val);
+
+return res;
+}
+
+static void run_test_csr(void)
+{
+
+uint64_t res;
+uint64_t val = 0;
+
+res = qcsr_call(global_qtest, "get_csr", 0, 0xf11, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0x100);
+
+val = 0xff;
+res = qcsr_call(global_qtest, "set_csr", 0, 0x342, &val);
+
+g_assert_cmpint(res, ==, 0);
+
+val = 0;
+res = qcsr_call(global_qtest, "get_csr", 0, 0x342, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0xff);
+
+qtest_quit(global_qtest);
+}
+
+int main(int argc, char **argv)
+{
+g_test_init(&argc, &argv, NULL);
+
+qtest_add_func("/cpu/csr", run_test_csr);
+
+qtest_start("-machine virt -cpu any,mvendorid=0x100");
+
+return g_test_run();
+
+}
-- 
2.34.1




[RFC PATCH v4 0/2] Support RISC-V CSR read/write in Qtest environment

2024-07-03 Thread Ivan Klokov
These patches add functionality for unit testing RISC-V-specific registers.
The first patch adds a Qtest backend, and the second implements a simple test.

---
v4:
   - Change wrapper to direct call
---

Ivan Klokov (2):
  target/riscv: Add RISC-V CSR qtest support
  tests/qtest: QTest example for RISC-V CSR register

 target/riscv/cpu.c   | 17 +++
 target/riscv/cpu.h   |  3 ++
 target/riscv/csr.c   | 53 +-
 tests/qtest/libqtest.c   | 27 +++
 tests/qtest/libqtest.h   | 14 ++
 tests/qtest/meson.build  |  2 +
 tests/qtest/riscv-csr-test.c | 86 
 7 files changed, 201 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/riscv-csr-test.c

-- 
2.34.1




[RFC PATCH v4 1/2] target/riscv: Add RISC-V CSR qtest support

2024-07-03 Thread Ivan Klokov
The RISC-V architecture supports the creation of custom
CSR-mapped devices. It would be convenient to test them in the same way
as MMIO-mapped devices. To do this, a new call has been added
to read/write CSR registers.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu.c | 17 ++
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c | 53 +-
 tests/qtest/libqtest.c | 27 +
 tests/qtest/libqtest.h | 14 +++
 5 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..7c15860414 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1149,6 +1149,18 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error 
**errp)
 }
 }
 
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_register_csr_qtest_callback(void)
+{
+static gsize reinit_done;
+if (g_once_init_enter(&reinit_done)) {
+qtest_set_command_cb(csr_qtest_callback);
+
+g_once_init_leave(&reinit_done, 1);
+}
+}
+#endif
+
 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -1175,6 +1187,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 
 riscv_cpu_register_gdb_regs_for_features(cs);
 
+#ifndef CONFIG_USER_ONLY
+/* register callback for csr qtests */
+riscv_cpu_register_csr_qtest_callback();
+#endif
+
 #ifndef CONFIG_USER_ONLY
 if (cpu->cfg.debug) {
 riscv_trigger_realize(&cpu->env);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..6d4bbec53c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -32,6 +32,8 @@
 #include "cpu_cfg.h"
 #include "qapi/qapi-types-common.h"
 #include "cpu-qom.h"
+#include "qemu/cutils.h"
+#include "sysemu/qtest.h"
 
 typedef struct CPUArchState CPURISCVState;
 
@@ -813,6 +815,7 @@ bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
+bool csr_qtest_callback(CharBackend *chr, gchar **words);
 
 extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58ef7079dc..f4f5128c9c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -29,7 +29,7 @@
 #include "sysemu/cpu-timers.h"
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
-
+#include "tests/qtest/libqtest.h"
 
 /* CSR function table public API */
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
@@ -4549,6 +4549,57 @@ static RISCVException write_jvt(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+#if !defined(CONFIG_USER_ONLY)
+static uint64_t csr_call(char *cmd, uint64_t cpu_num, int csrno,
+uint64_t *val)
+{
+RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
+CPURISCVState *env = &cpu->env;
+
+int ret = RISCV_EXCP_NONE;
+if (strcmp(cmd, "get_csr") == 0) {
+ret = riscv_csrrw(env, csrno, (target_ulong *)val, 0, 0);
+
+} else if (strcmp(cmd, "set_csr") == 0) {
+ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val, 
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
+}
+
+if (ret == RISCV_EXCP_NONE) {
+ret = 0;
+} else {
+g_assert_not_reached();
+}
+
+return ret;
+}
+
+bool csr_qtest_callback(CharBackend *chr, gchar **words)
+{
+if (strcmp(words[0], "csr") == 0) {
+
+uint64_t res, cpu;
+
+uint64_t val;
+int rc, csr;
+
+rc = qemu_strtou64(words[2], NULL, 0, &cpu);
+g_assert(rc == 0);
+rc = qemu_strtoi(words[3], NULL, 0, &csr);
+g_assert(rc == 0);
+rc = qemu_strtou64(words[4], NULL, 0, &val);
+g_assert(rc == 0);
+res = csr_call(words[1], cpu, csr, &val);
+
+qtest_send_prefix(chr);
+qtest_sendf(chr, "OK %"PRIx64" "TARGET_FMT_lx"\n", res, 
(target_ulong)val);
+
+return true;
+}
+
+return false;
+}
+#endif
+
 /*
  * Control and Status Register function table
  * riscv_csr_operations::predicate() must be provided for an implemented CSR
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index c7f6897d78..f8c3ff15a9 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -1205,6 +1205,33 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
 return 0;
 }
 
+static void qtest_rsp_csr(QTestState *s, uint64_t *val)
+{
+gchar **args;
+uint64_t ret;
+int rc;
+
+args = qtest_rsp_args(s, 3);
+
+rc = qemu_strtou64(args[1], NULL, 16, &ret);
+g_assert(rc == 0);
+rc = qemu_strtou64(args[2], NULL, 16, val);
+g_assert(rc == 0);
+
+g_strfreev(args);
+}
+
+uint64_t qtest_csr_call(QTestState *s, const char *name,
+ uint64_t cpu, int 

[RFC PATCH v3 1/2] target/riscv: Add RISC-V CSR qtest support

2024-06-25 Thread Ivan Klokov
The RISC-V architecture supports the creation of custom
CSR-mapped devices. It would be convenient to test them in the same way
as MMIO-mapped devices. To do this, a new call has been added
to read/write CSR registers.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu.c | 14 +++
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c | 53 +-
 tests/qtest/libqtest.c | 27 +
 tests/qtest/libqtest.h | 14 +++
 5 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..55cc01bfb3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1148,7 +1148,17 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error 
**errp)
 }
 }
 }
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_register_csr_qtest_callback(void)
+{
+static gsize reinit_done;
+if (g_once_init_enter(&reinit_done)) {
+qtest_set_command_cb(csr_qtest_callback);
 
+g_once_init_leave(&reinit_done, 1);
+}
+}
+#endif
 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -1174,6 +1184,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 
 riscv_cpu_register_gdb_regs_for_features(cs);
+#ifndef CONFIG_USER_ONLY
+/* register callback for csr qtests */
+riscv_cpu_register_csr_qtest_callback();
+#endif
 
 #ifndef CONFIG_USER_ONLY
 if (cpu->cfg.debug) {
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..6d4bbec53c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -32,6 +32,8 @@
 #include "cpu_cfg.h"
 #include "qapi/qapi-types-common.h"
 #include "cpu-qom.h"
+#include "qemu/cutils.h"
+#include "sysemu/qtest.h"
 
 typedef struct CPUArchState CPURISCVState;
 
@@ -813,6 +815,7 @@ bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
+bool csr_qtest_callback(CharBackend *chr, gchar **words);
 
 extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58ef7079dc..f4f5128c9c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -29,7 +29,7 @@
 #include "sysemu/cpu-timers.h"
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
-
+#include "tests/qtest/libqtest.h"
 
 /* CSR function table public API */
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
@@ -4549,6 +4549,57 @@ static RISCVException write_jvt(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+#if !defined(CONFIG_USER_ONLY)
+static uint64_t csr_call(char *cmd, uint64_t cpu_num, int csrno,
+uint64_t *val)
+{
+RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
+CPURISCVState *env = &cpu->env;
+
+int ret = RISCV_EXCP_NONE;
+if (strcmp(cmd, "get_csr") == 0) {
+ret = riscv_csrrw(env, csrno, (target_ulong *)val, 0, 0);
+
+} else if (strcmp(cmd, "set_csr") == 0) {
+ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val, 
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
+}
+
+if (ret == RISCV_EXCP_NONE) {
+ret = 0;
+} else {
+g_assert_not_reached();
+}
+
+return ret;
+}
+
+bool csr_qtest_callback(CharBackend *chr, gchar **words)
+{
+if (strcmp(words[0], "csr") == 0) {
+
+uint64_t res, cpu;
+
+uint64_t val;
+int rc, csr;
+
+rc = qemu_strtou64(words[2], NULL, 0, &cpu);
+g_assert(rc == 0);
+rc = qemu_strtoi(words[3], NULL, 0, &csr);
+g_assert(rc == 0);
+rc = qemu_strtou64(words[4], NULL, 0, &val);
+g_assert(rc == 0);
+res = csr_call(words[1], cpu, csr, &val);
+
+qtest_send_prefix(chr);
+qtest_sendf(chr, "OK %"PRIx64" "TARGET_FMT_lx"\n", res, 
(target_ulong)val);
+
+return true;
+}
+
+return false;
+}
+#endif
+
 /*
  * Control and Status Register function table
  * riscv_csr_operations::predicate() must be provided for an implemented CSR
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index c7f6897d78..f8c3ff15a9 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -1205,6 +1205,33 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
 return 0;
 }
 
+static void qtest_rsp_csr(QTestState *s, uint64_t *val)
+{
+gchar **args;
+uint64_t ret;
+int rc;
+
+args = qtest_rsp_args(s, 3);
+
+rc = qemu_strtou64(args[1], NULL, 16, &ret);
+g_assert(rc == 0);
+rc = qemu_strtou64(args[2], NULL, 16, val);
+g_assert(rc == 0);
+
+g_strfreev(args);
+}
+
+uint64_t qtest_csr_call(QTestState *s, const char *name,
+ uint64_t cpu, int csr,
+ uint64_t *val)

[RFC PATCH v3 0/2] Support RISC-V CSR read/write in Qtest environment

2024-06-25 Thread Ivan Klokov
These patches add functionality for unit testing RISC-V-specific registers.
The first patch adds a Qtest backend, and the second implements a simple test.

---
v3:
   - Refactor, delete additions to libqos framework
---

Ivan Klokov (2):
  target/riscv: Add RISC-V CSR qtest support
  tests/qtest: QTest example for RISC-V CSR register

 target/riscv/cpu.c   | 14 ++
 target/riscv/cpu.h   |  3 ++
 target/riscv/csr.c   | 53 +-
 tests/qtest/libqtest.c   | 27 
 tests/qtest/libqtest.h   | 14 ++
 tests/qtest/meson.build  |  2 +
 tests/qtest/riscv-csr-test.c | 85 
 7 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/riscv-csr-test.c

-- 
2.34.1




[RFC PATCH v3 2/2] tests/qtest: QTest example for RISC-V CSR register

2024-06-25 Thread Ivan Klokov
Added demo for reading CSR register from qtest environment.

Signed-off-by: Ivan Klokov 
---
 tests/qtest/meson.build  |  2 +
 tests/qtest/riscv-csr-test.c | 85 
 2 files changed, 87 insertions(+)
 create mode 100644 tests/qtest/riscv-csr-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 12792948ff..45d651da99 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -259,6 +259,8 @@ qtests_s390x = \
 qtests_riscv32 = \
   (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? 
['sifive-e-aon-watchdog-test'] : [])
 
+qtests_riscv32 += ['riscv-csr-test']
+
 qos_test_ss = ss.source_set()
 qos_test_ss.add(
   'ac97-test.c',
diff --git a/tests/qtest/riscv-csr-test.c b/tests/qtest/riscv-csr-test.c
new file mode 100644
index 00..21a3646ae9
--- /dev/null
+++ b/tests/qtest/riscv-csr-test.c
@@ -0,0 +1,85 @@
+/*
+ * QTest testcase for RISC-V CSRs
+ *
+ * Copyright (c) 2024 Syntacore.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "libqtest.h"
+
+static uint64_t qcsr_call(QTestState *qts, const char *name, uint64_t cpu,
+   int csrno, uint64_t *val)
+{
+uint64_t res = 0;
+
+res = qtest_csr_call(qts, name, cpu, csrno, val);
+
+return res;
+}
+
+static int qcsr_get_csr(QTestState *qts, uint64_t cpu,
+int csrno, uint64_t *val)
+{
+int res;
+
+res = qcsr_call(qts, "get_csr", cpu, csrno, val);
+
+return res;
+}
+
+static int qcsr_set_csr(QTestState *qts, uint64_t cpu,
+int csrno, uint64_t *val)
+{
+int res;
+
+res = qcsr_call(qts, "set_csr", cpu, csrno, val);
+
+return res;
+}
+
+static void run_test_csr(void)
+{
+
+uint64_t res;
+uint64_t val = 0;
+
+res = qcsr_get_csr(global_qtest, 0, 0xf11, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0x100);
+
+val = 0xff;
+res = qcsr_set_csr(global_qtest, 0, 0x342, &val);
+g_assert_cmpint(res, ==, 0);
+
+val = 0;
+res = qcsr_get_csr(global_qtest, 0, 0x342, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0xff);
+
+qtest_quit(global_qtest);
+}
+
+int main(int argc, char **argv)
+{
+g_test_init(&argc, &argv, NULL);
+
+qtest_add_func("/cpu/csr", run_test_csr);
+
+qtest_start("-machine virt -cpu any,mvendorid=0x100");
+
+return g_test_run();
+
+}
-- 
2.34.1




[RFC PATCH v2 0/2] Support RISC-V CSR read/write in Qtest environment

2024-06-17 Thread Ivan Klokov
These patches add functionality for unit testing RISC-V-specific registers.
The first patch adds a Qtest backend, and the second implements a simple test.

---
v2:
   - Refactor unit test, add missed files
---

Ivan Klokov (2):
  Add RISC-V CSR qtest support
  QTest example for RISC-V CSR register

 target/riscv/cpu.c | 13 +
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c | 49 +-
 tests/qtest/libqos/csr.c   | 42 +
 tests/qtest/libqos/csr.h   | 16 +++
 tests/qtest/libqos/meson.build |  3 +++
 tests/qtest/libqtest.c | 27 +++
 tests/qtest/libqtest.h | 14 ++
 tests/qtest/meson.build|  2 ++
 tests/qtest/riscv-csr-test.c   | 47 
 10 files changed, 215 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/libqos/csr.c
 create mode 100644 tests/qtest/libqos/csr.h
 create mode 100644 tests/qtest/riscv-csr-test.c

-- 
2.34.1




[RFC PATCH v2 2/2] QTest example for RISC-V CSR register

2024-06-17 Thread Ivan Klokov
Added demo for reading CSR register from qtest environment.

Signed-off-by: Ivan Klokov 
---
 tests/qtest/meson.build  |  2 ++
 tests/qtest/riscv-csr-test.c | 47 
 2 files changed, 49 insertions(+)
 create mode 100644 tests/qtest/riscv-csr-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 12792948ff..45d651da99 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -259,6 +259,8 @@ qtests_s390x = \
 qtests_riscv32 = \
   (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? 
['sifive-e-aon-watchdog-test'] : [])
 
+qtests_riscv32 += ['riscv-csr-test']
+
 qos_test_ss = ss.source_set()
 qos_test_ss.add(
   'ac97-test.c',
diff --git a/tests/qtest/riscv-csr-test.c b/tests/qtest/riscv-csr-test.c
new file mode 100644
index 00..565395ac8e
--- /dev/null
+++ b/tests/qtest/riscv-csr-test.c
@@ -0,0 +1,47 @@
+/*
+ * QTest testcase for RISC-V CSRs
+ *
+ * Copyright (c) 2024 Syntacore.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "libqtest.h"
+
+#include "libqos/csr.h"
+
+static void run_test_csr(void)
+{
+
+uint64_t res;
+uint64_t val = 0;
+
+res = qcsr_get_csr(global_qtest, 0, 0xf11, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0x100);
+
+qtest_quit(global_qtest);
+}
+
+int main(int argc, char **argv)
+{
+g_test_init(&argc, &argv, NULL);
+
+qtest_add_func("/cpu/csr", run_test_csr);
+
+qtest_start("-machine virt -cpu any,mvendorid=0x100");
+
+return g_test_run();
+
+}
-- 
2.34.1




[RFC PATCH v2 1/2] Add RISC-V CSR qtest support

2024-06-17 Thread Ivan Klokov
The RISC-V architecture supports the creation of custom
CSR-mapped devices. It would be convenient to test them in the same way
as MMIO-mapped devices. To do this, a new call has been added
to read/write CSR registers.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu.c | 13 +
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c | 49 +-
 tests/qtest/libqos/csr.c   | 42 +
 tests/qtest/libqos/csr.h   | 16 +++
 tests/qtest/libqos/meson.build |  3 +++
 tests/qtest/libqtest.c | 27 +++
 tests/qtest/libqtest.h | 14 ++
 8 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/libqos/csr.c
 create mode 100644 tests/qtest/libqos/csr.h

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..f1df0f4de0 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1149,6 +1149,16 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error 
**errp)
 }
 }
 
+static void riscv_cpu_register_csr_qtest_callback(void)
+{
+static gsize reinit_done;
+if (g_once_init_enter(&reinit_done)) {
+qtest_set_command_cb(csr_qtest_callback);
+
+g_once_init_leave(&reinit_done, 1);
+}
+}
+
 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -1175,6 +1185,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 
 riscv_cpu_register_gdb_regs_for_features(cs);
 
+/* register callback for csr qtests */
+riscv_cpu_register_csr_qtest_callback();
+
 #ifndef CONFIG_USER_ONLY
 if (cpu->cfg.debug) {
 riscv_trigger_realize(&cpu->env);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..6d4bbec53c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -32,6 +32,8 @@
 #include "cpu_cfg.h"
 #include "qapi/qapi-types-common.h"
 #include "cpu-qom.h"
+#include "qemu/cutils.h"
+#include "sysemu/qtest.h"
 
 typedef struct CPUArchState CPURISCVState;
 
@@ -813,6 +815,7 @@ bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
+bool csr_qtest_callback(CharBackend *chr, gchar **words);
 
 extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58ef7079dc..82540ae5dc 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -29,7 +29,7 @@
 #include "sysemu/cpu-timers.h"
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
-
+#include "tests/qtest/libqtest.h"
 
 /* CSR function table public API */
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
@@ -4549,6 +4549,53 @@ static RISCVException write_jvt(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static uint64_t csr_call(char *cmd, uint64_t cpu_num, int csrno,
+uint64_t *val)
+{
+RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
+CPURISCVState *env = &cpu->env;
+
+int ret = RISCV_EXCP_NONE;
+if (strcmp(cmd, "get_csr") == 0) {
+ret = riscv_csrrw(env, csrno, (target_ulong *)val, 0, 0);
+
+} else if (strcmp(cmd, "set_csr") == 0) {
+ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val, 
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
+}
+
+if (ret == RISCV_EXCP_NONE) {
+ret = 0;
+}
+
+return ret;
+}
+
+bool csr_qtest_callback(CharBackend *chr, gchar **words)
+{
+if (strcmp(words[0], "csr") == 0) {
+
+uint64_t res, cpu;
+
+uint64_t val;
+int rc, csr;
+
+rc = qemu_strtou64(words[2], NULL, 0, &cpu);
+g_assert(rc == 0);
+rc = qemu_strtoi(words[3], NULL, 0, &csr);
+g_assert(rc == 0);
+rc = qemu_strtou64(words[4], NULL, 0, &val);
+g_assert(rc == 0);
+res = csr_call(words[1], cpu, csr, &val);
+
+qtest_send_prefix(chr);
+qtest_sendf(chr, "OK %"PRIx64" "TARGET_FMT_lx"\n", res, 
(target_ulong)val);
+
+return true;
+}
+
+return false;
+}
+
 /*
  * Control and Status Register function table
  * riscv_csr_operations::predicate() must be provided for an implemented CSR
diff --git a/tests/qtest/libqos/csr.c b/tests/qtest/libqos/csr.c
new file mode 100644
index 00..2dc52fc442
--- /dev/null
+++ b/tests/qtest/libqos/csr.c
@@ -0,0 +1,42 @@
+/*
+ * QTest RISC-V CSR driver
+ *
+ * Copyright (c) 2024 Syntacore
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "../libqtest.h"
+#include "csr.h"
+
+static uint64_t qcsr_call(QTestState *qts, const char *name, uint64_t cpu,
+  

[PATCH 1/2] Add RISC-V CSR qtest support

2024-06-13 Thread Ivan Klokov
The RISC-V architecture supports the creation of custom
CSR-mapped devices. It would be convenient to test them in the same way
as MMIO-mapped devices. To do this, a new call has been added
to read/write CSR registers.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu.c | 13 +
 target/riscv/cpu.h |  3 +++
 target/riscv/csr.c | 49 +-
 tests/qtest/libqos/meson.build |  3 +++
 tests/qtest/libqtest.c | 27 +++
 tests/qtest/libqtest.h | 14 ++
 6 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..f1df0f4de0 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1149,6 +1149,16 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error 
**errp)
 }
 }
 
+static void riscv_cpu_register_csr_qtest_callback(void)
+{
+static gsize reinit_done;
+if (g_once_init_enter(&reinit_done)) {
+qtest_set_command_cb(csr_qtest_callback);
+
+g_once_init_leave(&reinit_done, 1);
+}
+}
+
 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -1175,6 +1185,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 
 riscv_cpu_register_gdb_regs_for_features(cs);
 
+/* register callback for csr qtests */
+riscv_cpu_register_csr_qtest_callback();
+
 #ifndef CONFIG_USER_ONLY
 if (cpu->cfg.debug) {
 riscv_trigger_realize(&cpu->env);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..6d4bbec53c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -32,6 +32,8 @@
 #include "cpu_cfg.h"
 #include "qapi/qapi-types-common.h"
 #include "cpu-qom.h"
+#include "qemu/cutils.h"
+#include "sysemu/qtest.h"
 
 typedef struct CPUArchState CPURISCVState;
 
@@ -813,6 +815,7 @@ bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
+bool csr_qtest_callback(CharBackend *chr, gchar **words);
 
 extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58ef7079dc..82540ae5dc 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -29,7 +29,7 @@
 #include "sysemu/cpu-timers.h"
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
-
+#include "tests/qtest/libqtest.h"
 
 /* CSR function table public API */
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
@@ -4549,6 +4549,53 @@ static RISCVException write_jvt(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static uint64_t csr_call(char *cmd, uint64_t cpu_num, int csrno,
+uint64_t *val)
+{
+RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
+CPURISCVState *env = &cpu->env;
+
+int ret = RISCV_EXCP_NONE;
+if (strcmp(cmd, "get_csr") == 0) {
+ret = riscv_csrrw(env, csrno, (target_ulong *)val, 0, 0);
+
+} else if (strcmp(cmd, "set_csr") == 0) {
+ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val, 
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
+}
+
+if (ret == RISCV_EXCP_NONE) {
+ret = 0;
+}
+
+return ret;
+}
+
+bool csr_qtest_callback(CharBackend *chr, gchar **words)
+{
+if (strcmp(words[0], "csr") == 0) {
+
+uint64_t res, cpu;
+
+uint64_t val;
+int rc, csr;
+
+rc = qemu_strtou64(words[2], NULL, 0, &cpu);
+g_assert(rc == 0);
+rc = qemu_strtoi(words[3], NULL, 0, &csr);
+g_assert(rc == 0);
+rc = qemu_strtou64(words[4], NULL, 0, &val);
+g_assert(rc == 0);
+res = csr_call(words[1], cpu, csr, &val);
+
+qtest_send_prefix(chr);
+qtest_sendf(chr, "OK %"PRIx64" "TARGET_FMT_lx"\n", res, 
(target_ulong)val);
+
+return true;
+}
+
+return false;
+}
+
 /*
  * Control and Status Register function table
  * riscv_csr_operations::predicate() must be provided for an implemented CSR
diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 558eb4c24b..a944febbd8 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -25,6 +25,9 @@ libqos_srcs = files(
 # usb
 'usb.c',
 
+#riscv csr
+'csr.c',
+
 # qgraph devices:
 'e1000e.c',
 'i2c.c',
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index d8f80d335e..e0dfc95c04 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -1199,6 +1199,33 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
 return 0;
 }
 
+static void qtest_rsp_csr(QTestState *s, uint64_t *val)
+{
+gchar **args;
+uint64_t ret;
+int rc;
+
+a

[PATCH 2/2] QTest example for RISC-V CSR register

2024-06-13 Thread Ivan Klokov
Added demo for reading CSR register from qtest environment.

Signed-off-by: Ivan Klokov 
---
 tests/qtest/meson.build  |  2 ++
 tests/qtest/riscv-csr-test.c | 68 
 2 files changed, 70 insertions(+)
 create mode 100644 tests/qtest/riscv-csr-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 12792948ff..45d651da99 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -259,6 +259,8 @@ qtests_s390x = \
 qtests_riscv32 = \
   (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? 
['sifive-e-aon-watchdog-test'] : [])
 
+qtests_riscv32 += ['riscv-csr-test']
+
 qos_test_ss = ss.source_set()
 qos_test_ss.add(
   'ac97-test.c',
diff --git a/tests/qtest/riscv-csr-test.c b/tests/qtest/riscv-csr-test.c
new file mode 100644
index 00..715d5fe4b7
--- /dev/null
+++ b/tests/qtest/riscv-csr-test.c
@@ -0,0 +1,68 @@
+/*
+ * QTest testcase for RISC-V CSRs
+ *
+ * Copyright (c) 2024 Syntacore.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "qemu/error-report.h"
+
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
+#include "qom/object_interfaces.h"
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/qdev-properties.h"
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "libqtest.h"
+
+#include "libqos/csr.h"
+#include "libqos/libqos.h"
+
+static void run_test_csr(void)
+{
+
+uint64_t res;
+uint64_t val = 0;
+
+res = qcsr_get_csr(global_qtest, 0, 0xf11, &val);
+
+g_assert_cmpint(res, ==, 0);
+g_assert_cmpint(val, ==, 0x100);
+}
+
+int main(int argc, char **argv)
+{
+g_test_init(&argc, &argv, NULL);
+
+qtest_add_func("/cpu/csr", run_test_csr);
+
+qtest_start("--nographic -machine virt -cpu any,mvendorid=0x100");
+
+g_test_run();
+
+qtest_quit(global_qtest);
+
+return 0;
+
+}
-- 
2.34.1




[RFC PATCH 0/2] Support RISC-V CSR read/write in Qtest environment

2024-06-13 Thread Ivan Klokov
These patches add functionality for unit testing RISC-V-specific registers.
The first patch adds a Qtest backend, and the second implements a simple test.

Ivan Klokov (2):
  Add RISC-V CSR qtest support
  QTest example for RISC-V CSR register

 target/riscv/cpu.c | 13 +++
 target/riscv/cpu.h |  3 ++
 target/riscv/csr.c | 49 +++-
 tests/qtest/libqos/meson.build |  3 ++
 tests/qtest/libqtest.c | 27 ++
 tests/qtest/libqtest.h | 14 +++
 tests/qtest/meson.build|  2 +
 tests/qtest/riscv-csr-test.c   | 68 ++
 8 files changed, 178 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/riscv-csr-test.c

-- 
2.34.1




[PATCH 1/1] target/riscv: pmp: Ignore writes when RW=01 and MML=0

2023-12-20 Thread Ivan Klokov
This patch changes behavior on writing RW=01 to pmpcfg with MML=0.
RWX filed is form of collective WARL with the combination of
pmpcfg.RW=01 remains reserved for future standard use.

According to definition of WARL writing the CSR has no other side
effect. But current implementation change architectural state and
change system behavior. After writing we will get unreadable-unwriteble
region regardless on the previous state.

On the other side WARL said that we should read legal value and nothing
says about what we should write. Current behavior change system state
regardless of whether we read this register or not.

Fixes: ac66f2f0 ("target/riscv: pmp: Ignore writes when RW=01")

Signed-off-by: Ivan Klokov 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 162e88a90a..c0b814699e 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -126,7 +126,7 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t 
pmp_index, uint8_t val)
 /* If !mseccfg.MML then ignore writes with encoding RW=01 */
 if ((val & PMP_WRITE) && !(val & PMP_READ) &&
 !MSECCFG_MML_ISSET(env)) {
-val &= ~(PMP_WRITE | PMP_READ);
+return false;
 }
 env->pmp_state.pmp[pmp_index].cfg_reg = val;
 pmp_update_rule_addr(env, pmp_index);
-- 
2.34.1




[PATCH 1/1] target/riscv: Clear vstart_qe_zero flag

2023-12-14 Thread Ivan Klokov
The vstart_qe_zero flag is set at the beginning of the translation
phase from the env->vstart variable. During the execution phase, some
instructions may change env->vstart, but the flag remains the same as
at the start of the block. With some combinations of instructions this
causes an illegal instruction exception. This patch simultaneously
updates flag and env->vstart and to avoid inconsistency.

Signed-off-by: Ivan Klokov 
---
 target/riscv/insn_trans/trans_rvbf16.c.inc |  6 +-
 target/riscv/insn_trans/trans_rvv.c.inc| 88 +++---
 target/riscv/insn_trans/trans_rvvk.c.inc   | 12 +--
 target/riscv/translate.c   | 12 ++-
 4 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc 
b/target/riscv/insn_trans/trans_rvbf16.c.inc
index 4e39c00884..2867bbc2bb 100644
--- a/target/riscv/insn_trans/trans_rvbf16.c.inc
+++ b/target/riscv/insn_trans/trans_rvbf16.c.inc
@@ -86,7 +86,7 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, 
arg_vfncvtbf16_f_f_w *a)
ctx->cfg_ptr->vlen / 8,
ctx->cfg_ptr->vlen / 8, data,
gen_helper_vfncvtbf16_f_f_w);
-mark_vs_dirty(ctx);
+finalize_rvv_inst(ctx);
 gen_set_label(over);
 return true;
 }
@@ -115,7 +115,7 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, 
arg_vfwcvtbf16_f_f_v *a)
ctx->cfg_ptr->vlen / 8,
ctx->cfg_ptr->vlen / 8, data,
gen_helper_vfwcvtbf16_f_f_v);
-mark_vs_dirty(ctx);
+finalize_rvv_inst(ctx);
 gen_set_label(over);
 return true;
 }
@@ -146,7 +146,7 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, 
arg_vfwmaccbf16_vv *a)
ctx->cfg_ptr->vlen / 8,
ctx->cfg_ptr->vlen / 8, data,
gen_helper_vfwmaccbf16_vv);
-mark_vs_dirty(ctx);
+finalize_rvv_inst(ctx);
 gen_set_label(over);
 return true;
 }
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 78bd363310..fcf49f7352 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -167,7 +167,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, 
TCGv s2)
 
 gen_helper_vsetvl(dst, tcg_env, s1, s2);
 gen_set_gpr(s, rd, dst);
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 
 gen_update_pc(s, s->cur_insn_len);
 lookup_and_goto_ptr(s);
@@ -187,7 +187,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, 
TCGv s2)
 
 gen_helper_vsetvl(dst, tcg_env, s1, s2);
 gen_set_gpr(s, rd, dst);
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 gen_update_pc(s, s->cur_insn_len);
 lookup_and_goto_ptr(s);
 s->base.is_jmp = DISAS_NORETURN;
@@ -639,7 +639,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, 
uint32_t data,
 fn(dest, mask, base, tcg_env, desc);
 
 if (!is_store) {
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 }
 
 gen_set_label(over);
@@ -800,7 +800,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, 
uint32_t rs2,
 fn(dest, mask, base, stride, tcg_env, desc);
 
 if (!is_store) {
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 }
 
 gen_set_label(over);
@@ -907,7 +907,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, 
uint32_t vs2,
 fn(dest, mask, base, index, tcg_env, desc);
 
 if (!is_store) {
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 }
 
 gen_set_label(over);
@@ -1044,7 +1044,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, 
uint32_t data,
 
 fn(dest, mask, base, tcg_env, desc);
 
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 gen_set_label(over);
 return true;
 }
@@ -1105,7 +1105,7 @@ static bool ldst_whole_trans(uint32_t vd, uint32_t rs1, 
uint32_t nf,
 fn(dest, base, tcg_env, desc);
 
 if (!is_store) {
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 }
 gen_set_label(over);
 
@@ -1202,7 +1202,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn 
*gvec_fn,
tcg_env, s->cfg_ptr->vlen / 8,
s->cfg_ptr->vlen / 8, data, fn);
 }
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 gen_set_label(over);
 return true;
 }
@@ -1257,7 +1257,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, 
uint32_t vs2, uint32_t vm,
 
 fn(dest, mask, src1, src2, tcg_env, desc);
 
-mark_vs_dirty(s);
+finalize_rvv_inst(s);
 gen_set_label(over);
 return true;
 }
@@ -1283,7 +1283,7 @@ do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn 
*gvec_fn,
 gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->r

[PATCH 1/1] target/riscv/pmp: Use hwaddr instead of target_ulong for RV32

2023-11-23 Thread Ivan Klokov
The Sv32 page-based virtual-memory scheme described in RISCV privileged
spec Section 5.3 supports 34-bit physical addresses for RV32, so the
PMP scheme must support addresses wider than XLEN for RV32. However,
PMP address register format is still 32 bit wide.

Signed-off-by: Ivan Klokov 
---
 target/riscv/pmp.c | 26 --
 target/riscv/pmp.h |  8 
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 162e88a90a..dff9512c3f 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -150,8 +150,7 @@ void pmp_unlock_entries(CPURISCVState *env)
 }
 }
 
-static void pmp_decode_napot(target_ulong a, target_ulong *sa,
- target_ulong *ea)
+static void pmp_decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea)
 {
 /*
  * ...aaa0   8-byte NAPOT range
@@ -173,8 +172,8 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t 
pmp_index)
 uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg;
 target_ulong this_addr = env->pmp_state.pmp[pmp_index].addr_reg;
 target_ulong prev_addr = 0u;
-target_ulong sa = 0u;
-target_ulong ea = 0u;
+hwaddr sa = 0u;
+hwaddr ea = 0u;
 
 if (pmp_index >= 1u) {
 prev_addr = env->pmp_state.pmp[pmp_index - 1].addr_reg;
@@ -227,8 +226,7 @@ void pmp_update_rule_nums(CPURISCVState *env)
 }
 }
 
-static int pmp_is_in_range(CPURISCVState *env, int pmp_index,
-   target_ulong addr)
+static int pmp_is_in_range(CPURISCVState *env, int pmp_index, hwaddr addr)
 {
 int result = 0;
 
@@ -305,14 +303,14 @@ static bool pmp_hart_has_privs_default(CPURISCVState 
*env, pmp_priv_t privs,
  * Return true if a pmp rule match or default match
  * Return false if no match
  */
-bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
+bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
 target_ulong size, pmp_priv_t privs,
 pmp_priv_t *allowed_privs, target_ulong mode)
 {
 int i = 0;
 int pmp_size = 0;
-target_ulong s = 0;
-target_ulong e = 0;
+hwaddr s = 0;
+hwaddr e = 0;
 
 /* Short cut if no rules */
 if (0 == pmp_get_num_rules(env)) {
@@ -624,12 +622,12 @@ target_ulong mseccfg_csr_read(CPURISCVState *env)
  * To avoid this we return a size of 1 (which means no caching) if the PMP
  * region only covers partial of the TLB page.
  */
-target_ulong pmp_get_tlb_size(CPURISCVState *env, target_ulong addr)
+target_ulong pmp_get_tlb_size(CPURISCVState *env, hwaddr addr)
 {
-target_ulong pmp_sa;
-target_ulong pmp_ea;
-target_ulong tlb_sa = addr & ~(TARGET_PAGE_SIZE - 1);
-target_ulong tlb_ea = tlb_sa + TARGET_PAGE_SIZE - 1;
+hwaddr pmp_sa;
+hwaddr pmp_ea;
+hwaddr tlb_sa = addr & ~(TARGET_PAGE_SIZE - 1);
+hwaddr tlb_ea = tlb_sa + TARGET_PAGE_SIZE - 1;
 int i;
 
 /*
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
index 9af8614cd4..f5c10ce85c 100644
--- a/target/riscv/pmp.h
+++ b/target/riscv/pmp.h
@@ -53,8 +53,8 @@ typedef struct {
 } pmp_entry_t;
 
 typedef struct {
-target_ulong sa;
-target_ulong ea;
+hwaddr sa;
+hwaddr ea;
 } pmp_addr_t;
 
 typedef struct {
@@ -73,11 +73,11 @@ target_ulong mseccfg_csr_read(CPURISCVState *env);
 void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
target_ulong val);
 target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
-bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
+bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
 target_ulong size, pmp_priv_t privs,
 pmp_priv_t *allowed_privs,
 target_ulong mode);
-target_ulong pmp_get_tlb_size(CPURISCVState *env, target_ulong addr);
+target_ulong pmp_get_tlb_size(CPURISCVState *env, hwaddr addr);
 void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
 void pmp_update_rule_nums(CPURISCVState *env);
 uint32_t pmp_get_num_rules(CPURISCVState *env);
-- 
2.34.1




[PATCH v2 0/2] Fix mmu translation with H extension

2023-11-20 Thread Ivan Klokov
A series of patches that correct the conversion of virtual addresses 
to physical ones. Correct exception for mbare mode and fix MXR bit 
behavior with MPV\MPRV bits.
---
v2:
   - Fix typo, specify the fixed commits
---

Ivan Klokov (2):
  target/riscv/cpu_helper.c: Invalid exception on MMU translation stage
  target/riscv/cpu_helper.c: Fix mxr bit behavior

 target/riscv/cpu_helper.c | 54 +++
 1 file changed, 27 insertions(+), 27 deletions(-)

-- 
2.34.1




[PATCH v2 2/2] target/riscv/cpu_helper.c: Fix mxr bit behavior

2023-11-20 Thread Ivan Klokov
According to RISCV Specification sect 9.5 on two stage translation when
V=1 the vsstatus(mstatus in QEMU's terms) field MXR, which makes
execute-only pages readable, only overrides VS-stage page protection.
Setting MXR at HS-level(mstatus_hs), however, overrides both VS-stage
and G-stage execute-only permissions.

The hypervisor extension changes the behavior of MXR\MPV\MPRV bits.
Due to RISCV Specification sect. 9.4.1 when MPRV=1, explicit memory
accesses are translated and protected, and endianness is applied, as
though the current virtualization mode were set to MPV and the current
nominal privilege mode were set to MPP. vsstatus.MXR makes readable
those pages marked executable at the VS translation stage.

Fixes: 36a18664ba ("target/riscv: Implement second stage MMU")

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu_helper.c | 24 
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9ff0952e46..e7e23b34f4 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1032,13 +1032,29 @@ restart:
 prot |= PAGE_WRITE;
 }
 if (pte & PTE_X) {
-bool mxr;
+bool mxr = false;
 
-if (first_stage == true) {
+/*
+ * Use mstatus for first stage or for the second stage without
+ * virt_enabled (MPRV+MPV)
+ */
+if (first_stage || !env->virt_enabled) {
 mxr = get_field(env->mstatus, MSTATUS_MXR);
-} else {
-mxr = get_field(env->vsstatus, MSTATUS_MXR);
 }
+
+/* MPRV+MPV case, check VSSTATUS */
+if (first_stage && two_stage && !env->virt_enabled) {
+mxr |= get_field(env->vsstatus, MSTATUS_MXR);
+}
+
+/*
+ * Setting MXR at HS-level overrides both VS-stage and G-stage
+ * execute-only permissions
+ */
+if (env->virt_enabled) {
+mxr |= get_field(env->mstatus_hs, MSTATUS_MXR);
+}
+
 if (mxr) {
 prot |= PAGE_READ;
 }
-- 
2.34.1




[PATCH v2 1/2] target/riscv/cpu_helper.c: Invalid exception on MMU translation stage

2023-11-20 Thread Ivan Klokov
According to RISCV privileged spec sect. 5.3.2 Virtual Address Translation 
Process
access-fault exceptions may raise only after PMA/PMP check. Current 
implementation
generates an access-fault for mbare mode even if there were no PMA/PMP errors.
This patch removes the erroneous MMU mode check and generates an access-fault
exception based on the pmp_violation flag only.

Fixes: 1448689c7b ("target/riscv: Allow specifying MMU stage")

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu_helper.c | 30 +++---
 1 file changed, 7 insertions(+), 23 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b7af69de53..9ff0952e46 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1143,47 +1143,31 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
-int page_fault_exceptions, vm;
-uint64_t stap_mode;
-
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-stap_mode = SATP32_MODE;
-} else {
-stap_mode = SATP64_MODE;
-}
-
-if (first_stage) {
-vm = get_field(env->satp, stap_mode);
-} else {
-vm = get_field(env->hgatp, stap_mode);
-}
-
-page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
 
 switch (access_type) {
 case MMU_INST_FETCH:
 if (env->virt_enabled && !first_stage) {
 cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
 }
 break;
 case MMU_DATA_LOAD:
 if (two_stage && !first_stage) {
 cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
 }
 break;
 case MMU_DATA_STORE:
 if (two_stage && !first_stage) {
 cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_STORE_PAGE_FAULT :
-RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
+RISCV_EXCP_STORE_PAGE_FAULT;
 }
 break;
 default:
-- 
2.34.1




[PATCH 0/2] Fix mmu translation with H extension

2023-11-20 Thread Ivan Klokov
A series of patches that correct the conversion of virtual addresses 
to physical ones. Correct exception for mbare mode and fix MXR bit 
behavior with MPV\MPV bits.

Ivan Klokov (2):
  target/riscv/cpu_helper.c: Invalid exception on MMU translation stage
  target/riscv/cpu_helper.c: Fix mxr bit behavior

 target/riscv/cpu_helper.c | 54 +++
 1 file changed, 27 insertions(+), 27 deletions(-)

-- 
2.34.1




[PATCH 1/2] target/riscv/cpu_helper.c: Invalid exception on MMU translation stage

2023-11-20 Thread Ivan Klokov
According to RISCV priveleged spec sect. 5.3.2 Virtual Address Translation 
Process
access-fault exceptions may raise only after PMA/PMP check. Current 
implementation
generates an acces-fault for mbare mode even if there were no PMA/PMP errors.
This patch removes the erroneous MMU mode check and generates an access-fault
exception based on the pmp_violation flag only.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu_helper.c | 30 +++---
 1 file changed, 7 insertions(+), 23 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b7af69de53..9ff0952e46 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1143,47 +1143,31 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
-int page_fault_exceptions, vm;
-uint64_t stap_mode;
-
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-stap_mode = SATP32_MODE;
-} else {
-stap_mode = SATP64_MODE;
-}
-
-if (first_stage) {
-vm = get_field(env->satp, stap_mode);
-} else {
-vm = get_field(env->hgatp, stap_mode);
-}
-
-page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
 
 switch (access_type) {
 case MMU_INST_FETCH:
 if (env->virt_enabled && !first_stage) {
 cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
 }
 break;
 case MMU_DATA_LOAD:
 if (two_stage && !first_stage) {
 cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
 }
 break;
 case MMU_DATA_STORE:
 if (two_stage && !first_stage) {
 cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
 } else {
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_STORE_PAGE_FAULT :
-RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+cs->exception_index = pmp_violation ?
+RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
+RISCV_EXCP_STORE_PAGE_FAULT;
 }
 break;
 default:
-- 
2.34.1




[PATCH 2/2] target/riscv/cpu_helper.c: Fix mxr bit behavior

2023-11-20 Thread Ivan Klokov
According to RISCV Specification sect 9.5 on two stage translation when
V=1 the vsstatus(mstatus in QEMU's terms) field MXR, which makes
execute-only pages readable, only overrides VS-stage page protection.
Setting MXR at HS-level(mstatus_hs), however, overrides both VS-stage
and G-stage execute-only permissions.

The hypervisor extension changes the behavior of MXR\MPV\MPRV bits.
Due to RISCV Specification sect. 9.4.1 when MPRV=1, explicit memory
accesses are translated and protected, and endianness is applied, as
though the current virtualization mode were set to MPV and the current
nominal privilege mode were set to MPP. vsstatus.MXR makes readable
those pages marked executable at the VS translation stage.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu_helper.c | 24 
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9ff0952e46..e7e23b34f4 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1032,13 +1032,29 @@ restart:
 prot |= PAGE_WRITE;
 }
 if (pte & PTE_X) {
-bool mxr;
+bool mxr = false;
 
-if (first_stage == true) {
+/*
+ * Use mstatus for first stage or for the second stage without
+ * virt_enabled (MPRV+MPV)
+ */
+if (first_stage || !env->virt_enabled) {
 mxr = get_field(env->mstatus, MSTATUS_MXR);
-} else {
-mxr = get_field(env->vsstatus, MSTATUS_MXR);
 }
+
+/* MPRV+MPV case, check VSSTATUS */
+if (first_stage && two_stage && !env->virt_enabled) {
+mxr |= get_field(env->vsstatus, MSTATUS_MXR);
+}
+
+/*
+ * Setting MXR at HS-level overrides both VS-stage and G-stage
+ * execute-only permissions
+ */
+if (env->virt_enabled) {
+mxr |= get_field(env->mstatus_hs, MSTATUS_MXR);
+}
+
 if (mxr) {
 prot |= PAGE_READ;
 }
-- 
2.34.1




[PATCH v5 1/1] target/riscv: Add RVV registers to log

2023-06-29 Thread Ivan Klokov
Print RvV extension register to log if VPU option is enabled.

Signed-off-by: Ivan Klokov 
---
v5:
   - Fix typo, move macros out of function, direct access to cfg.vlen field. 
---
 target/riscv/cpu.c | 57 +-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 881bddf393..ff29573b1f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -55,6 +55,17 @@ struct isa_ext_data {
 #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
 {#_name, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
 
+/*
+ * From vector_helper.c
+ * Note that vector data is stored in host-endian 64-bit chunks,
+ * so addressing bytes needs a host-endian fixup.
+ */
+#if HOST_BIG_ENDIAN
+#define BYTE(x)   ((x) ^ 7)
+#else
+#define BYTE(x)   (x)
+#endif
+
 /*
  * Here are the ordering rules of extension naming defined by RISC-V
  * specification :
@@ -183,6 +194,14 @@ const char * const riscv_fpr_regnames[] = {
 "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_rvv_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
+  "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
+  "v14", "v15", "v16", "v17", "v18", "v19", "v20",
+  "v21", "v22", "v23", "v24", "v25", "v26", "v27",
+  "v28", "v29", "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -608,7 +627,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
-int i;
+int i, j;
+uint8_t *p;
 
 #if !defined(CONFIG_USER_ONLY)
 if (riscv_has_ext(env, RVH)) {
@@ -692,6 +712,41 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (riscv_has_ext(env, RVV) && (flags & CPU_DUMP_VPU)) {
+static const int dump_rvv_csrs[] = {
+CSR_VSTART,
+CSR_VXSAT,
+CSR_VXRM,
+CSR_VCSR,
+CSR_VL,
+CSR_VTYPE,
+CSR_VLENB,
+};
+for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
+int csrno = dump_rvv_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
+uint16_t vlenb = cpu->cfg.vlen >> 3;
+
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
+p = (uint8_t *)env->vreg;
+for (j = vlenb - 1 ; j >= 0; j--) {
+qemu_fprintf(f, "%02x", *(p + i * vlenb + BYTE(j)));
+}
+qemu_fprintf(f, "\n");
+}
+}
 }
 
 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
-- 
2.34.1




[PATCH v4 1/1] target/riscv: Add RVV registers to log

2023-06-22 Thread Ivan Klokov
Print RvV extesion register to log if VPU option is enabled.

Signed-off-by: Ivan Klokov 
---
v4:
   - General part of patch has been merged, rebase riscv part and resend. 
---
 target/riscv/cpu.c | 56 +-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index fb8458bf74..b23f3fde0d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -183,6 +183,14 @@ const char * const riscv_fpr_regnames[] = {
 "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_rvv_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
+  "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
+  "v14", "v15", "v16", "v17", "v18", "v19", "v20",
+  "v21", "v22", "v23", "v24", "v25", "v26", "v27",
+  "v28", "v29", "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -611,7 +619,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
-int i;
+int i, j;
+uint8_t *p;
 
 #if !defined(CONFIG_USER_ONLY)
 if (riscv_has_ext(env, RVH)) {
@@ -695,6 +704,51 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (riscv_has_ext(env, RVV) && (flags & CPU_DUMP_VPU)) {
+static const int dump_rvv_csrs[] = {
+CSR_VSTART,
+CSR_VXSAT,
+CSR_VXRM,
+CSR_VCSR,
+CSR_VL,
+CSR_VTYPE,
+CSR_VLENB,
+};
+for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
+int csrno = dump_rvv_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
+uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+
+/*
+ * From vector_helper.c
+ * Note that vector data is stored in host-endian 64-bit chunks,
+ * so addressing bytes needs a host-endian fixup.
+ */
+#if HOST_BIG_ENDIAN
+#define BYTE(x)   ((x) ^ 7)
+#else
+#define BYTE(x)   (x)
+#endif
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
+p = (uint8_t *)env->vreg;
+for (j = vlenb - 1 ; j >= 0; j--) {
+qemu_fprintf(f, "%02x", *(p + i * vlenb + BYTE(j)));
+}
+qemu_fprintf(f, "\n");
+}
+}
 }
 
 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
-- 
2.34.1




[PATCH] hw/intc/riscv_aplic: Zero init APLIC internal state

2023-04-13 Thread Ivan Klokov
Since g_new is used to initialize the RISCVAPLICState->state structure,
in some case we get behavior that is not as expected. This patch
changes this to g_new0, which allows to initialize the APLIC in the correct 
state.

Signed-off-by: Ivan Klokov 
---
 hw/intc/riscv_aplic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index cfd007e629..71591d44bf 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -803,7 +803,7 @@ static void riscv_aplic_realize(DeviceState *dev, Error 
**errp)
 
 aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
 aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
-aplic->state = g_new(uint32_t, aplic->num_irqs);
+aplic->state = g_new0(uint32_t, aplic->num_irqs);
 aplic->target = g_new0(uint32_t, aplic->num_irqs);
 if (!aplic->msimode) {
 for (i = 0; i < aplic->num_irqs; i++) {
-- 
2.34.1




[PATCH v3 2/2] target/riscv: Add RVV registers to log

2023-04-10 Thread Ivan Klokov
Print RvV extesion register to log if VPU option is enabled.

Signed-off-by: Ivan Klokov 
---
 target/riscv/cpu.c | 56 +-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5bc0005cc7..cfd063a5dc 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -172,6 +172,14 @@ const char * const riscv_fpr_regnames[] = {
   "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_rvv_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
+  "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
+  "v14", "v15", "v16", "v17", "v18", "v19", "v20",
+  "v21", "v22", "v23", "v24", "v25", "v26", "v27",
+  "v28", "v29", "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -422,7 +430,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
-int i;
+int i, j;
+uint8_t *p;
 
 #if !defined(CONFIG_USER_ONLY)
 if (riscv_has_ext(env, RVH)) {
@@ -506,6 +515,51 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (riscv_has_ext(env, RVV) && (flags & CPU_DUMP_VPU)) {
+static const int dump_rvv_csrs[] = {
+CSR_VSTART,
+CSR_VXSAT,
+CSR_VXRM,
+CSR_VCSR,
+CSR_VL,
+CSR_VTYPE,
+CSR_VLENB,
+};
+for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
+int csrno = dump_rvv_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
+uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+
+/*
+ * From vector_helper.c
+ * Note that vector data is stored in host-endian 64-bit chunks,
+ * so addressing bytes needs a host-endian fixup.
+ */
+#if HOST_BIG_ENDIAN
+#define BYTE(x)   ((x) ^ 7)
+#else
+#define BYTE(x)   (x)
+#endif
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
+p = (uint8_t *)env->vreg;
+for (j = vlenb - 1 ; j >= 0; j--) {
+qemu_fprintf(f, "%02x", *(p + i * vlenb + BYTE(j)));
+}
+qemu_fprintf(f, "\n");
+}
+}
 }
 
 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
-- 
2.34.1




[PATCH v3 0/2] Support for print to log vector extension registers

2023-04-10 Thread Ivan Klokov
The patch added an ability to include VPU registers in the 'cpu' logging.
---
v3:
   - split of the patch into two parts: general and RISC-V specific
---

Ivan Klokov (2):
  util/log: Add vector registers to log
  target/riscv: Add RVV registers to log

 accel/tcg/cpu-exec.c  |  3 +++
 include/hw/core/cpu.h |  2 ++
 include/qemu/log.h|  1 +
 target/riscv/cpu.c| 56 ++-
 util/log.c|  2 ++
 5 files changed, 63 insertions(+), 1 deletion(-)

-- 
2.34.1




[PATCH v3 1/2] util/log: Add vector registers to log

2023-04-10 Thread Ivan Klokov
Added QEMU option 'vpu' to log vector extension registers such as gpr\fpu.

Signed-off-by: Ivan Klokov 
---
 accel/tcg/cpu-exec.c  | 3 +++
 include/hw/core/cpu.h | 2 ++
 include/qemu/log.h| 1 +
 util/log.c| 2 ++
 4 files changed, 8 insertions(+)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 56aaf58b9d..0dca69fccb 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -319,6 +319,9 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
 #if defined(TARGET_I386)
 flags |= CPU_DUMP_CCOP;
 #endif
+if (qemu_loglevel_mask(CPU_LOG_TB_VPU)) {
+flags |= CPU_DUMP_VPU;
+}
 cpu_dump_state(cpu, logfile, flags);
 qemu_log_unlock(logfile);
 }
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 75689bff02..7c9d25ff45 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -545,11 +545,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
  * @CPU_DUMP_CODE:
  * @CPU_DUMP_FPU: dump FPU register state, not just integer
  * @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
+ * @CPU_DUMP_VPU: dump VPU registers
  */
 enum CPUDumpFlags {
 CPU_DUMP_CODE = 0x0001,
 CPU_DUMP_FPU  = 0x0002,
 CPU_DUMP_CCOP = 0x0004,
+CPU_DUMP_VPU  = 0x0008,
 };
 
 /**
diff --git a/include/qemu/log.h b/include/qemu/log.h
index c5643d8dd5..df59bfabcd 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -35,6 +35,7 @@ bool qemu_log_separate(void);
 /* LOG_STRACE is used for user-mode strace logging. */
 #define LOG_STRACE (1 << 19)
 #define LOG_PER_THREAD (1 << 20)
+#define CPU_LOG_TB_VPU (1 << 21)
 
 /* Lock/unlock output. */
 
diff --git a/util/log.c b/util/log.c
index 7837ff9917..93dccee7b8 100644
--- a/util/log.c
+++ b/util/log.c
@@ -495,6 +495,8 @@ const QEMULogItem qemu_log_items[] = {
   "log every user-mode syscall, its input, and its result" },
 { LOG_PER_THREAD, "tid",
   "open a separate log file per thread; filename must contain '%d'" },
+{ CPU_LOG_TB_VPU, "vpu",
+  "include VPU registers in the 'cpu' logging" },
 { 0, NULL, NULL },
 };
 
-- 
2.34.1




[PATCH v2] target/riscv: Add RVV registers to log

2023-03-09 Thread Ivan Klokov
Added QEMU option 'rvv' to add RISC-V RVV registers to log like regular regs.

Signed-off-by: Ivan Klokov 
---
v2:
   - fix option name
   - fix byte ordering
---
 accel/tcg/cpu-exec.c  |  3 +++
 include/hw/core/cpu.h |  2 ++
 include/qemu/log.h|  1 +
 target/riscv/cpu.c| 59 ++-
 util/log.c|  2 ++
 5 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 56aaf58b9d..0dca69fccb 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -319,6 +319,9 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
 #if defined(TARGET_I386)
 flags |= CPU_DUMP_CCOP;
 #endif
+if (qemu_loglevel_mask(CPU_LOG_TB_VPU)) {
+flags |= CPU_DUMP_VPU;
+}
 cpu_dump_state(cpu, logfile, flags);
 qemu_log_unlock(logfile);
 }
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 75689bff02..7c9d25ff45 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -545,11 +545,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
  * @CPU_DUMP_CODE:
  * @CPU_DUMP_FPU: dump FPU register state, not just integer
  * @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
+ * @CPU_DUMP_VPU: dump VPU registers
  */
 enum CPUDumpFlags {
 CPU_DUMP_CODE = 0x0001,
 CPU_DUMP_FPU  = 0x0002,
 CPU_DUMP_CCOP = 0x0004,
+CPU_DUMP_VPU  = 0x0008,
 };
 
 /**
diff --git a/include/qemu/log.h b/include/qemu/log.h
index c5643d8dd5..df59bfabcd 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -35,6 +35,7 @@ bool qemu_log_separate(void);
 /* LOG_STRACE is used for user-mode strace logging. */
 #define LOG_STRACE (1 << 19)
 #define LOG_PER_THREAD (1 << 20)
+#define CPU_LOG_TB_VPU (1 << 21)
 
 /* Lock/unlock output. */
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5bc0005cc7..0b16c9c8e3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -172,6 +172,14 @@ const char * const riscv_fpr_regnames[] = {
   "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_rvv_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
+  "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
+  "v14", "v15", "v16", "v17", "v18", "v19", "v20",
+  "v21", "v22", "v23", "v24", "v25", "v26", "v27",
+  "v28", "v29", "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -422,7 +430,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
-int i;
+int i, j;
+uint8_t *p;
 
 #if !defined(CONFIG_USER_ONLY)
 if (riscv_has_ext(env, RVH)) {
@@ -506,6 +515,54 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (riscv_has_ext(env, RVV)) {
+if (flags & CPU_DUMP_VPU) {
+
+static const int dump_rvv_csrs[] = {
+CSR_VSTART,
+CSR_VXSAT,
+CSR_VXRM,
+CSR_VCSR,
+CSR_VL,
+CSR_VTYPE,
+CSR_VLENB,
+};
+for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
+int csrno = dump_rvv_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
+uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+
+/*
+ * From vector_helper.c
+ * Note that vector data is stored in host-endian 64-bit chunks,
+ * so addressing bytes needs a host-endian fixup.
+ */
+#if HOST_BIG_ENDIAN
+#define BYTE(x)   ((x) ^ 7)
+#else
+#define BYTE(x)   (x)
+#endif
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
+p = (uint8_t *)env->vreg;
+for (j = vlenb - 1 ; j >= 0; j--) {
+qemu_fprintf(f, "%02

Re: [PATCH] Fix slli_uw decoding

2023-03-06 Thread Ivan Klokov
Hello guys. I would be really appreciate if you look this patch.It would be nice to merge it to new release 8.0 27.02.2023, 12:02, "Ivan Klokov" :The decoding of the slli_uw currently contains decodingerror: shamt part of opcode has six bits, not five.Fixes 3de1fb71("target/riscv: update disas.c for xnor/orn/andn and slli.uw")Signed-off-by: Ivan Klokov <ivan.klo...@syntacore.com>--- disas/riscv.c | 8  1 file changed, 4 insertions(+), 4 deletions(-)diff --git a/disas/riscv.c b/disas/riscv.cindex ddda687c13..03cfefb0d3 100644--- a/disas/riscv.c+++ b/disas/riscv.c@@ -1647,7 +1647,7 @@ const rv_opcode_data opcode_data[] = { { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },- { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },+ { "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },@@ -2617,10 +2617,10 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) switch (((inst >> 12) & 0b111)) { case 0: op = rv_op_addiw; break; case 1:- switch (((inst >> 25) & 0b111)) {+ switch (((inst >> 26) & 0b11)) { case 0: op = rv_op_slliw; break;- case 4: op = rv_op_slli_uw; break;- case 48:+ case 2: op = rv_op_slli_uw; break;+ case 24: switch ((inst >> 20) & 0b1) {     case 0b0: op = rv_op_clzw; break; case 0b1: op = rv_op_ctzw; break;--2.34.1   -- Kind regards,Ivan Klokov 

Re: [PATCH] [PATCH] disas/riscv Fix ctzw disassemble

2023-03-01 Thread Ivan Klokov

Hello, Palmer!

Thanks for your reviewing

I'm sorry, I sent V2 patch, but forgot to add the appropriate tag.

Please see 
https://lists.nongnu.org/archive/html/qemu-devel/2023-02/msg05278.html


It was also reviewed by Daniel Henrique Barboza and weiwei

02.03.2023 3:32, Palmer Dabbelt пишет:
On Fri, 17 Feb 2023 07:45:14 PST (-0800), dbarb...@ventanamicro.com 
wrote:



On 2/17/23 12:14, Ivan Klokov wrote:

Due to typo in opcode list, ctzw is disassembled as clzw instruction.



The code was added by 02c1b569a15b4b06a so I believe a "Fixes:" tag 
is in

order:

Fixes: 02c1b569a15b ("disas/riscv: Add Zb[abcs] instructions")


Signed-off-by: Ivan Klokov 
---
  disas/riscv.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index ddda687c13..d0639cd047 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -1644,7 +1644,7 @@ const rv_opcode_data opcode_data[] = {
  { "minu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
  { "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
  { "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
-    { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+    { "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
  { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },



Does the order matter here? This patch is putting ctzw before clzw, 
but 20 lines

or so before we have "clz" after "ctz".


IIUC the ordering does matter: the values in rv_op_* need to match the 
index of opcode_data[].  decode_inst_opcode() fills out rv_op_*, and 
then the various decode bits (with format_inst() being the most 
relevant as it looks at the name field).


So unless I'm missing something, the correct patch should look like

   diff --git a/disas/riscv.c b/disas/riscv.c
   index ddda687c13..544558 100644
   --- a/disas/riscv.c
   +++ b/disas/riscv.c
   @@ -1645,7 +1645,7 @@ const rv_opcode_data opcode_data[] = {
    { "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
    { "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
    { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
   -    { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
   +    { "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
    { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
    { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
    { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },

The threading seems to have gotten a little screwed up with the v2 so 
sorry if
I missed something, but I didn't see one with the ordering changed.  I 
stuck

what I think is a correct patch over at
<https://github.com/qemu/qemu/commit/09da30795bcca53447a6f6f9dde4aa91a48f8a01>, 


LMK if that's OK (or just send a v3).

If the order doesn't matter I think it would be nice to put ctzw 
after clzw.




Thanks,


Daniel


  { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
  { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },






[PATCH] Fix slli_uw decoding

2023-02-27 Thread Ivan Klokov
The decoding of the slli_uw currently contains decoding
error: shamt part of opcode has six bits, not five.

Fixes 3de1fb71("target/riscv: update disas.c for xnor/orn/andn and slli.uw")

Signed-off-by: Ivan Klokov 
---
 disas/riscv.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index ddda687c13..03cfefb0d3 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -1647,7 +1647,7 @@ const rv_opcode_data opcode_data[] = {
 { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
-{ "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
+{ "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
 { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
@@ -2617,10 +2617,10 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 switch (((inst >> 12) & 0b111)) {
 case 0: op = rv_op_addiw; break;
 case 1:
-switch (((inst >> 25) & 0b111)) {
+switch (((inst >> 26) & 0b11)) {
 case 0: op = rv_op_slliw; break;
-case 4: op = rv_op_slli_uw; break;
-case 48:
+case 2: op = rv_op_slli_uw; break;
+case 24:
 switch ((inst >> 20) & 0b1) {
 case 0b0: op = rv_op_clzw; break;
 case 0b1: op = rv_op_ctzw; break;
-- 
2.34.1




[PATCH] [PATCH] disas/riscv Fix ctzw disassemble

2023-02-17 Thread Ivan Klokov
Due to typo in opcode list, ctzw is disassembled as clzw instruction.

Fixes: 02c1b569a15b ("disas/riscv: Add Zb[abcs] instructions")
Signed-off-by: Ivan Klokov 
---
v2:
   - added fixes line
---
 disas/riscv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index ddda687c13..544558 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -1645,7 +1645,7 @@ const rv_opcode_data opcode_data[] = {
 { "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
-{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+{ "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
 { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
-- 
2.34.1




[PATCH] [PATCH] disas/riscv Fix ctzw disassemble

2023-02-17 Thread Ivan Klokov
Due to typo in opcode list, ctzw is disassembled as clzw instruction.

Signed-off-by: Ivan Klokov 
---
 disas/riscv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index ddda687c13..d0639cd047 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -1644,7 +1644,7 @@ const rv_opcode_data opcode_data[] = {
 { "minu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
-{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+{ "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
 { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
-- 
2.34.1




[PATCH] target/riscv: Add RVV registers to log

2023-02-01 Thread Ivan Klokov
Added QEMU option 'rvv' to add RISC-V RVV registers to log like regular regs.

Signed-off-by: Ivan Klokov 
---
 accel/tcg/cpu-exec.c  |  5 +
 include/hw/core/cpu.h |  2 ++
 include/qemu/log.h|  3 ++-
 target/riscv/cpu.c| 49 ++-
 util/log.c|  3 +++
 5 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 04cd1f3092..90e3b79544 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -296,6 +296,11 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
 }
 #if defined(TARGET_I386)
 flags |= CPU_DUMP_CCOP;
+#endif
+#if defined(TARGET_RISCV)
+if (qemu_loglevel_mask(CPU_LOG_RISCV_RVV)) {
+flags |= CPU_DUMP_RVV;
+}
 #endif
 cpu_dump_state(cpu, logfile, flags);
 qemu_log_unlock(logfile);
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 2417597236..82d90854c5 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -543,11 +543,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
  * @CPU_DUMP_CODE:
  * @CPU_DUMP_FPU: dump FPU register state, not just integer
  * @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
+ * @CPU_DUMP_RVV: dump RISC-V RVV registers
  */
 enum CPUDumpFlags {
 CPU_DUMP_CODE = 0x0001,
 CPU_DUMP_FPU  = 0x0002,
 CPU_DUMP_CCOP = 0x0004,
+CPU_DUMP_RVV  = 0x0008,
 };
 
 /**
diff --git a/include/qemu/log.h b/include/qemu/log.h
index c5643d8dd5..fb061d75f8 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -35,7 +35,8 @@ bool qemu_log_separate(void);
 /* LOG_STRACE is used for user-mode strace logging. */
 #define LOG_STRACE (1 << 19)
 #define LOG_PER_THREAD (1 << 20)
-
+/* RISC-V "V" Vector Extension */
+#define CPU_LOG_RISCV_RVV  (1 << 21)
 /* Lock/unlock output. */
 
 FILE *qemu_log_trylock(void) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 14a7027095..319aac5517 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -154,6 +154,14 @@ const char * const riscv_fpr_regnames[] = {
   "f30/ft10", "f31/ft11"
 };
 
+const char * const riscv_rvv_regnames[] = {
+  "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
+  "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
+  "v14", "v15", "v16", "v17", "v18", "v19", "v20",
+  "v21", "v22", "v23", "v24", "v25", "v26", "v27",
+  "v28", "v29", "v30", "v31"
+};
+
 static const char * const riscv_excp_names[] = {
 "misaligned_fetch",
 "fault_fetch",
@@ -375,7 +383,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
-int i;
+int i, j;
+uint8_t *p;
 
 #if !defined(CONFIG_USER_ONLY)
 if (riscv_has_ext(env, RVH)) {
@@ -459,6 +468,44 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 }
 }
 }
+if (riscv_has_ext(env, RVV)) {
+if (flags & CPU_DUMP_RVV) {
+
+static const int dump_rvv_csrs[] = {
+CSR_VSTART,
+CSR_VXSAT,
+CSR_VXRM,
+CSR_VCSR,
+CSR_VL,
+CSR_VTYPE,
+CSR_VLENB,
+};
+for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
+int csrno = dump_rvv_csrs[i];
+target_ulong val = 0;
+RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+/*
+ * Rely on the smode, hmode, etc, predicates within csr.c
+ * to do the filtering of the registers that are present.
+ */
+if (res == RISCV_EXCP_NONE) {
+qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
+ csr_ops[csrno].name, val);
+}
+}
+uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+
+for (i = 0; i < 32; i++) {
+qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
+p = (uint8_t *)env->vreg;
+for (j = 0; j < vlenb; j++) {
+qemu_fprintf(f, "%02x", *(p + i * vlenb + j));
+}
+qemu_fprintf(f, "\n");
+}
+}
+}
 }
 
 sta