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 |