diff options
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/xics.c | 174 | ||||
-rw-r--r-- | hw/intc/xics_kvm.c | 80 | ||||
-rw-r--r-- | hw/intc/xics_pnv.c | 15 |
3 files changed, 157 insertions, 112 deletions
diff --git a/hw/intc/xics.c b/hw/intc/xics.c index e73e623e3b..b9f1a3c972 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -294,7 +294,6 @@ static const VMStateDescription vmstate_icp_server = { static void icp_reset(void *dev) { ICPState *icp = ICP(dev); - ICPStateClass *icpc = ICP_GET_CLASS(icp); icp->xirr = 0; icp->pending_priority = 0xff; @@ -302,16 +301,11 @@ static void icp_reset(void *dev) /* Make all outputs are deasserted */ qemu_set_irq(icp->output, 0); - - if (icpc->reset) { - icpc->reset(icp); - } } static void icp_realize(DeviceState *dev, Error **errp) { ICPState *icp = ICP(dev); - ICPStateClass *icpc = ICP_GET_CLASS(dev); PowerPCCPU *cpu; CPUPPCState *env; Object *obj; @@ -351,10 +345,6 @@ static void icp_realize(DeviceState *dev, Error **errp) return; } - if (icpc->realize) { - icpc->realize(icp, errp); - } - qemu_register_reset(icp_reset, dev); vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); } @@ -547,9 +537,61 @@ static void ics_simple_eoi(ICSState *ics, uint32_t nr) } } -static void ics_simple_reset(void *dev) +static void ics_simple_reset(DeviceState *dev) +{ + ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); + + icsc->parent_reset(dev); +} + +static void ics_simple_reset_handler(void *dev) +{ + ics_simple_reset(dev); +} + +static void ics_simple_realize(DeviceState *dev, Error **errp) { ICSState *ics = ICS_SIMPLE(dev); + ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); + Error *local_err = NULL; + + icsc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs); + + qemu_register_reset(ics_simple_reset_handler, ics); +} + +static void ics_simple_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ICSStateClass *isc = ICS_BASE_CLASS(klass); + + device_class_set_parent_realize(dc, ics_simple_realize, + &isc->parent_realize); + device_class_set_parent_reset(dc, ics_simple_reset, + &isc->parent_reset); + + isc->reject = ics_simple_reject; + isc->resend = ics_simple_resend; + isc->eoi = ics_simple_eoi; +} + +static const TypeInfo ics_simple_info = { + .name = TYPE_ICS_SIMPLE, + .parent = TYPE_ICS_BASE, + .instance_size = sizeof(ICSState), + .class_init = ics_simple_class_init, + .class_size = sizeof(ICSStateClass), +}; + +static void ics_base_reset(DeviceState *dev) +{ + ICSState *ics = ICS_BASE(dev); int i; uint8_t flags[ics->nr_irqs]; @@ -566,7 +608,35 @@ static void ics_simple_reset(void *dev) } } -static int ics_simple_dispatch_pre_save(void *opaque) +static void ics_base_realize(DeviceState *dev, Error **errp) +{ + ICSState *ics = ICS_BASE(dev); + Object *obj; + Error *err = NULL; + + obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); + if (!obj) { + error_propagate(errp, err); + error_prepend(errp, "required link '" ICS_PROP_XICS "' not found: "); + return; + } + ics->xics = XICS_FABRIC(obj); + + if (!ics->nr_irqs) { + error_setg(errp, "Number of interrupts needs to be greater 0"); + return; + } + ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); +} + +static void ics_base_instance_init(Object *obj) +{ + ICSState *ics = ICS_BASE(obj); + + ics->offset = XICS_IRQ_BASE; +} + +static int ics_base_dispatch_pre_save(void *opaque) { ICSState *ics = opaque; ICSStateClass *info = ICS_BASE_GET_CLASS(ics); @@ -578,7 +648,7 @@ static int ics_simple_dispatch_pre_save(void *opaque) return 0; } -static int ics_simple_dispatch_post_load(void *opaque, int version_id) +static int ics_base_dispatch_post_load(void *opaque, int version_id) { ICSState *ics = opaque; ICSStateClass *info = ICS_BASE_GET_CLASS(ics); @@ -590,7 +660,7 @@ static int ics_simple_dispatch_post_load(void *opaque, int version_id) return 0; } -static const VMStateDescription vmstate_ics_simple_irq = { +static const VMStateDescription vmstate_ics_base_irq = { .name = "ics/irq", .version_id = 2, .minimum_version_id = 1, @@ -604,95 +674,36 @@ static const VMStateDescription vmstate_ics_simple_irq = { }, }; -static const VMStateDescription vmstate_ics_simple = { +static const VMStateDescription vmstate_ics_base = { .name = "ics", .version_id = 1, .minimum_version_id = 1, - .pre_save = ics_simple_dispatch_pre_save, - .post_load = ics_simple_dispatch_post_load, + .pre_save = ics_base_dispatch_pre_save, + .post_load = ics_base_dispatch_post_load, .fields = (VMStateField[]) { /* Sanity check */ VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL), VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, - vmstate_ics_simple_irq, + vmstate_ics_base_irq, ICSIRQState), VMSTATE_END_OF_LIST() }, }; -static void ics_simple_initfn(Object *obj) -{ - ICSState *ics = ICS_SIMPLE(obj); - - ics->offset = XICS_IRQ_BASE; -} - -static void ics_simple_realize(ICSState *ics, Error **errp) -{ - if (!ics->nr_irqs) { - error_setg(errp, "Number of interrupts needs to be greater 0"); - return; - } - ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); - ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs); - - qemu_register_reset(ics_simple_reset, ics); -} - -static Property ics_simple_properties[] = { +static Property ics_base_properties[] = { DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0), DEFINE_PROP_END_OF_LIST(), }; -static void ics_simple_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - ICSStateClass *isc = ICS_BASE_CLASS(klass); - - isc->realize = ics_simple_realize; - dc->props = ics_simple_properties; - dc->vmsd = &vmstate_ics_simple; - isc->reject = ics_simple_reject; - isc->resend = ics_simple_resend; - isc->eoi = ics_simple_eoi; -} - -static const TypeInfo ics_simple_info = { - .name = TYPE_ICS_SIMPLE, - .parent = TYPE_ICS_BASE, - .instance_size = sizeof(ICSState), - .class_init = ics_simple_class_init, - .class_size = sizeof(ICSStateClass), - .instance_init = ics_simple_initfn, -}; - -static void ics_base_realize(DeviceState *dev, Error **errp) -{ - ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); - ICSState *ics = ICS_BASE(dev); - Object *obj; - Error *err = NULL; - - obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); - if (!obj) { - error_propagate(errp, err); - error_prepend(errp, "required link '" ICS_PROP_XICS "' not found: "); - return; - } - ics->xics = XICS_FABRIC(obj); - - - if (icsc->realize) { - icsc->realize(ics, errp); - } -} - static void ics_base_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = ics_base_realize; + dc->props = ics_base_properties; + dc->reset = ics_base_reset; + dc->vmsd = &vmstate_ics_base; } static const TypeInfo ics_base_info = { @@ -700,6 +711,7 @@ static const TypeInfo ics_base_info = { .parent = TYPE_DEVICE, .abstract = true, .instance_size = sizeof(ICSState), + .instance_init = ics_base_instance_init, .class_init = ics_base_class_init, .class_size = sizeof(ICSStateClass), }; diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 8dba2f84e7..30c3769a20 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -114,22 +114,38 @@ static int icp_set_kvm_state(ICPState *icp, int version_id) return 0; } -static void icp_kvm_reset(ICPState *icp) +static void icp_kvm_reset(DeviceState *dev) { - icp_set_kvm_state(icp, 1); + ICPStateClass *icpc = ICP_GET_CLASS(dev); + + icpc->parent_reset(dev); + + icp_set_kvm_state(ICP(dev), 1); } -static void icp_kvm_realize(ICPState *icp, Error **errp) +static void icp_kvm_realize(DeviceState *dev, Error **errp) { - CPUState *cs = icp->cs; + ICPState *icp = ICP(dev); + ICPStateClass *icpc = ICP_GET_CLASS(icp); + Error *local_err = NULL; + CPUState *cs; KVMEnabledICP *enabled_icp; - unsigned long vcpu_id = kvm_arch_vcpu_id(cs); + unsigned long vcpu_id; int ret; if (kernel_xics_fd == -1) { abort(); } + icpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + cs = icp->cs; + vcpu_id = kvm_arch_vcpu_id(cs); + /* * If we are reusing a parked vCPU fd corresponding to the CPU * which was hot-removed earlier we don't have to renable @@ -154,12 +170,16 @@ static void icp_kvm_realize(ICPState *icp, Error **errp) static void icp_kvm_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); ICPStateClass *icpc = ICP_CLASS(klass); + device_class_set_parent_realize(dc, icp_kvm_realize, + &icpc->parent_realize); + device_class_set_parent_reset(dc, icp_kvm_reset, + &icpc->parent_reset); + icpc->pre_save = icp_get_kvm_state; icpc->post_load = icp_set_kvm_state; - icpc->realize = icp_kvm_realize; - icpc->reset = icp_kvm_reset; icpc->synchronize_state = icp_synchronize_state; } @@ -304,44 +324,46 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val) } } -static void ics_kvm_reset(void *dev) +static void ics_kvm_reset(DeviceState *dev) { - ICSState *ics = ICS_SIMPLE(dev); - int i; - uint8_t flags[ics->nr_irqs]; + ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); - for (i = 0; i < ics->nr_irqs; i++) { - flags[i] = ics->irqs[i].flags; - } - - memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); + icsc->parent_reset(dev); - for (i = 0; i < ics->nr_irqs; i++) { - ics->irqs[i].priority = 0xff; - ics->irqs[i].saved_priority = 0xff; - ics->irqs[i].flags = flags[i]; - } + ics_set_kvm_state(ICS_KVM(dev), 1); +} - ics_set_kvm_state(ics, 1); +static void ics_kvm_reset_handler(void *dev) +{ + ics_kvm_reset(dev); } -static void ics_kvm_realize(ICSState *ics, Error **errp) +static void ics_kvm_realize(DeviceState *dev, Error **errp) { - if (!ics->nr_irqs) { - error_setg(errp, "Number of interrupts needs to be greater 0"); + ICSState *ics = ICS_KVM(dev); + ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); + Error *local_err = NULL; + + icsc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } - ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs); - qemu_register_reset(ics_kvm_reset, ics); + qemu_register_reset(ics_kvm_reset_handler, ics); } static void ics_kvm_class_init(ObjectClass *klass, void *data) { ICSStateClass *icsc = ICS_BASE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_parent_realize(dc, ics_kvm_realize, + &icsc->parent_realize); + device_class_set_parent_reset(dc, ics_kvm_reset, + &icsc->parent_reset); - icsc->realize = ics_kvm_realize; icsc->pre_save = ics_get_kvm_state; icsc->post_load = ics_set_kvm_state; icsc->synchronize_state = ics_synchronize_state; @@ -349,7 +371,7 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data) static const TypeInfo ics_kvm_info = { .name = TYPE_ICS_KVM, - .parent = TYPE_ICS_SIMPLE, + .parent = TYPE_ICS_BASE, .instance_size = sizeof(ICSState), .class_init = ics_kvm_class_init, }; diff --git a/hw/intc/xics_pnv.c b/hw/intc/xics_pnv.c index c87de2189c..fa48505f36 100644 --- a/hw/intc/xics_pnv.c +++ b/hw/intc/xics_pnv.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "sysemu/sysemu.h" #include "qemu/log.h" #include "hw/ppc/xics.h" @@ -158,9 +159,18 @@ static const MemoryRegionOps pnv_icp_ops = { }, }; -static void pnv_icp_realize(ICPState *icp, Error **errp) +static void pnv_icp_realize(DeviceState *dev, Error **errp) { + ICPState *icp = ICP(dev); PnvICPState *pnv_icp = PNV_ICP(icp); + ICPStateClass *icpc = ICP_GET_CLASS(icp); + Error *local_err = NULL; + + icpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } memory_region_init_io(&pnv_icp->mmio, OBJECT(icp), &pnv_icp_ops, icp, "icp-thread", 0x1000); @@ -171,7 +181,8 @@ static void pnv_icp_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); ICPStateClass *icpc = ICP_CLASS(klass); - icpc->realize = pnv_icp_realize; + device_class_set_parent_realize(dc, pnv_icp_realize, + &icpc->parent_realize); dc->desc = "PowerNV ICP"; } |