The new CLIC interrupt-handling mode is encoded as a new state in the
existing WARL xtvec register, where the low two bits of are 11.
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
target/riscv/csr.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index f6c84b9fe4..39ff72041a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -637,9 +637,18 @@ static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val)
static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val)
{
- /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+ /*
+ * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC,
+ * others reserved
+ */
if ((val & 3) < 2) {
env->mtvec = val;
+ } else if ((val & 1) && env->clic) {
+ /*
+ * If only CLIC mode is supported, writes to bit 1 are also ignored and
+ * it is always set to one. CLIC mode hardwires xtvec bits 2-5 to zero.
+ */
+ env->mtvec = ((val & ~0x3f) << 6) | (0b000011);
Why do we need to left-shift the value 6 bits here?
} else {
qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n");
}
@@ -837,9 +846,18 @@ static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
static int write_stvec(CPURISCVState *env, int csrno, target_ulong val)
{
- /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+ /*
+ * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC,
+ * others reserved
+ */
if ((val & 3) < 2) {
env->stvec = val;
+ } else if ((val & 1) && env->clic) {
+ /*
+ * If only CLIC mode is supported, writes to bit 1 are also ignored and
+ * it is always set to one. CLIC mode hardwires xtvec bits 2-5 to zero.
+ */
+ env->stvec = ((val & ~0x3f) << 6) | (0b000011);
Same here, why do we need to left-shift the value 6 bits here?
Also, CLIC v0.8 spec[1] doesn't include the change for stvec.
I'm not sure if it's the same as v0.9 to check stvec
when the interrupt is delegated to S-mode in CLIC-mode.
Regards,
Frank Chang
} else {
qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n");
}
--
2.25.1