[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common
From: |
Alexey Kardashevskiy |
Subject: |
[Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common |
Date: |
Tue, 6 Aug 2013 18:27:52 +1000 |
The upcoming XICS-KVM support will use bits of emulated XICS code.
So this introduces new level of hierarchy - "xics-common" class. Both
emulated XICS and XICS-KVM will inherit from it and override class
callbacks when required.
The new "xics-common" class implements:
1. replaces static "nr_irqs" and "nr_servers" properties with
the dynamic ones and adds callbacks to be executed when properties
are set.
2. xics_cpu_setup() callback renamed to xics_common_cpu_setup() as
it is a common part for both XICS'es
3. xics_reset() renamed to xics_common_reset() for the same reason.
The emulated XICS changes:
1. instance_init() callback is replaced with "nr_irqs" property callback
as it creates ICS which needs the nr_irqs property set.
2. the part of xics_realize() which creates ICPs is moved to
the "nr_servers" property callback as realize() is too late to
create/initialize devices and instance_init() is too early to create
devices as the number of child devices comes via the "nr_servers"
property.
3. added ics_initfn() which does a little part of what xics_realize() did.
Signed-off-by: Alexey Kardashevskiy <address@hidden>
---
hw/intc/xics.c | 190 +++++++++++++++++++++++++++++++++++---------------
include/hw/ppc/xics.h | 11 ++-
2 files changed, 143 insertions(+), 58 deletions(-)
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 20840e3..95865aa 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -30,6 +30,112 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/xics.h"
#include "qemu/error-report.h"
+#include "qapi/visitor.h"
+
+/*
+ * XICS Common class - parent for emulated XICS and KVM-XICS
+ */
+
+static void xics_common_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
+{
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
+ ICPState *ss = &icp->ss[cs->cpu_index];
+
+ assert(cs->cpu_index < icp->nr_servers);
+
+ switch (PPC_INPUT(env)) {
+ case PPC_FLAGS_INPUT_POWER7:
+ ss->output = env->irq_inputs[POWER7_INPUT_INT];
+ break;
+
+ case PPC_FLAGS_INPUT_970:
+ ss->output = env->irq_inputs[PPC970_INPUT_INT];
+ break;
+
+ default:
+ error_report("XICS interrupt controller does not support this CPU "
+ "bus model");
+ abort();
+ }
+}
+
+void xics_prop_set_nr_irqs(Object *obj, struct Visitor *v,
+ void *opaque, const char *name, struct Error **errp)
+{
+ XICSState *icp = XICS_COMMON(obj);
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
+ Error *error = NULL;
+ int64_t value;
+
+ visit_type_int(v, &value, name, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ assert(info->set_nr_irqs);
+ assert(!icp->nr_irqs);
+ assert(!icp->ics);
+ info->set_nr_irqs(icp, value);
+}
+
+void xics_prop_set_nr_servers(Object *obj, struct Visitor *v,
+ void *opaque, const char *name, struct Error
**errp)
+{
+ XICSState *icp = XICS_COMMON(obj);
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
+ Error *error = NULL;
+ int64_t value;
+
+ visit_type_int(v, &value, name, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ assert(info->set_nr_servers);
+ assert(!icp->nr_servers);
+ info->set_nr_servers(icp, value);
+}
+
+static void xics_common_initfn(Object *obj)
+{
+ object_property_add(obj, "nr_irqs", "int",
+ NULL, xics_prop_set_nr_irqs, NULL, NULL, NULL);
+ object_property_add(obj, "nr_servers", "int",
+ NULL, xics_prop_set_nr_servers, NULL, NULL, NULL);
+}
+
+static void xics_common_reset(DeviceState *d)
+{
+ XICSState *icp = XICS_COMMON(d);
+ int i;
+
+ for (i = 0; i < icp->nr_servers; i++) {
+ device_reset(DEVICE(&icp->ss[i]));
+ }
+
+ device_reset(DEVICE(icp->ics));
+}
+
+static void xics_common_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ XICSStateClass *xsc = XICS_COMMON_CLASS(oc);
+
+ dc->reset = xics_common_reset;
+ xsc->cpu_setup = xics_common_cpu_setup;
+}
+
+static const TypeInfo xics_common_info = {
+ .name = TYPE_XICS_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XICSState),
+ .class_size = sizeof(XICSStateClass),
+ .instance_init = xics_common_initfn,
+ .class_init = xics_common_class_init,
+};
/*
* ICP: Presentation layer
@@ -443,6 +549,13 @@ static const VMStateDescription vmstate_ics = {
},
};
+static void ics_initfn(Object *obj)
+{
+ ICSState *ics = ICS(obj);
+
+ ics->offset = XICS_IRQ_BASE;
+}
+
static int ics_realize(DeviceState *dev)
{
ICSState *ics = ICS(dev);
@@ -472,6 +585,7 @@ static const TypeInfo ics_info = {
.instance_size = sizeof(ICSState),
.class_init = ics_class_init,
.class_size = sizeof(ICSStateClass),
+ .instance_init = ics_initfn,
};
/*
@@ -651,47 +765,32 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment
*spapr,
/*
* XICS
*/
+void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs)
+{
+ icp->ics = ICS(object_new(TYPE_ICS));
+ object_property_add_child(OBJECT(icp), "ics", OBJECT(icp->ics), NULL);
+ icp->ics->icp = icp;
+ icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
+}
-static void xics_reset(DeviceState *d)
+void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers)
{
- XICSState *icp = XICS(d);
int i;
+ icp->nr_servers = nr_servers;
+
+ icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
for (i = 0; i < icp->nr_servers; i++) {
- device_reset(DEVICE(&icp->ss[i]));
- }
-
- device_reset(DEVICE(icp->ics));
-}
-
-static void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- CPUPPCState *env = &cpu->env;
- ICPState *ss = &icp->ss[cs->cpu_index];
-
- assert(cs->cpu_index < icp->nr_servers);
-
- switch (PPC_INPUT(env)) {
- case PPC_FLAGS_INPUT_POWER7:
- ss->output = env->irq_inputs[POWER7_INPUT_INT];
- break;
-
- case PPC_FLAGS_INPUT_970:
- ss->output = env->irq_inputs[PPC970_INPUT_INT];
- break;
-
- default:
- error_report("XICS interrupt controller does not support this CPU "
- "bus model");
- abort();
+ char buffer[32];
+ object_initialize(&icp->ss[i], TYPE_ICP);
+ snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+ object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
NULL);
}
}
static void xics_realize(DeviceState *dev, Error **errp)
{
XICSState *icp = XICS(dev);
- ICSState *ics = icp->ics;
Error *error = NULL;
int i;
@@ -706,9 +805,6 @@ static void xics_realize(DeviceState *dev, Error **errp)
spapr_register_hypercall(H_XIRR, h_xirr);
spapr_register_hypercall(H_EOI, h_eoi);
- ics->nr_irqs = icp->nr_irqs;
- ics->offset = XICS_IRQ_BASE;
- ics->icp = icp;
object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
if (error) {
error_propagate(errp, error);
@@ -716,12 +812,7 @@ static void xics_realize(DeviceState *dev, Error **errp)
}
assert(icp->nr_servers);
- icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
for (i = 0; i < icp->nr_servers; i++) {
- char buffer[32];
- object_initialize(&icp->ss[i], TYPE_ICP);
- snprintf(buffer, sizeof(buffer), "icp[%d]", i);
- object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
NULL);
object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized",
&error);
if (error) {
error_propagate(errp, error);
@@ -730,42 +821,27 @@ static void xics_realize(DeviceState *dev, Error **errp)
}
}
-static void xics_initfn(Object *obj)
-{
- XICSState *xics = XICS(obj);
-
- xics->ics = ICS(object_new(TYPE_ICS));
- object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
-}
-
-static Property xics_properties[] = {
- DEFINE_PROP_UINT32("nr_servers", XICSState, nr_servers, -1),
- DEFINE_PROP_UINT32("nr_irqs", XICSState, nr_irqs, -1),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void xics_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
XICSStateClass *xsc = XICS_CLASS(oc);
dc->realize = xics_realize;
- dc->props = xics_properties;
- dc->reset = xics_reset;
- xsc->cpu_setup = xics_cpu_setup;
+ xsc->set_nr_irqs = xics_set_nr_irqs;
+ xsc->set_nr_servers = xics_set_nr_servers;
}
static const TypeInfo xics_info = {
.name = TYPE_XICS,
- .parent = TYPE_SYS_BUS_DEVICE,
+ .parent = TYPE_XICS_COMMON,
.instance_size = sizeof(XICSState),
.class_size = sizeof(XICSStateClass),
.class_init = xics_class_init,
- .instance_init = xics_initfn,
};
static void xics_register_types(void)
{
+ type_register_static(&xics_common_info);
type_register_static(&xics_info);
type_register_static(&ics_info);
type_register_static(&icp_info);
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 90ecaf8..1066f69 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -29,11 +29,18 @@
#include "hw/sysbus.h"
+#define TYPE_XICS_COMMON "xics-common"
+#define XICS_COMMON(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_COMMON)
+
#define TYPE_XICS "xics"
#define XICS(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS)
+#define XICS_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
#define XICS_CLASS(klass) \
OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS)
+#define XICS_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
#define XICS_GET_CLASS(obj) \
OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS)
@@ -58,6 +65,8 @@ struct XICSStateClass {
DeviceClass parent_class;
void (*cpu_setup)(XICSState *icp, PowerPCCPU *cpu);
+ void (*set_nr_irqs)(XICSState *icp, uint32_t nr_irqs);
+ void (*set_nr_servers)(XICSState *icp, uint32_t nr_servers);
};
struct XICSState {
@@ -138,7 +147,7 @@ void xics_set_irq_type(XICSState *icp, int irq, bool lsi);
static inline void xics_dispatch_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
{
- XICSStateClass *info = XICS_GET_CLASS(icp);
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
assert(info->cpu_setup);
info->cpu_setup(icp, cpu);
--
1.8.3.2
- [Qemu-ppc] [PATCH 0/6 v2] xics: reworks and in-kernel support, Alexey Kardashevskiy, 2013/08/06
- [Qemu-ppc] [PATCH 1/6] target-ppc: Add helper for KVM_PPC_RTAS_DEFINE_TOKEN, Alexey Kardashevskiy, 2013/08/06
- [Qemu-ppc] [PATCH 2/6] xics: add pre_save/post_load/cpu_setup dispatchers, Alexey Kardashevskiy, 2013/08/06
- [Qemu-ppc] [PATCH 3/6] xics: move registration of global state to realize(), Alexey Kardashevskiy, 2013/08/06
- [Qemu-ppc] [PATCH 4/6] xics: minor changes and cleanups, Alexey Kardashevskiy, 2013/08/06
- [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common,
Alexey Kardashevskiy <=
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Andreas Färber, 2013/08/06
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Alexey Kardashevskiy, 2013/08/07
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Andreas Färber, 2013/08/07
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Alexey Kardashevskiy, 2013/08/07
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Andreas Färber, 2013/08/07
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Alexey Kardashevskiy, 2013/08/07
- Re: [Qemu-ppc] [PATCH 5/6] xics: split to xics and xics-common, Andreas Färber, 2013/08/08
[Qemu-ppc] [PATCH 6/6] xics-kvm: Support for in-kernel XICS interrupt controller, Alexey Kardashevskiy, 2013/08/06