hw/riscv: Allow creating multiple instances of PLIC

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.patel@wdc.com>
Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20200616032229.766089-3-anup.patel@wdc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Anup Patel 2020-05-15 10:25:33 +05:30 committed by Alistair Francis
parent 3bf03f0899
commit c9270e10a5
5 changed files with 23 additions and 19 deletions

View File

@ -200,7 +200,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
/* MMIO */ /* MMIO */
s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base, 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_SOURCES,
SIFIVE_E_PLIC_NUM_PRIORITIES, SIFIVE_E_PLIC_NUM_PRIORITIES,
SIFIVE_E_PLIC_PRIORITY_BASE, SIFIVE_E_PLIC_PRIORITY_BASE,

View File

@ -361,6 +361,7 @@ static const MemoryRegionOps sifive_plic_ops = {
static Property sifive_plic_properties[] = { static Property sifive_plic_properties[] = {
DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config), 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-sources", SiFivePLICState, num_sources, 0),
DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0), DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0),
DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0), DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0),
@ -409,10 +410,12 @@ static void parse_hart_config(SiFivePLICState *plic)
} }
hartid++; hartid++;
/* store hart/mode combinations */
plic->num_addrs = addrid; plic->num_addrs = addrid;
plic->num_harts = hartid;
/* store hart/mode combinations */
plic->addr_config = g_new(PLICAddr, plic->num_addrs); plic->addr_config = g_new(PLICAddr, plic->num_addrs);
addrid = 0, hartid = 0; addrid = 0, hartid = plic->hartid_base;
p = plic->hart_config; p = plic->hart_config;
while ((c = *p++)) { while ((c = *p++)) {
if (c == ',') { if (c == ',') {
@ -438,8 +441,6 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level)
static void sifive_plic_realize(DeviceState *dev, Error **errp) 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); SiFivePLICState *plic = SIFIVE_PLIC(dev);
int i; int i;
@ -460,8 +461,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 * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached. * hardware controlled when a PLIC is attached.
*/ */
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < plic->num_harts; i++) {
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i)); RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(plic->hartid_base + i));
if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
error_report("SEIP already claimed"); error_report("SEIP already claimed");
exit(1); exit(1);
@ -497,16 +498,17 @@ 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_sources, uint32_t num_priorities, uint32_t hartid_base, uint32_t num_sources,
uint32_t priority_base, uint32_t pending_base, uint32_t num_priorities, uint32_t priority_base,
uint32_t enable_base, uint32_t enable_stride, uint32_t pending_base, uint32_t enable_base,
uint32_t context_base, uint32_t context_stride, uint32_t enable_stride, uint32_t context_base,
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);
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);
qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
qdev_prop_set_uint32(dev, "num-sources", num_sources); qdev_prop_set_uint32(dev, "num-sources", num_sources);
qdev_prop_set_uint32(dev, "num-priorities", num_priorities); qdev_prop_set_uint32(dev, "num-priorities", num_priorities);
qdev_prop_set_uint32(dev, "priority-base", priority_base); qdev_prop_set_uint32(dev, "priority-base", priority_base);

View File

@ -687,7 +687,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
/* MMIO */ /* MMIO */
s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, 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_SOURCES,
SIFIVE_U_PLIC_NUM_PRIORITIES, SIFIVE_U_PLIC_NUM_PRIORITIES,
SIFIVE_U_PLIC_PRIORITY_BASE, SIFIVE_U_PLIC_PRIORITY_BASE,

View File

@ -560,7 +560,7 @@ static void virt_machine_init(MachineState *machine)
/* MMIO */ /* MMIO */
s->plic = sifive_plic_create(memmap[VIRT_PLIC].base, s->plic = sifive_plic_create(memmap[VIRT_PLIC].base,
plic_hart_config, plic_hart_config, 0,
VIRT_PLIC_NUM_SOURCES, VIRT_PLIC_NUM_SOURCES,
VIRT_PLIC_NUM_PRIORITIES, VIRT_PLIC_NUM_PRIORITIES,
VIRT_PLIC_PRIORITY_BASE, VIRT_PLIC_PRIORITY_BASE,

View File

@ -48,6 +48,7 @@ typedef struct SiFivePLICState {
/*< public >*/ /*< public >*/
MemoryRegion mmio; MemoryRegion mmio;
uint32_t num_addrs; uint32_t num_addrs;
uint32_t num_harts;
uint32_t bitfield_words; uint32_t bitfield_words;
PLICAddr *addr_config; PLICAddr *addr_config;
uint32_t *source_priority; uint32_t *source_priority;
@ -58,6 +59,7 @@ typedef struct SiFivePLICState {
/* config */ /* config */
char *hart_config; char *hart_config;
uint32_t hartid_base;
uint32_t num_sources; uint32_t num_sources;
uint32_t num_priorities; uint32_t num_priorities;
uint32_t priority_base; uint32_t priority_base;
@ -70,10 +72,10 @@ typedef struct SiFivePLICState {
} SiFivePLICState; } SiFivePLICState;
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
uint32_t num_sources, uint32_t num_priorities, uint32_t hartid_base, uint32_t num_sources,
uint32_t priority_base, uint32_t pending_base, uint32_t num_priorities, uint32_t priority_base,
uint32_t enable_base, uint32_t enable_stride, uint32_t pending_base, uint32_t enable_base,
uint32_t context_base, uint32_t context_stride, uint32_t enable_stride, uint32_t context_base,
uint32_t aperture_size); uint32_t context_stride, uint32_t aperture_size);
#endif #endif