/* 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)