aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.