Skip to content

Commit 1addf57

Browse files
Ivan KlokovFabiano Rosas
authored andcommitted
target/riscv: Add RISC-V CSR qtest support
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 <ivan.klokov@syntacore.com> Acked-by: Fabiano Rosas <farosas@suse.de> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Signed-off-by: Fabiano Rosas <farosas@suse.de>
1 parent 4d5d933 commit 1addf57

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

hw/riscv/riscv_hart.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qapi/error.h"
2323
#include "qemu/module.h"
2424
#include "system/reset.h"
25+
#include "system/qtest.h"
26+
#include "qemu/cutils.h"
2527
#include "hw/sysbus.h"
2628
#include "target/riscv/cpu.h"
2729
#include "hw/qdev-properties.h"
@@ -41,6 +43,55 @@ static void riscv_harts_cpu_reset(void *opaque)
4143
cpu_reset(CPU(cpu));
4244
}
4345

46+
#ifndef CONFIG_USER_ONLY
47+
static void csr_call(char *cmd, uint64_t cpu_num, int csrno, uint64_t *val)
48+
{
49+
RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num));
50+
CPURISCVState *env = &cpu->env;
51+
52+
int ret = RISCV_EXCP_NONE;
53+
if (strcmp(cmd, "get_csr") == 0) {
54+
ret = riscv_csrr(env, csrno, (target_ulong *)val);
55+
} else if (strcmp(cmd, "set_csr") == 0) {
56+
ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val,
57+
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
58+
}
59+
60+
g_assert(ret == RISCV_EXCP_NONE);
61+
}
62+
63+
static bool csr_qtest_callback(CharBackend *chr, gchar **words)
64+
{
65+
if (strcmp(words[0], "csr") == 0) {
66+
67+
uint64_t cpu;
68+
uint64_t val;
69+
int rc, csr;
70+
71+
rc = qemu_strtou64(words[2], NULL, 0, &cpu);
72+
g_assert(rc == 0);
73+
rc = qemu_strtoi(words[3], NULL, 0, &csr);
74+
g_assert(rc == 0);
75+
rc = qemu_strtou64(words[4], NULL, 0, &val);
76+
g_assert(rc == 0);
77+
csr_call(words[1], cpu, csr, &val);
78+
79+
qtest_send_prefix(chr);
80+
qtest_sendf(chr, "OK 0 "TARGET_FMT_lx"\n", (target_ulong)val);
81+
82+
return true;
83+
}
84+
85+
return false;
86+
}
87+
88+
static void riscv_cpu_register_csr_qtest_callback(void)
89+
{
90+
static GOnce once;
91+
g_once(&once, (GThreadFunc)qtest_set_command_cb, csr_qtest_callback);
92+
}
93+
#endif
94+
4495
static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
4596
char *cpu_type, Error **errp)
4697
{
@@ -58,6 +109,10 @@ static void riscv_harts_realize(DeviceState *dev, Error **errp)
58109

59110
s->harts = g_new0(RISCVCPU, s->num_harts);
60111

112+
#ifndef CONFIG_USER_ONLY
113+
riscv_cpu_register_csr_qtest_callback();
114+
#endif
115+
61116
for (n = 0; n < s->num_harts; n++) {
62117
if (!riscv_hart_realize(s, n, s->cpu_type, errp)) {
63118
return;

tests/qtest/libqtest.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,33 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
12181218
return 0;
12191219
}
12201220

1221+
static void qtest_rsp_csr(QTestState *s, uint64_t *val)
1222+
{
1223+
gchar **args;
1224+
uint64_t ret;
1225+
int rc;
1226+
1227+
args = qtest_rsp_args(s, 3);
1228+
1229+
rc = qemu_strtou64(args[1], NULL, 16, &ret);
1230+
g_assert(rc == 0);
1231+
rc = qemu_strtou64(args[2], NULL, 16, val);
1232+
g_assert(rc == 0);
1233+
1234+
g_strfreev(args);
1235+
}
1236+
1237+
uint64_t qtest_csr_call(QTestState *s, const char *name,
1238+
uint64_t cpu, int csr,
1239+
uint64_t *val)
1240+
{
1241+
qtest_sendf(s, "csr %s 0x%"PRIx64" %d 0x%"PRIx64"\n",
1242+
name, cpu, csr, *val);
1243+
1244+
qtest_rsp_csr(s, val);
1245+
return 0;
1246+
}
1247+
12211248
void qtest_add_func(const char *str, void (*fn)(void))
12221249
{
12231250
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);

tests/qtest/libqtest.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,20 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
600600
uint32_t nargs, uint64_t args,
601601
uint32_t nret, uint64_t ret);
602602

603+
/**
604+
* qtest_csr_call:
605+
* @s: #QTestState instance to operate on.
606+
* @name: name of the command to call.
607+
* @cpu: hart number.
608+
* @csr: CSR number.
609+
* @val: Value for reading/writing.
610+
*
611+
* Call an RISC-V CSR read/write function
612+
*/
613+
uint64_t qtest_csr_call(QTestState *s, const char *name,
614+
uint64_t cpu, int csr,
615+
uint64_t *val);
616+
603617
/**
604618
* qtest_bufread:
605619
* @s: #QTestState instance to operate on.

0 commit comments

Comments
 (0)