[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/5] hw/intc/sifive_plic: report errors and free allocated memory
From: |
Damien Hedde |
Subject: |
[PATCH 3/5] hw/intc/sifive_plic: report errors and free allocated memory |
Date: |
Fri, 18 Feb 2022 17:46:44 +0100 |
Add the instance_finalize() method to free the allocated arrays
and make realize() method report errors instead of exiting.
code in realize() is re-ordered to first check for errors and leave
the object in a clean state. To achieve this, we do the following:
+ parse_hart_config and char_to_mode are refactored to return errors
instead of exiting.
+ in case of interrupt claim failure, we now release the succesfully
claimed ones.
These clean-ups allow the following life-cycle use cases (happening
when user creation is allowed) to execute as expected:
+ init -> finalize
+ init -> realize-failure -> finalize
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
hw/intc/sifive_plic.c | 90 +++++++++++++++++++++++++++++--------------
1 file changed, 62 insertions(+), 28 deletions(-)
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index eebbcf33d4..8692ea6725 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -37,16 +37,20 @@ static bool addr_between(uint32_t addr, uint32_t base,
uint32_t num)
return addr >= base && addr - base < num;
}
-static PLICMode char_to_mode(char c)
+static PLICMode char_to_mode(char c, bool *success)
{
+ if (success) {
+ *success = true;
+ };
switch (c) {
case 'U': return PLICMode_U;
case 'S': return PLICMode_S;
case 'H': return PLICMode_H;
case 'M': return PLICMode_M;
default:
- error_report("plic: invalid mode '%c'", c);
- exit(1);
+ g_assert(success != NULL);
+ *success = false;
+ return 0;
}
}
@@ -260,7 +264,7 @@ static void sifive_plic_reset(DeviceState *dev)
* "MS,MS" 2 harts, 0-1 with M and S mode
* "M,MS,MS,MS,MS" 5 harts, 0 with M mode, 1-5 with M and S mode
*/
-static void parse_hart_config(SiFivePLICState *plic)
+static bool parse_hart_config(SiFivePLICState *plic, Error **errp)
{
int addrid, hartid, modes;
const char *p;
@@ -275,11 +279,16 @@ static void parse_hart_config(SiFivePLICState *plic)
modes = 0;
hartid++;
} else {
- int m = 1 << char_to_mode(c);
+ bool mode_ok = false;
+ int m = 1 << char_to_mode(c, &mode_ok);
+ if (!mode_ok) {
+ error_setg(errp, "plic: invalid mode '%c'", c);
+ return false;
+ }
if (modes == (modes | m)) {
- error_report("plic: duplicate mode '%c' in config: %s",
- c, plic->hart_config);
- exit(1);
+ error_setg(errp, "plic: duplicate mode '%c' in config: %s",
+ c, plic->hart_config);
+ return false;
}
modes |= m;
}
@@ -302,10 +311,12 @@ static void parse_hart_config(SiFivePLICState *plic)
} else {
plic->addr_config[addrid].addrid = addrid;
plic->addr_config[addrid].hartid = hartid;
- plic->addr_config[addrid].mode = char_to_mode(c);
+ plic->addr_config[addrid].mode = char_to_mode(c, NULL);
addrid++;
}
}
+
+ return true;
}
static void sifive_plic_irq_request(void *opaque, int irq, int level)
@@ -321,12 +332,34 @@ static void sifive_plic_realize(DeviceState *dev, Error
**errp)
SiFivePLICState *s = SIFIVE_PLIC(dev);
int i;
+ if (!parse_hart_config(s, errp)) {
+ return;
+ }
+
+ /*
+ * 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
+ * hardware controlled when a PLIC is attached.
+ */
+ for (i = 0; i < s->num_harts; i++) {
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
+ if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
+ error_setg(errp, "SEIP (hartid %u) already claimed",
+ (unsigned) (s->hartid_base + i));
+ /* release interrupts we already claimed */
+ while (--i >= 0) {
+ cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
+ riscv_cpu_release_claimed_interrupts(cpu, MIP_SEIP);
+ }
+ return;
+ }
+ }
+
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_plic_ops, s,
TYPE_SIFIVE_PLIC, s->aperture_size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
- parse_hart_config(s);
-
s->bitfield_words = (s->num_sources + 31) >> 5;
s->num_enables = s->bitfield_words * s->num_addrs;
s->source_priority = g_new0(uint32_t, s->num_sources);
@@ -343,19 +376,6 @@ static void sifive_plic_realize(DeviceState *dev, Error
**errp)
s->m_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
qdev_init_gpio_out(dev, s->m_external_irqs, s->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
- * hardware controlled when a PLIC is attached.
- */
- for (i = 0; i < s->num_harts; i++) {
- RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
- if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
- error_report("SEIP already claimed");
- exit(1);
- }
- }
-
msi_nonbroken = true;
}
@@ -380,6 +400,19 @@ static const VMStateDescription vmstate_sifive_plic = {
}
};
+static void sifive_plic_finalize(Object *obj)
+{
+ SiFivePLICState *s = SIFIVE_PLIC(obj);
+
+ /* free allocated arrays during realize */
+ g_free(s->addr_config);
+ g_free(s->source_priority);
+ g_free(s->target_priority);
+ g_free(s->pending);
+ g_free(s->claimed);
+ g_free(s->enable);
+}
+
static Property sifive_plic_properties[] = {
DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config),
DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0),
@@ -406,10 +439,11 @@ static void sifive_plic_class_init(ObjectClass *klass,
void *data)
}
static const TypeInfo sifive_plic_info = {
- .name = TYPE_SIFIVE_PLIC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(SiFivePLICState),
- .class_init = sifive_plic_class_init,
+ .name = TYPE_SIFIVE_PLIC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SiFivePLICState),
+ .class_init = sifive_plic_class_init,
+ .instance_finalize = sifive_plic_finalize,
};
static void sifive_plic_register_types(void)
--
2.35.1
[PATCH 2/5] target/riscv: add riscv_cpu_release_claimed_interrupts function, Damien Hedde, 2022/02/18
[PATCH 3/5] hw/intc/sifive_plic: report errors and free allocated memory,
Damien Hedde <=
[PATCH 4/5] hw/intc/riscv_aclint: swi: report errors and free allocated memory, Damien Hedde, 2022/02/18
[PATCH 5/5] hw/intc/riscv_aclint: mtimer: report errors and free allocated memory, Damien Hedde, 2022/02/18