#include "hw/intc/sifive_plic.h"
#include "target/riscv/cpu.h"
#include "migration/vmstate.h"
+#include "hw/irq.h"
#define RISCV_DEBUG_PLIC 0
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;
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
* 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,
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);
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;
}
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
{
+ MachineState *ms = MACHINE(qdev_get_machine());
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
MemoryRegion *system_memory = get_system_memory();
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
- (char *)SHAKTI_C_PLIC_HART_CONFIG, 0,
+ (char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
SHAKTI_C_PLIC_NUM_SOURCES,
SHAKTI_C_PLIC_NUM_PRIORITIES,
SHAKTI_C_PLIC_PRIORITY_BASE,