1
These patches add functionality for unit testing RISC-V-specific registers.
1
These patches add functionality for unit testing RISC-V-specific registers.
2
The first patch adds a Qtest backend, and the second implements a simple test.
2
The first patch adds a Qtest backend, and the second implements a simple test.
3
3
4
---
4
---
5
v5:
5
v9:
6
- Move code from target/riscv to hw/riscv
6
- Fix build errors.
7
v8:
8
- Delete RFC label.
9
v7:
10
- Fix build errors, add Reviewed-by, Acked-by.
7
---
11
---
8
12
9
Ivan Klokov (2):
13
Ivan Klokov (2):
10
target/riscv: Add RISC-V CSR qtest support
14
target/riscv: Add RISC-V CSR qtest support
11
tests/qtest: QTest example for RISC-V CSR register
15
tests/qtest: QTest example for RISC-V CSR register
12
16
13
hw/riscv/riscv_hart.c | 65 ++++++++++++++++++++++++++++++++++++
17
hw/riscv/riscv_hart.c | 55 +++++++++++++++++++++++++++++++++++
14
tests/qtest/libqtest.c | 27 +++++++++++++++
18
tests/qtest/libqtest.c | 27 +++++++++++++++++
15
tests/qtest/libqtest.h | 14 ++++++++
19
tests/qtest/libqtest.h | 14 +++++++++
16
tests/qtest/meson.build | 2 +-
20
tests/qtest/meson.build | 2 +-
17
tests/qtest/riscv-csr-test.c | 56 +++++++++++++++++++++++++++++++
21
tests/qtest/riscv-csr-test.c | 56 ++++++++++++++++++++++++++++++++++++
18
5 files changed, 163 insertions(+), 1 deletion(-)
22
5 files changed, 153 insertions(+), 1 deletion(-)
19
create mode 100644 tests/qtest/riscv-csr-test.c
23
create mode 100644 tests/qtest/riscv-csr-test.c
20
24
21
--
25
--
22
2.34.1
26
2.34.1
diff view generated by jsdifflib
1
The RISC-V architecture supports the creation of custom
1
The RISC-V architecture supports the creation of custom
2
CSR-mapped devices. It would be convenient to test them in the same way
2
CSR-mapped devices. It would be convenient to test them in the same way
3
as MMIO-mapped devices. To do this, a new call has been added
3
as MMIO-mapped devices. To do this, a new call has been added
4
to read/write CSR registers.
4
to read/write CSR registers.
5
5
6
Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com>
6
Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com>
7
Acked-by: Fabiano Rosas <farosas@suse.de>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
7
---
9
---
8
hw/riscv/riscv_hart.c | 65 ++++++++++++++++++++++++++++++++++++++++++
10
hw/riscv/riscv_hart.c | 55 ++++++++++++++++++++++++++++++++++++++++++
9
tests/qtest/libqtest.c | 27 ++++++++++++++++++
11
tests/qtest/libqtest.c | 27 +++++++++++++++++++++
10
tests/qtest/libqtest.h | 14 +++++++++
12
tests/qtest/libqtest.h | 14 +++++++++++
11
3 files changed, 106 insertions(+)
13
3 files changed, 96 insertions(+)
12
14
13
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
15
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/riscv/riscv_hart.c
17
--- a/hw/riscv/riscv_hart.c
16
+++ b/hw/riscv/riscv_hart.c
18
+++ b/hw/riscv/riscv_hart.c
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
18
#include "qemu/osdep.h"
19
#include "qapi/error.h"
20
#include "qapi/error.h"
20
#include "qemu/module.h"
21
#include "qemu/module.h"
22
#include "system/reset.h"
23
+#include "system/qtest.h"
21
+#include "qemu/cutils.h"
24
+#include "qemu/cutils.h"
22
+#include "sysemu/qtest.h"
23
#include "sysemu/reset.h"
24
#include "hw/sysbus.h"
25
#include "hw/sysbus.h"
25
#include "target/riscv/cpu.h"
26
#include "target/riscv/cpu.h"
27
#include "hw/qdev-properties.h"
26
@@ -XXX,XX +XXX,XX @@ static void riscv_harts_cpu_reset(void *opaque)
28
@@ -XXX,XX +XXX,XX @@ static void riscv_harts_cpu_reset(void *opaque)
27
cpu_reset(CPU(cpu));
29
cpu_reset(CPU(cpu));
28
}
30
}
29
31
30
+#ifndef CONFIG_USER_ONLY
32
+#ifndef CONFIG_USER_ONLY
31
+static uint64_t csr_call(char *cmd, uint64_t cpu_num, int csrno,
33
+static void csr_call(char *cmd, uint64_t cpu_num, int csrno, uint64_t *val)
32
+ uint64_t *val)
33
+{
34
+{
34
+ RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
35
+ RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
35
+ CPURISCVState *env = &cpu->env;
36
+ CPURISCVState *env = &cpu->env;
36
+
37
+
37
+ int ret = RISCV_EXCP_NONE;
38
+ int ret = RISCV_EXCP_NONE;
38
+ if (strcmp(cmd, "get_csr") == 0) {
39
+ if (strcmp(cmd, "get_csr") == 0) {
39
+ ret = riscv_csrr(env, csrno, (target_ulong *)val);
40
+ ret = riscv_csrr(env, csrno, (target_ulong *)val);
40
+ } else if (strcmp(cmd, "set_csr") == 0) {
41
+ } else if (strcmp(cmd, "set_csr") == 0) {
41
+ ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
42
+ ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val,
43
+ MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
42
+ }
44
+ }
43
+
45
+
44
+ if (ret == RISCV_EXCP_NONE) {
46
+ g_assert(ret == RISCV_EXCP_NONE);
45
+ ret = 0;
46
+ } else {
47
+ g_assert_not_reached();
48
+ }
49
+
50
+ return ret;
51
+}
47
+}
52
+
48
+
53
+static bool csr_qtest_callback(CharBackend *chr, gchar **words)
49
+static bool csr_qtest_callback(CharBackend *chr, gchar **words)
54
+{
50
+{
55
+ if (strcmp(words[0], "csr") == 0) {
51
+ if (strcmp(words[0], "csr") == 0) {
56
+
52
+
57
+ uint64_t res, cpu;
53
+ uint64_t cpu;
58
+
59
+ uint64_t val;
54
+ uint64_t val;
60
+ int rc, csr;
55
+ int rc, csr;
61
+
56
+
62
+ rc = qemu_strtou64(words[2], NULL, 0, &cpu);
57
+ rc = qemu_strtou64(words[2], NULL, 0, &cpu);
63
+ g_assert(rc == 0);
58
+ g_assert(rc == 0);
64
+ rc = qemu_strtoi(words[3], NULL, 0, &csr);
59
+ rc = qemu_strtoi(words[3], NULL, 0, &csr);
65
+ g_assert(rc == 0);
60
+ g_assert(rc == 0);
66
+ rc = qemu_strtou64(words[4], NULL, 0, &val);
61
+ rc = qemu_strtou64(words[4], NULL, 0, &val);
67
+ g_assert(rc == 0);
62
+ g_assert(rc == 0);
68
+ res = csr_call(words[1], cpu, csr, &val);
63
+ csr_call(words[1], cpu, csr, &val);
69
+
64
+
70
+ qtest_send_prefix(chr);
65
+ qtest_send_prefix(chr);
71
+ qtest_sendf(chr, "OK %"PRIx64" "TARGET_FMT_lx"\n", res, (target_ulong)val);
66
+ qtest_sendf(chr, "OK 0 "TARGET_FMT_lx"\n", (target_ulong)val);
72
+
67
+
73
+ return true;
68
+ return true;
74
+ }
69
+ }
75
+
70
+
76
+ return false;
71
+ return false;
77
+}
72
+}
78
+
73
+
79
+static void riscv_cpu_register_csr_qtest_callback(void)
74
+static void riscv_cpu_register_csr_qtest_callback(void)
80
+{
75
+{
81
+ static gsize reinit_done;
76
+ static GOnce once;
82
+ if (g_once_init_enter(&reinit_done)) {
77
+ g_once(&once, (GThreadFunc)qtest_set_command_cb, csr_qtest_callback);
83
+ qtest_set_command_cb(csr_qtest_callback);
84
+
85
+ g_once_init_leave(&reinit_done, 1);
86
+ }
87
+}
78
+}
88
+#endif
79
+#endif
89
+
80
+
90
static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
81
static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
91
char *cpu_type, Error **errp)
82
char *cpu_type, Error **errp)
92
{
83
{
93
@@ -XXX,XX +XXX,XX @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
84
@@ -XXX,XX +XXX,XX @@ static void riscv_harts_realize(DeviceState *dev, Error **errp)
94
qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
85
95
s->harts[idx].env.mhartid = s->hartid_base + idx;
86
s->harts = g_new0(RISCVCPU, s->num_harts);
96
qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
87
97
+#ifndef CONFIG_USER_ONLY
88
+#ifndef CONFIG_USER_ONLY
98
+ riscv_cpu_register_csr_qtest_callback();
89
+ riscv_cpu_register_csr_qtest_callback();
99
+#endif
90
+#endif
100
return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
91
+
101
}
92
for (n = 0; n < s->num_harts; n++) {
102
93
if (!riscv_hart_realize(s, n, s->cpu_type, errp)) {
94
return;
103
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
95
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
104
index XXXXXXX..XXXXXXX 100644
96
index XXXXXXX..XXXXXXX 100644
105
--- a/tests/qtest/libqtest.c
97
--- a/tests/qtest/libqtest.c
106
+++ b/tests/qtest/libqtest.c
98
+++ b/tests/qtest/libqtest.c
107
@@ -XXX,XX +XXX,XX @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
99
@@ -XXX,XX +XXX,XX @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
...
...
156
+ *
148
+ *
157
+ * Call an RISC-V CSR read/write function
149
+ * Call an RISC-V CSR read/write function
158
+ */
150
+ */
159
+uint64_t qtest_csr_call(QTestState *s, const char *name,
151
+uint64_t qtest_csr_call(QTestState *s, const char *name,
160
+ uint64_t cpu, int csr,
152
+ uint64_t cpu, int csr,
161
+ unsigned long *val);
153
+ uint64_t *val);
162
+
154
+
163
/**
155
/**
164
* qtest_bufread:
156
* qtest_bufread:
165
* @s: #QTestState instance to operate on.
157
* @s: #QTestState instance to operate on.
166
--
158
--
167
2.34.1
159
2.34.1
diff view generated by jsdifflib
1
Added demo for reading CSR register from qtest environment.
1
Added demo for reading CSR register from qtest environment.
2
2
3
Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com>
3
Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com>
4
Reviewed-by: Fabiano Rosas <farosas@suse.de>
5
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
4
---
6
---
5
tests/qtest/meson.build | 2 +-
7
tests/qtest/meson.build | 2 +-
6
tests/qtest/riscv-csr-test.c | 56 ++++++++++++++++++++++++++++++++++++
8
tests/qtest/riscv-csr-test.c | 56 ++++++++++++++++++++++++++++++++++++
7
2 files changed, 57 insertions(+), 1 deletion(-)
9
2 files changed, 57 insertions(+), 1 deletion(-)
8
create mode 100644 tests/qtest/riscv-csr-test.c
10
create mode 100644 tests/qtest/riscv-csr-test.c
...
...
diff view generated by jsdifflib