|
@@ -293,11 +293,29 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * According to RISC-V ACLINT spec:
|
|
|
|
+ * - On MTIMER device reset, the MTIME register is cleared to zero.
|
|
|
|
+ * - On MTIMER device reset, the MTIMECMP registers are in unknown state.
|
|
|
|
+ */
|
|
|
|
+ RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Clear mtime register by writing to 0 it.
|
|
|
|
+ * Pending mtime interrupts will also be cleared at the same time.
|
|
|
|
+ */
|
|
|
|
+ riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
|
|
|
|
+}
|
|
|
|
+
|
|
static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
|
|
static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
{
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
dc->realize = riscv_aclint_mtimer_realize;
|
|
dc->realize = riscv_aclint_mtimer_realize;
|
|
device_class_set_props(dc, riscv_aclint_mtimer_properties);
|
|
device_class_set_props(dc, riscv_aclint_mtimer_properties);
|
|
|
|
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
|
|
|
|
+ rc->phases.enter = riscv_aclint_mtimer_reset_enter;
|
|
}
|
|
}
|
|
|
|
|
|
static const TypeInfo riscv_aclint_mtimer_info = {
|
|
static const TypeInfo riscv_aclint_mtimer_info = {
|
|
@@ -452,11 +470,32 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * According to RISC-V ACLINT spec:
|
|
|
|
+ * - On MSWI device reset, each MSIP register is cleared to zero.
|
|
|
|
+ *
|
|
|
|
+ * p.s. SSWI device reset does nothing since SETSIP register always reads 0.
|
|
|
|
+ */
|
|
|
|
+ RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (!swi->sswi) {
|
|
|
|
+ for (i = 0; i < swi->num_harts; i++) {
|
|
|
|
+ /* Clear MSIP registers by lowering software interrupts. */
|
|
|
|
+ qemu_irq_lower(swi->soft_irqs[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
|
|
static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
{
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
dc->realize = riscv_aclint_swi_realize;
|
|
dc->realize = riscv_aclint_swi_realize;
|
|
device_class_set_props(dc, riscv_aclint_swi_properties);
|
|
device_class_set_props(dc, riscv_aclint_swi_properties);
|
|
|
|
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
|
|
|
|
+ rc->phases.enter = riscv_aclint_swi_reset_enter;
|
|
}
|
|
}
|
|
|
|
|
|
static const TypeInfo riscv_aclint_swi_info = {
|
|
static const TypeInfo riscv_aclint_swi_info = {
|