diff options
Diffstat (limited to 'hw/intc')
| -rw-r--r-- | hw/intc/arm_gicv3_its.c | 44 | ||||
| -rw-r--r-- | hw/intc/loongarch_extioi.c | 111 | ||||
| -rw-r--r-- | hw/intc/loongarch_extioi_common.c | 112 | ||||
| -rw-r--r-- | hw/intc/loongarch_pch_pic.c | 105 | ||||
| -rw-r--r-- | hw/intc/loongarch_pic_common.c | 96 | ||||
| -rw-r--r-- | hw/intc/meson.build | 4 |
6 files changed, 304 insertions, 168 deletions
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 2388a96799..936368c901 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -465,7 +465,7 @@ static ItsCmdResult lookup_vte(GICv3ITSState *s, const char *who, static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite, int irqlevel) { - CTEntry cte; + CTEntry cte = {}; ItsCmdResult cmdres; cmdres = lookup_cte(s, __func__, ite->icid, &cte); @@ -479,7 +479,7 @@ static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite, static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite, int irqlevel) { - VTEntry vte; + VTEntry vte = {}; ItsCmdResult cmdres; cmdres = lookup_vte(s, __func__, ite->vpeid, &vte); @@ -514,8 +514,8 @@ static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite, static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid, uint32_t eventid, ItsCmdType cmd) { - DTEntry dte; - ITEntry ite; + DTEntry dte = {}; + ITEntry ite = {}; ItsCmdResult cmdres; int irqlevel; @@ -583,8 +583,8 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt, uint32_t pIntid = 0; uint64_t num_eventids; uint16_t icid = 0; - DTEntry dte; - ITEntry ite; + DTEntry dte = {}; + ITEntry ite = {}; devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT; eventid = cmdpkt[1] & EVENTID_MASK; @@ -651,8 +651,8 @@ static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt, { uint32_t devid, eventid, vintid, doorbell, vpeid; uint32_t num_eventids; - DTEntry dte; - ITEntry ite; + DTEntry dte = {}; + ITEntry ite = {}; if (!its_feature_virtual(s)) { return CMD_CONTINUE; @@ -761,7 +761,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte) static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt) { uint16_t icid; - CTEntry cte; + CTEntry cte = {}; icid = cmdpkt[2] & ICID_MASK; cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK; @@ -822,7 +822,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte) static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt) { uint32_t devid; - DTEntry dte; + DTEntry dte = {}; devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT; dte.size = cmdpkt[1] & SIZE_MASK; @@ -886,9 +886,9 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt) { uint32_t devid, eventid; uint16_t new_icid; - DTEntry dte; - CTEntry old_cte, new_cte; - ITEntry old_ite; + DTEntry dte = {}; + CTEntry old_cte = {}, new_cte = {}; + ITEntry old_ite = {}; ItsCmdResult cmdres; devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID); @@ -965,7 +965,7 @@ static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte) static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt) { - VTEntry vte; + VTEntry vte = {}; uint32_t vpeid; if (!its_feature_virtual(s)) { @@ -1030,7 +1030,7 @@ static void vmovp_callback(gpointer data, gpointer opaque) */ GICv3ITSState *s = data; VmovpCallbackData *cbdata = opaque; - VTEntry vte; + VTEntry vte = {}; ItsCmdResult cmdres; cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte); @@ -1085,9 +1085,9 @@ static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt) { uint32_t devid, eventid, vpeid, doorbell; bool doorbell_valid; - DTEntry dte; - ITEntry ite; - VTEntry old_vte, new_vte; + DTEntry dte = {}; + ITEntry ite = {}; + VTEntry old_vte = {}, new_vte = {}; ItsCmdResult cmdres; if (!its_feature_virtual(s)) { @@ -1186,10 +1186,10 @@ static ItsCmdResult process_vinvall(GICv3ITSState *s, const uint64_t *cmdpkt) static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt) { uint32_t devid, eventid; - ITEntry ite; - DTEntry dte; - CTEntry cte; - VTEntry vte; + ITEntry ite = {}; + DTEntry dte = {}; + CTEntry cte = {}; + VTEntry vte = {}; ItsCmdResult cmdres; devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID); diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index be7d3997fd..4a1a7c357c 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -10,16 +10,13 @@ #include "qemu/log.h" #include "qapi/error.h" #include "hw/irq.h" -#include "hw/sysbus.h" #include "hw/loongarch/virt.h" -#include "hw/qdev-properties.h" #include "exec/address-spaces.h" #include "hw/intc/loongarch_extioi.h" -#include "migration/vmstate.h" #include "trace.h" -static void extioi_update_irq(LoongArchExtIOI *s, int irq, int level) +static void extioi_update_irq(LoongArchExtIOICommonState *s, int irq, int level) { int ipnum, cpu, found, irq_index, irq_mask; @@ -54,7 +51,7 @@ static void extioi_update_irq(LoongArchExtIOI *s, int irq, int level) static void extioi_setirq(void *opaque, int irq, int level) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); trace_loongarch_extioi_setirq(irq, level); if (level) { set_bit32(irq, s->isr); @@ -67,7 +64,7 @@ static void extioi_setirq(void *opaque, int irq, int level) static MemTxResult extioi_readw(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); unsigned long offset = addr & 0xffff; uint32_t index, cpu; @@ -106,7 +103,7 @@ static MemTxResult extioi_readw(void *opaque, hwaddr addr, uint64_t *data, return MEMTX_OK; } -static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\ +static inline void extioi_enable_irq(LoongArchExtIOICommonState *s, int index,\ uint32_t mask, int level) { uint32_t val; @@ -125,8 +122,8 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\ } } -static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq, - uint64_t val, bool notify) +static inline void extioi_update_sw_coremap(LoongArchExtIOICommonState *s, + int irq, uint64_t val, bool notify) { int i, cpu; @@ -162,8 +159,8 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq, } } -static inline void extioi_update_sw_ipmap(LoongArchExtIOI *s, int index, - uint64_t val) +static inline void extioi_update_sw_ipmap(LoongArchExtIOICommonState *s, + int index, uint64_t val) { int i; uint8_t ipnum; @@ -186,7 +183,7 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr, uint64_t val, unsigned size, MemTxAttrs attrs) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); int cpu, index, old_data, irq; uint32_t offset; @@ -266,7 +263,7 @@ static const MemoryRegionOps extioi_ops = { static MemTxResult extioi_virt_readw(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); switch (addr) { case EXTIOI_VIRT_FEATURES: @@ -286,7 +283,7 @@ static MemTxResult extioi_virt_writew(void *opaque, hwaddr addr, uint64_t val, unsigned size, MemTxAttrs attrs) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); switch (addr) { case EXTIOI_VIRT_FEATURES: @@ -320,12 +317,15 @@ static const MemoryRegionOps extioi_virt_ops = { static void loongarch_extioi_realize(DeviceState *dev, Error **errp) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(dev); + LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_GET_CLASS(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + Error *local_err = NULL; int i, pin; - if (s->num_cpu == 0) { - error_setg(errp, "num-cpu must be at least 1"); + lec->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } @@ -360,23 +360,23 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp) } } -static void loongarch_extioi_finalize(Object *obj) +static void loongarch_extioi_unrealize(DeviceState *dev) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(obj); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(dev); g_free(s->cpu); } static void loongarch_extioi_reset(DeviceState *d) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(d); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(d); s->status = 0; } static int vmstate_extioi_post_load(void *opaque, int version_id) { - LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); int i, start_irq; for (i = 0; i < (EXTIOI_IRQS / 4); i++) { @@ -391,65 +391,28 @@ static int vmstate_extioi_post_load(void *opaque, int version_id) return 0; } -static const VMStateDescription vmstate_extioi_core = { - .name = "extioi-core", - .version_id = 1, - .minimum_version_id = 1, - .fields = (const VMStateField[]) { - VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_loongarch_extioi = { - .name = TYPE_LOONGARCH_EXTIOI, - .version_id = 3, - .minimum_version_id = 3, - .post_load = vmstate_extioi_post_load, - .fields = (const VMStateField[]) { - VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT), - VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI, - EXTIOI_IRQS_NODETYPE_COUNT / 2), - VMSTATE_UINT32_ARRAY(enable, LoongArchExtIOI, EXTIOI_IRQS / 32), - VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32), - VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4), - VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4), - - VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu, - vmstate_extioi_core, ExtIOICore), - VMSTATE_UINT32(features, LoongArchExtIOI), - VMSTATE_UINT32(status, LoongArchExtIOI), - VMSTATE_END_OF_LIST() - } -}; - -static const Property extioi_properties[] = { - DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1), - DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOI, features, - EXTIOI_HAS_VIRT_EXTENSION, 0), -}; - static void loongarch_extioi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_CLASS(klass); + LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass); - dc->realize = loongarch_extioi_realize; + device_class_set_parent_realize(dc, loongarch_extioi_realize, + &lec->parent_realize); + device_class_set_parent_unrealize(dc, loongarch_extioi_unrealize, + &lec->parent_unrealize); device_class_set_legacy_reset(dc, loongarch_extioi_reset); - device_class_set_props(dc, extioi_properties); - dc->vmsd = &vmstate_loongarch_extioi; + lecc->post_load = vmstate_extioi_post_load; } -static const TypeInfo loongarch_extioi_info = { - .name = TYPE_LOONGARCH_EXTIOI, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(struct LoongArchExtIOI), - .class_init = loongarch_extioi_class_init, - .instance_finalize = loongarch_extioi_finalize, +static const TypeInfo loongarch_extioi_types[] = { + { + .name = TYPE_LOONGARCH_EXTIOI, + .parent = TYPE_LOONGARCH_EXTIOI_COMMON, + .instance_size = sizeof(LoongArchExtIOIState), + .class_size = sizeof(LoongArchExtIOIClass), + .class_init = loongarch_extioi_class_init, + } }; -static void loongarch_extioi_register_types(void) -{ - type_register_static(&loongarch_extioi_info); -} - -type_init(loongarch_extioi_register_types) +DEFINE_TYPES(loongarch_extioi_types) diff --git a/hw/intc/loongarch_extioi_common.c b/hw/intc/loongarch_extioi_common.c new file mode 100644 index 0000000000..e4c1cc3c98 --- /dev/null +++ b/hw/intc/loongarch_extioi_common.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Loongson extioi interrupt controller emulation + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/intc/loongarch_extioi_common.h" +#include "migration/vmstate.h" + +static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp) +{ + LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)dev; + + if (s->num_cpu == 0) { + error_setg(errp, "num-cpu must be at least 1"); + return; + } +} + +static int loongarch_extioi_common_pre_save(void *opaque) +{ + LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque; + LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s); + + if (lecc->pre_save) { + return lecc->pre_save(s); + } + + return 0; +} + +static int loongarch_extioi_common_post_load(void *opaque, int version_id) +{ + LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque; + LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(s); + + if (lecc->post_load) { + return lecc->post_load(s, version_id); + } + + return 0; +} + +static const VMStateDescription vmstate_extioi_core = { + .name = "extioi-core", + .version_id = 1, + .minimum_version_id = 1, + .fields = (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_loongarch_extioi = { + .name = "loongarch.extioi", + .version_id = 3, + .minimum_version_id = 3, + .pre_save = loongarch_extioi_common_pre_save, + .post_load = loongarch_extioi_common_post_load, + .fields = (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOICommonState, + EXTIOI_IRQS_GROUP_COUNT), + VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOICommonState, + EXTIOI_IRQS_NODETYPE_COUNT / 2), + VMSTATE_UINT32_ARRAY(enable, LoongArchExtIOICommonState, + EXTIOI_IRQS / 32), + VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOICommonState, + EXTIOI_IRQS / 32), + VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOICommonState, + EXTIOI_IRQS_IPMAP_SIZE / 4), + VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOICommonState, + EXTIOI_IRQS / 4), + VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOICommonState, + num_cpu, vmstate_extioi_core, ExtIOICore), + VMSTATE_UINT32(features, LoongArchExtIOICommonState), + VMSTATE_UINT32(status, LoongArchExtIOICommonState), + VMSTATE_END_OF_LIST() + } +}; + +static const Property extioi_properties[] = { + DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOICommonState, num_cpu, 1), + DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOICommonState, + features, EXTIOI_HAS_VIRT_EXTENSION, 0), +}; + +static void loongarch_extioi_common_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass); + + device_class_set_parent_realize(dc, loongarch_extioi_common_realize, + &lecc->parent_realize); + device_class_set_props(dc, extioi_properties); + dc->vmsd = &vmstate_loongarch_extioi; +} + +static const TypeInfo loongarch_extioi_common_types[] = { + { + .name = TYPE_LOONGARCH_EXTIOI_COMMON, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(LoongArchExtIOICommonState), + .class_size = sizeof(LoongArchExtIOICommonClass), + .class_init = loongarch_extioi_common_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(loongarch_extioi_common_types) diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c index dc93c90b3c..acd75ccb0c 100644 --- a/hw/intc/loongarch_pch_pic.c +++ b/hw/intc/loongarch_pch_pic.c @@ -7,17 +7,13 @@ #include "qemu/osdep.h" #include "qemu/bitops.h" -#include "hw/sysbus.h" -#include "hw/loongarch/virt.h" -#include "hw/pci-host/ls7a.h" #include "hw/irq.h" #include "hw/intc/loongarch_pch_pic.h" -#include "hw/qdev-properties.h" -#include "migration/vmstate.h" #include "trace.h" #include "qapi/error.h" -static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level) +static void pch_pic_update_irq(LoongArchPICCommonState *s, uint64_t mask, + int level) { uint64_t val; int irq; @@ -45,7 +41,7 @@ static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level) static void pch_pic_irq_handler(void *opaque, int irq, int level) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t mask = 1ULL << irq; assert(irq < s->irq_num); @@ -78,7 +74,7 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level) static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t val = 0; uint32_t offset = addr & 0xfff; @@ -136,7 +132,7 @@ static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi) static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint32_t offset, old_valid, data = (uint32_t)value; uint64_t old, int_mask; offset = addr & 0xfff; @@ -208,7 +204,7 @@ static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr, static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t val = 0; uint32_t offset = addr & 0xfff; @@ -236,7 +232,7 @@ static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr, static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint32_t offset, data = (uint32_t)value; offset = addr & 0xfff; @@ -263,7 +259,7 @@ static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr, static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t val = 0; uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; int64_t offset_tmp; @@ -292,7 +288,7 @@ static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr, static void loongarch_pch_pic_writeb(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); int32_t offset_tmp; uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; @@ -360,7 +356,7 @@ static const MemoryRegionOps loongarch_pch_pic_reg8_ops = { static void loongarch_pch_pic_reset(DeviceState *d) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(d); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(d); int i; s->int_mask = -1; @@ -379,30 +375,27 @@ static void loongarch_pch_pic_reset(DeviceState *d) s->int_polarity = 0x0; } -static void loongarch_pch_pic_realize(DeviceState *dev, Error **errp) +static void loongarch_pic_realize(DeviceState *dev, Error **errp) { - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(dev); - - if (!s->irq_num || s->irq_num > VIRT_PCH_PIC_IRQ_NUM) { - error_setg(errp, "Invalid 'pic_irq_num'"); + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(dev); + LoongarchPICClass *lpc = LOONGARCH_PIC_GET_CLASS(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + Error *local_err = NULL; + + lpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } qdev_init_gpio_out(dev, s->parent_irq, s->irq_num); qdev_init_gpio_in(dev, pch_pic_irq_handler, s->irq_num); -} - -static void loongarch_pch_pic_init(Object *obj) -{ - LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - - memory_region_init_io(&s->iomem32_low, obj, + memory_region_init_io(&s->iomem32_low, OBJECT(dev), &loongarch_pch_pic_reg32_low_ops, s, PCH_PIC_NAME(.reg32_part1), 0x100); - memory_region_init_io(&s->iomem8, obj, &loongarch_pch_pic_reg8_ops, + memory_region_init_io(&s->iomem8, OBJECT(dev), &loongarch_pch_pic_reg8_ops, s, PCH_PIC_NAME(.reg8), 0x2a0); - memory_region_init_io(&s->iomem32_high, obj, + memory_region_init_io(&s->iomem32_high, OBJECT(dev), &loongarch_pch_pic_reg32_high_ops, s, PCH_PIC_NAME(.reg32_part2), 0xc60); sysbus_init_mmio(sbd, &s->iomem32_low); @@ -411,52 +404,24 @@ static void loongarch_pch_pic_init(Object *obj) } -static const Property loongarch_pch_pic_properties[] = { - DEFINE_PROP_UINT32("pch_pic_irq_num", LoongArchPCHPIC, irq_num, 0), -}; - -static const VMStateDescription vmstate_loongarch_pch_pic = { - .name = TYPE_LOONGARCH_PCH_PIC, - .version_id = 1, - .minimum_version_id = 1, - .fields = (const VMStateField[]) { - VMSTATE_UINT64(int_mask, LoongArchPCHPIC), - VMSTATE_UINT64(htmsi_en, LoongArchPCHPIC), - VMSTATE_UINT64(intedge, LoongArchPCHPIC), - VMSTATE_UINT64(intclr, LoongArchPCHPIC), - VMSTATE_UINT64(auto_crtl0, LoongArchPCHPIC), - VMSTATE_UINT64(auto_crtl1, LoongArchPCHPIC), - VMSTATE_UINT8_ARRAY(route_entry, LoongArchPCHPIC, 64), - VMSTATE_UINT8_ARRAY(htmsi_vector, LoongArchPCHPIC, 64), - VMSTATE_UINT64(last_intirr, LoongArchPCHPIC), - VMSTATE_UINT64(intirr, LoongArchPCHPIC), - VMSTATE_UINT64(intisr, LoongArchPCHPIC), - VMSTATE_UINT64(int_polarity, LoongArchPCHPIC), - VMSTATE_END_OF_LIST() - } -}; - -static void loongarch_pch_pic_class_init(ObjectClass *klass, void *data) +static void loongarch_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + LoongarchPICClass *lpc = LOONGARCH_PIC_CLASS(klass); - dc->realize = loongarch_pch_pic_realize; device_class_set_legacy_reset(dc, loongarch_pch_pic_reset); - dc->vmsd = &vmstate_loongarch_pch_pic; - device_class_set_props(dc, loongarch_pch_pic_properties); + device_class_set_parent_realize(dc, loongarch_pic_realize, + &lpc->parent_realize); } -static const TypeInfo loongarch_pch_pic_info = { - .name = TYPE_LOONGARCH_PCH_PIC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LoongArchPCHPIC), - .instance_init = loongarch_pch_pic_init, - .class_init = loongarch_pch_pic_class_init, +static const TypeInfo loongarch_pic_types[] = { + { + .name = TYPE_LOONGARCH_PIC, + .parent = TYPE_LOONGARCH_PIC_COMMON, + .instance_size = sizeof(LoongarchPICState), + .class_size = sizeof(LoongarchPICClass), + .class_init = loongarch_pic_class_init, + } }; -static void loongarch_pch_pic_register_types(void) -{ - type_register_static(&loongarch_pch_pic_info); -} - -type_init(loongarch_pch_pic_register_types) +DEFINE_TYPES(loongarch_pic_types) diff --git a/hw/intc/loongarch_pic_common.c b/hw/intc/loongarch_pic_common.c new file mode 100644 index 0000000000..e7f541db4b --- /dev/null +++ b/hw/intc/loongarch_pic_common.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Loongson 7A1000 I/O interrupt controller. + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/intc/loongarch_pic_common.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" + +static int loongarch_pic_pre_save(void *opaque) +{ + LoongArchPICCommonState *s = (LoongArchPICCommonState *)opaque; + LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_GET_CLASS(s); + + if (lpcc->pre_save) { + return lpcc->pre_save(s); + } + + return 0; +} + +static int loongarch_pic_post_load(void *opaque, int version_id) +{ + LoongArchPICCommonState *s = (LoongArchPICCommonState *)opaque; + LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_GET_CLASS(s); + + if (lpcc->post_load) { + return lpcc->post_load(s, version_id); + } + + return 0; +} + +static void loongarch_pic_common_realize(DeviceState *dev, Error **errp) +{ + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(dev); + + if (!s->irq_num || s->irq_num > VIRT_PCH_PIC_IRQ_NUM) { + error_setg(errp, "Invalid 'pic_irq_num'"); + return; + } +} + +static const Property loongarch_pic_common_properties[] = { + DEFINE_PROP_UINT32("pch_pic_irq_num", LoongArchPICCommonState, irq_num, 0), +}; + +static const VMStateDescription vmstate_loongarch_pic_common = { + .name = "loongarch_pch_pic", + .version_id = 1, + .minimum_version_id = 1, + .pre_save = loongarch_pic_pre_save, + .post_load = loongarch_pic_post_load, + .fields = (const VMStateField[]) { + VMSTATE_UINT64(int_mask, LoongArchPICCommonState), + VMSTATE_UINT64(htmsi_en, LoongArchPICCommonState), + VMSTATE_UINT64(intedge, LoongArchPICCommonState), + VMSTATE_UINT64(intclr, LoongArchPICCommonState), + VMSTATE_UINT64(auto_crtl0, LoongArchPICCommonState), + VMSTATE_UINT64(auto_crtl1, LoongArchPICCommonState), + VMSTATE_UINT8_ARRAY(route_entry, LoongArchPICCommonState, 64), + VMSTATE_UINT8_ARRAY(htmsi_vector, LoongArchPICCommonState, 64), + VMSTATE_UINT64(last_intirr, LoongArchPICCommonState), + VMSTATE_UINT64(intirr, LoongArchPICCommonState), + VMSTATE_UINT64(intisr, LoongArchPICCommonState), + VMSTATE_UINT64(int_polarity, LoongArchPICCommonState), + VMSTATE_END_OF_LIST() + } +}; + +static void loongarch_pic_common_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_CLASS(klass); + + device_class_set_parent_realize(dc, loongarch_pic_common_realize, + &lpcc->parent_realize); + device_class_set_props(dc, loongarch_pic_common_properties); + dc->vmsd = &vmstate_loongarch_pic_common; +} + +static const TypeInfo loongarch_pic_common_types[] = { + { + .name = TYPE_LOONGARCH_PIC_COMMON, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(LoongArchPICCommonState), + .class_size = sizeof(LoongArchPICCommonClass), + .class_init = loongarch_pic_common_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(loongarch_pic_common_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 6bfdc4eb33..510fdfb688 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -71,6 +71,6 @@ specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) specific_ss.add(when: 'CONFIG_LOONGSON_IPI_COMMON', if_true: files('loongson_ipi_common.c')) specific_ss.add(when: 'CONFIG_LOONGSON_IPI', if_true: files('loongson_ipi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c')) -specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c', 'loongarch_pic_common.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c')) -specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c')) |