mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
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>
This commit is contained in:
parent
4d5d933bbc
commit
1addf57177
3 changed files with 96 additions and 0 deletions
|
@ -22,6 +22,8 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "system/reset.h"
|
||||
#include "system/qtest.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "target/riscv/cpu.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
@ -41,6 +43,55 @@ static void riscv_harts_cpu_reset(void *opaque)
|
|||
cpu_reset(CPU(cpu));
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void 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_csrr(env, csrno, (target_ulong *)val);
|
||||
} else if (strcmp(cmd, "set_csr") == 0) {
|
||||
ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val,
|
||||
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
|
||||
}
|
||||
|
||||
g_assert(ret == RISCV_EXCP_NONE);
|
||||
}
|
||||
|
||||
static bool csr_qtest_callback(CharBackend *chr, gchar **words)
|
||||
{
|
||||
if (strcmp(words[0], "csr") == 0) {
|
||||
|
||||
uint64_t 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);
|
||||
csr_call(words[1], cpu, csr, &val);
|
||||
|
||||
qtest_send_prefix(chr);
|
||||
qtest_sendf(chr, "OK 0 "TARGET_FMT_lx"\n", (target_ulong)val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void riscv_cpu_register_csr_qtest_callback(void)
|
||||
{
|
||||
static GOnce once;
|
||||
g_once(&once, (GThreadFunc)qtest_set_command_cb, csr_qtest_callback);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
|
||||
char *cpu_type, Error **errp)
|
||||
{
|
||||
|
@ -58,6 +109,10 @@ static void riscv_harts_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
s->harts = g_new0(RISCVCPU, s->num_harts);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
riscv_cpu_register_csr_qtest_callback();
|
||||
#endif
|
||||
|
||||
for (n = 0; n < s->num_harts; n++) {
|
||||
if (!riscv_hart_realize(s, n, s->cpu_type, errp)) {
|
||||
return;
|
||||
|
|
|
@ -1218,6 +1218,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)
|
||||
{
|
||||
qtest_sendf(s, "csr %s 0x%"PRIx64" %d 0x%"PRIx64"\n",
|
||||
name, cpu, csr, *val);
|
||||
|
||||
qtest_rsp_csr(s, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qtest_add_func(const char *str, void (*fn)(void))
|
||||
{
|
||||
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
|
||||
|
|
|
@ -600,6 +600,20 @@ uint64_t qtest_rtas_call(QTestState *s, const char *name,
|
|||
uint32_t nargs, uint64_t args,
|
||||
uint32_t nret, uint64_t ret);
|
||||
|
||||
/**
|
||||
* qtest_csr_call:
|
||||
* @s: #QTestState instance to operate on.
|
||||
* @name: name of the command to call.
|
||||
* @cpu: hart number.
|
||||
* @csr: CSR number.
|
||||
* @val: Value for reading/writing.
|
||||
*
|
||||
* Call an RISC-V CSR read/write function
|
||||
*/
|
||||
uint64_t qtest_csr_call(QTestState *s, const char *name,
|
||||
uint64_t cpu, int csr,
|
||||
uint64_t *val);
|
||||
|
||||
/**
|
||||
* qtest_bufread:
|
||||
* @s: #QTestState instance to operate on.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue