aboutsummaryrefslogtreecommitdiff
path: root/target/riscv
diff options
context:
space:
mode:
authorDaniel Henrique Barboza <dbarboza@ventanamicro.com>2023-10-23 12:39:24 -0300
committerAlistair Francis <alistair.francis@wdc.com>2023-11-07 11:06:02 +1000
commitc004099330c2bb9c94984ac917815572fcd55bd0 (patch)
tree04d1c072f377de83e5bc3ecf7f04d3e4731ddd95 /target/riscv
parentac66f2f0d12d7ebb69bb45d5eb7f73fb0542bae5 (diff)
downloadqemu-c004099330c2bb9c94984ac917815572fcd55bd0.zip
qemu-c004099330c2bb9c94984ac917815572fcd55bd0.tar.gz
qemu-c004099330c2bb9c94984ac917815572fcd55bd0.tar.bz2
target/riscv: add zicntr extension flag for TCG
zicntr is the Base Counters and Timers extension described in chapter 12 of the unprivileged spec. It describes support for RDCYCLE, RDTIME and RDINSTRET. QEMU already implements it in TCG way before it was a discrete extension. zicntr is part of the RVA22 profile, so let's add it to QEMU to make the future profile implementation flag complete. Given than it represents an already existing feature, default it to 'true' for all CPUs. For TCG, we need a way to disable zicntr if the user wants to. This is done by restricting access to the CYCLE, TIME, and INSTRET counters via the 'ctr()' predicate when we're about to access them. Disabling zicntr happens via the command line or if its dependency, zicsr, happens to be disabled. We'll check for zicsr during realize() and, in case it's absent, disable zicntr. However, if the user was explicit about having zicntr support, error out instead of disabling it. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231023153927.435083-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv')
-rw-r--r--target/riscv/cpu.c12
-rw-r--r--target/riscv/cpu_cfg.h1
-rw-r--r--target/riscv/csr.c4
-rw-r--r--target/riscv/tcg/tcg-cpu.c8
4 files changed, 25 insertions, 0 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2881bf..69d64ec 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -80,6 +80,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom),
ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz),
ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
+ ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr),
ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr),
ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei),
ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
@@ -1208,6 +1209,15 @@ static void riscv_cpu_init(Object *obj)
qdev_init_gpio_in(DEVICE(obj), riscv_cpu_set_irq,
IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
#endif /* CONFIG_USER_ONLY */
+
+ /*
+ * The timer and performance counters extensions were supported
+ * in QEMU before they were added as discrete extensions in the
+ * ISA. To keep compatibility we'll always default them to 'true'
+ * for all CPUs. Each accelerator will decide what to do when
+ * users disable them.
+ */
+ RISCV_CPU(obj)->cfg.ext_zicntr = true;
}
typedef struct misa_ext_info {
@@ -1297,6 +1307,8 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
+ MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
+
MULTI_EXT_CFG_BOOL("zba", ext_zba, true),
MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true),
MULTI_EXT_CFG_BOOL("zbc", ext_zbc, true),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e7ce977..73fd4b3 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -62,6 +62,7 @@ struct RISCVCPUConfig {
bool ext_zksh;
bool ext_zkt;
bool ext_zifencei;
+ bool ext_zicntr;
bool ext_zicsr;
bool ext_zicbom;
bool ext_zicboz;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index f4e0a39..4ca96dd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -122,6 +122,10 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
(csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
+ if (!riscv_cpu_cfg(env)->ext_zicntr) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
goto skip_ext_pmu_check;
}
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index c5ff03e..a1e4ed2 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -541,6 +541,14 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
}
+ if (cpu->cfg.ext_zicntr && !cpu->cfg.ext_zicsr) {
+ if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicntr))) {
+ error_setg(errp, "zicntr requires zicsr");
+ return;
+ }
+ cpu->cfg.ext_zicntr = false;
+ }
+
/*
* Disable isa extensions based on priv spec after we
* validated and set everything we need.