diff options
author | Alistair Francis <alistair.francis@wdc.com> | 2021-08-30 15:35:02 +1000 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2021-09-21 07:56:49 +1000 |
commit | f436ecc3156dea7edce97e7c247e3667203f5c8b (patch) | |
tree | 1ca775b95bfaa3f19cb76a7cff031ac9aa05c4e0 /hw/intc/sifive_plic.c | |
parent | e5cc6aaeb51dd0d80e1f5a6d6a6808d6355958aa (diff) |
hw/intc: sifive_plic: Convert the PLIC to use RISC-V CPU GPIO lines
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
CPU GPIO lines to set the external MIP bits.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
Message-id: 0364190bfa935058a845c0fa1ecf650328840ad5.1630301632.git.alistair.francis@wdc.com
Diffstat (limited to 'hw/intc/sifive_plic.c')
-rw-r--r-- | hw/intc/sifive_plic.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 78903beb06..9ba36dc0b3 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -29,6 +29,7 @@ #include "hw/intc/sifive_plic.h" #include "target/riscv/cpu.h" #include "migration/vmstate.h" +#include "hw/irq.h" #define RISCV_DEBUG_PLIC 0 @@ -139,18 +140,14 @@ static void sifive_plic_update(SiFivePLICState *plic) for (addrid = 0; addrid < plic->num_addrs; addrid++) { uint32_t hartid = plic->addr_config[addrid].hartid; PLICMode mode = plic->addr_config[addrid].mode; - CPUState *cpu = qemu_get_cpu(hartid); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - if (!env) { - continue; - } int level = sifive_plic_irqs_pending(plic, addrid); + switch (mode) { case PLICMode_M: - riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level)); + qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], level); break; case PLICMode_S: - riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level)); + qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], level); break; default: break; @@ -456,6 +453,12 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio); qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources); + plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); + qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts); + + plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); + qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts); + /* We can't allow the supervisor to control SEIP as this would allow the * supervisor to clear a pending external interrupt which will result in * lost a interrupt in the case a PLIC is attached. The SEIP bit must be @@ -520,6 +523,7 @@ type_init(sifive_plic_register_types) * Create PLIC device. */ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, + uint32_t num_harts, uint32_t hartid_base, uint32_t num_sources, uint32_t num_priorities, uint32_t priority_base, uint32_t pending_base, uint32_t enable_base, @@ -527,6 +531,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, uint32_t context_stride, uint32_t aperture_size) { DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC); + int i; + assert(enable_stride == (enable_stride & -enable_stride)); assert(context_stride == (context_stride & -context_stride)); qdev_prop_set_string(dev, "hart-config", hart_config); @@ -542,5 +548,15 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, qdev_prop_set_uint32(dev, "aperture-size", aperture_size); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + for (i = 0; i < num_harts; i++) { + CPUState *cpu = qemu_get_cpu(hartid_base + i); + + qdev_connect_gpio_out(dev, i, + qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT)); + qdev_connect_gpio_out(dev, num_harts + i, + qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); + } + return dev; } |