aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/cpu.c
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2022-02-04 23:16:39 +0530
committerAlistair Francis <alistair.francis@wdc.com>2022-02-16 12:24:18 +1000
commitcd032fe75c1f7b24ccad772d50bfb689e7f5835d (patch)
treea7b62cfd8789ad2fae5409c76d32453cc1cbcac0 /target/riscv/cpu.c
parent881df35d3df52efd845087fb76d0b0116b366468 (diff)
downloadqemu-cd032fe75c1f7b24ccad772d50bfb689e7f5835d.zip
qemu-cd032fe75c1f7b24ccad772d50bfb689e7f5835d.tar.gz
qemu-cd032fe75c1f7b24ccad772d50bfb689e7f5835d.tar.bz2
target/riscv: Implement hgeie and hgeip CSRs
The hgeie and hgeip CSRs are required for emulating an external interrupt controller capable of injecting virtual external interrupt to Guest/VM running at VS-level. Signed-off-by: Anup Patel <anup.patel@wdc.com> Signed-off-by: Anup Patel <anup@brainfault.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Message-id: 20220204174700.534953-4-anup@brainfault.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv/cpu.c')
-rw-r--r--target/riscv/cpu.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e1224d2..f1c2684 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -663,27 +663,53 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
static void riscv_cpu_set_irq(void *opaque, int irq, int level)
{
RISCVCPU *cpu = RISCV_CPU(opaque);
+ CPURISCVState *env = &cpu->env;
- switch (irq) {
- case IRQ_U_SOFT:
- case IRQ_S_SOFT:
- case IRQ_VS_SOFT:
- case IRQ_M_SOFT:
- case IRQ_U_TIMER:
- case IRQ_S_TIMER:
- case IRQ_VS_TIMER:
- case IRQ_M_TIMER:
- case IRQ_U_EXT:
- case IRQ_S_EXT:
- case IRQ_VS_EXT:
- case IRQ_M_EXT:
- if (kvm_enabled()) {
- kvm_riscv_set_irq(cpu, irq, level);
- } else {
- riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
+ if (irq < IRQ_LOCAL_MAX) {
+ switch (irq) {
+ case IRQ_U_SOFT:
+ case IRQ_S_SOFT:
+ case IRQ_VS_SOFT:
+ case IRQ_M_SOFT:
+ case IRQ_U_TIMER:
+ case IRQ_S_TIMER:
+ case IRQ_VS_TIMER:
+ case IRQ_M_TIMER:
+ case IRQ_U_EXT:
+ case IRQ_S_EXT:
+ case IRQ_VS_EXT:
+ case IRQ_M_EXT:
+ if (kvm_enabled()) {
+ kvm_riscv_set_irq(cpu, irq, level);
+ } else {
+ riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
+ }
+ break;
+ default:
+ g_assert_not_reached();
}
- break;
- default:
+ } else if (irq < (IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX)) {
+ /* Require H-extension for handling guest local interrupts */
+ if (!riscv_has_ext(env, RVH)) {
+ g_assert_not_reached();
+ }
+
+ /* Compute bit position in HGEIP CSR */
+ irq = irq - IRQ_LOCAL_MAX + 1;
+ if (env->geilen < irq) {
+ g_assert_not_reached();
+ }
+
+ /* Update HGEIP CSR */
+ env->hgeip &= ~((target_ulong)1 << irq);
+ if (level) {
+ env->hgeip |= (target_ulong)1 << irq;
+ }
+
+ /* Update mip.SGEIP bit */
+ riscv_cpu_update_mip(cpu, MIP_SGEIP,
+ BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
+ } else {
g_assert_not_reached();
}
}
@@ -696,7 +722,8 @@ static void riscv_cpu_init(Object *obj)
cpu_set_cpustate_pointers(cpu);
#ifndef CONFIG_USER_ONLY
- qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, IRQ_LOCAL_MAX);
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
+ IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
#endif /* CONFIG_USER_ONLY */
}