We extend PLIC emulation to allow multiple instances of PLIC in
a QEMU RISC-V machine. To achieve this, we remove first HART id
zero assumption from PLIC emulation.
Signed-off-by: Anup Patel <anup.pa...@wdc.com>
---
hw/riscv/sifive_e.c | 2 +-
hw/riscv/sifive_plic.c | 24 +++++++++++++-----------
hw/riscv/sifive_u.c | 2 +-
hw/riscv/virt.c | 2 +-
include/hw/riscv/sifive_plic.h | 12 +++++++-----
5 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 1c3b37d0ba..bd122e71ae 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -152,7 +152,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev,
Error **errp)
/* MMIO */
s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base,
- (char *)SIFIVE_E_PLIC_HART_CONFIG,
+ (char *)SIFIVE_E_PLIC_HART_CONFIG, 0,
SIFIVE_E_PLIC_NUM_SOURCES,
SIFIVE_E_PLIC_NUM_PRIORITIES,
SIFIVE_E_PLIC_PRIORITY_BASE,
diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index c1e04cbb98..f88bb48053 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -352,6 +352,7 @@ static const MemoryRegionOps sifive_plic_ops = {
static Property sifive_plic_properties[] = {
DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config),
+ DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0),
DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0),
DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0),
DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0),
@@ -400,10 +401,12 @@ static void parse_hart_config(SiFivePLICState *plic)
}
hartid++;
- /* store hart/mode combinations */
plic->num_addrs = addrid;
+ plic->num_harts = hartid;
+
+ /* store hart/mode combinations */
plic->addr_config = g_new(PLICAddr, plic->num_addrs);
- addrid = 0, hartid = 0;
+ addrid = 0, hartid = plic->hartid_base;
p = plic->hart_config;
while ((c = *p++)) {
if (c == ',') {
@@ -429,8 +432,6 @@ static void sifive_plic_irq_request(void *opaque, int irq,
int level)
static void sifive_plic_realize(DeviceState *dev, Error **errp)
{
- MachineState *ms = MACHINE(qdev_get_machine());
- unsigned int smp_cpus = ms->smp.cpus;
SiFivePLICState *plic = SIFIVE_PLIC(dev);
int i;
@@ -451,8 +452,8 @@ static void sifive_plic_realize(DeviceState *dev, Error
**errp)
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached.
*/
- for (i = 0; i < smp_cpus; i++) {
- RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i));
+ for (i = 0; i < plic->num_harts; i++) {
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(plic->hartid_base + i));
if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
error_report("SEIP already claimed");
exit(1);
@@ -488,16 +489,17 @@ type_init(sifive_plic_register_types)
* Create PLIC device.
*/
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t num_sources, uint32_t num_priorities,
- uint32_t priority_base, uint32_t pending_base,
- uint32_t enable_base, uint32_t enable_stride,
- uint32_t context_base, uint32_t context_stride,
- uint32_t aperture_size)
+ 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 enable_stride, uint32_t context_base,
+ uint32_t context_stride, uint32_t aperture_size)
{
DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PLIC);
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, "hartid-base", hartid_base);
qdev_prop_set_uint32(dev, "num-sources", num_sources);
qdev_prop_set_uint32(dev, "num-priorities", num_priorities);
qdev_prop_set_uint32(dev, "priority-base", priority_base);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 22997fbf13..69dbd7980b 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -585,7 +585,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev,
Error **errp)
/* MMIO */
s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
- plic_hart_config,
+ plic_hart_config, 0,
SIFIVE_U_PLIC_NUM_SOURCES,
SIFIVE_U_PLIC_NUM_PRIORITIES,
SIFIVE_U_PLIC_PRIORITY_BASE,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index dcb8a83b35..f40efcb193 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -585,7 +585,7 @@ static void riscv_virt_board_init(MachineState *machine)
/* MMIO */
s->plic = sifive_plic_create(memmap[VIRT_PLIC].base,
- plic_hart_config,
+ plic_hart_config, 0,
VIRT_PLIC_NUM_SOURCES,
VIRT_PLIC_NUM_PRIORITIES,
VIRT_PLIC_PRIORITY_BASE,
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 4421e81249..ace76d0f1b 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -48,6 +48,7 @@ typedef struct SiFivePLICState {
/*< public >*/
MemoryRegion mmio;
uint32_t num_addrs;
+ uint32_t num_harts;
uint32_t bitfield_words;
PLICAddr *addr_config;
uint32_t *source_priority;
@@ -58,6 +59,7 @@ typedef struct SiFivePLICState {
/* config */
char *hart_config;
+ uint32_t hartid_base;
uint32_t num_sources;
uint32_t num_priorities;
uint32_t priority_base;
@@ -70,10 +72,10 @@ typedef struct SiFivePLICState {
} SiFivePLICState;
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t num_sources, uint32_t num_priorities,
- uint32_t priority_base, uint32_t pending_base,
- uint32_t enable_base, uint32_t enable_stride,
- uint32_t context_base, uint32_t context_stride,
- uint32_t aperture_size);
+ 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 enable_stride, uint32_t context_base,
+ uint32_t context_stride, uint32_t aperture_size);
#endif