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
This commit is contained in:
parent
e5cc6aaeb5
commit
f436ecc315
@ -29,6 +29,7 @@
|
|||||||
#include "hw/intc/sifive_plic.h"
|
#include "hw/intc/sifive_plic.h"
|
||||||
#include "target/riscv/cpu.h"
|
#include "target/riscv/cpu.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
|
#include "hw/irq.h"
|
||||||
|
|
||||||
#define RISCV_DEBUG_PLIC 0
|
#define RISCV_DEBUG_PLIC 0
|
||||||
|
|
||||||
@ -139,18 +140,14 @@ static void sifive_plic_update(SiFivePLICState *plic)
|
|||||||
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
|
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
|
||||||
uint32_t hartid = plic->addr_config[addrid].hartid;
|
uint32_t hartid = plic->addr_config[addrid].hartid;
|
||||||
PLICMode mode = plic->addr_config[addrid].mode;
|
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);
|
int level = sifive_plic_irqs_pending(plic, addrid);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PLICMode_M:
|
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;
|
break;
|
||||||
case PLICMode_S:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -456,6 +453,12 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
|
||||||
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
|
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
|
/* 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
|
* 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
|
* 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.
|
* Create PLIC device.
|
||||||
*/
|
*/
|
||||||
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
||||||
|
uint32_t num_harts,
|
||||||
uint32_t hartid_base, uint32_t num_sources,
|
uint32_t hartid_base, uint32_t num_sources,
|
||||||
uint32_t num_priorities, uint32_t priority_base,
|
uint32_t num_priorities, uint32_t priority_base,
|
||||||
uint32_t pending_base, uint32_t enable_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)
|
uint32_t context_stride, uint32_t aperture_size)
|
||||||
{
|
{
|
||||||
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
|
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
|
||||||
|
int i;
|
||||||
|
|
||||||
assert(enable_stride == (enable_stride & -enable_stride));
|
assert(enable_stride == (enable_stride & -enable_stride));
|
||||||
assert(context_stride == (context_stride & -context_stride));
|
assert(context_stride == (context_stride & -context_stride));
|
||||||
qdev_prop_set_string(dev, "hart-config", hart_config);
|
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);
|
qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
|
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;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* PLIC */
|
/* PLIC */
|
||||||
s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
|
s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
|
||||||
plic_hart_config, 0,
|
plic_hart_config, ms->smp.cpus, 0,
|
||||||
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
|
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
|
||||||
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
|
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
|
||||||
MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
|
MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
|
||||||
|
@ -106,13 +106,14 @@ type_init(shakti_c_machine_type_info_register)
|
|||||||
|
|
||||||
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
|
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
MachineState *ms = MACHINE(qdev_get_machine());
|
||||||
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
|
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
|
|
||||||
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
|
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
|
||||||
|
|
||||||
sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
|
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_SOURCES,
|
||||||
SHAKTI_C_PLIC_NUM_PRIORITIES,
|
SHAKTI_C_PLIC_NUM_PRIORITIES,
|
||||||
SHAKTI_C_PLIC_PRIORITY_BASE,
|
SHAKTI_C_PLIC_PRIORITY_BASE,
|
||||||
|
@ -197,7 +197,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* MMIO */
|
/* MMIO */
|
||||||
s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
|
s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
|
||||||
(char *)SIFIVE_E_PLIC_HART_CONFIG, 0,
|
(char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
|
||||||
SIFIVE_E_PLIC_NUM_SOURCES,
|
SIFIVE_E_PLIC_NUM_SOURCES,
|
||||||
SIFIVE_E_PLIC_NUM_PRIORITIES,
|
SIFIVE_E_PLIC_NUM_PRIORITIES,
|
||||||
SIFIVE_E_PLIC_PRIORITY_BASE,
|
SIFIVE_E_PLIC_PRIORITY_BASE,
|
||||||
|
@ -832,7 +832,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* MMIO */
|
/* MMIO */
|
||||||
s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
|
s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
|
||||||
plic_hart_config, 0,
|
plic_hart_config, ms->smp.cpus, 0,
|
||||||
SIFIVE_U_PLIC_NUM_SOURCES,
|
SIFIVE_U_PLIC_NUM_SOURCES,
|
||||||
SIFIVE_U_PLIC_NUM_PRIORITIES,
|
SIFIVE_U_PLIC_NUM_PRIORITIES,
|
||||||
SIFIVE_U_PLIC_PRIORITY_BASE,
|
SIFIVE_U_PLIC_PRIORITY_BASE,
|
||||||
|
@ -625,7 +625,7 @@ static void virt_machine_init(MachineState *machine)
|
|||||||
/* Per-socket PLIC */
|
/* Per-socket PLIC */
|
||||||
s->plic[i] = sifive_plic_create(
|
s->plic[i] = sifive_plic_create(
|
||||||
memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
|
memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
|
||||||
plic_hart_config, base_hartid,
|
plic_hart_config, hart_count, base_hartid,
|
||||||
VIRT_PLIC_NUM_SOURCES,
|
VIRT_PLIC_NUM_SOURCES,
|
||||||
VIRT_PLIC_NUM_PRIORITIES,
|
VIRT_PLIC_NUM_PRIORITIES,
|
||||||
VIRT_PLIC_PRIORITY_BASE,
|
VIRT_PLIC_PRIORITY_BASE,
|
||||||
|
@ -72,9 +72,13 @@ struct SiFivePLICState {
|
|||||||
uint32_t context_base;
|
uint32_t context_base;
|
||||||
uint32_t context_stride;
|
uint32_t context_stride;
|
||||||
uint32_t aperture_size;
|
uint32_t aperture_size;
|
||||||
|
|
||||||
|
qemu_irq *m_external_irqs;
|
||||||
|
qemu_irq *s_external_irqs;
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
|
||||||
|
uint32_t num_harts,
|
||||||
uint32_t hartid_base, uint32_t num_sources,
|
uint32_t hartid_base, uint32_t num_sources,
|
||||||
uint32_t num_priorities, uint32_t priority_base,
|
uint32_t num_priorities, uint32_t priority_base,
|
||||||
uint32_t pending_base, uint32_t enable_base,
|
uint32_t pending_base, uint32_t enable_base,
|
||||||
|
Loading…
Reference in New Issue
Block a user