[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 37/77] ppc/xics: Split ICS into base class and "simple
From: |
Benjamin Herrenschmidt |
Subject: |
[Qemu-ppc] [PATCH 37/77] ppc/xics: Split ICS into base class and "simple" implementation |
Date: |
Wed, 11 Nov 2015 11:27:50 +1100 |
The existing implementation becomes the "ics-simple" subclass of ICS,
so there should be no change in behaviour for SPAPR.
This will allow different implementations for the source controllers
such as the MSI support of PHB3 on Power8 which uses in-memory state
tables for example.
Signed-off-by: Benjamin Herrenschmidt <address@hidden>
---
hw/intc/xics.c | 123 ++++++++++++++++++++++++++++++++------------------
hw/intc/xics_kvm.c | 2 +-
hw/intc/xics_spapr.c | 34 ++++++++------
include/hw/ppc/xics.h | 12 +++--
4 files changed, 108 insertions(+), 63 deletions(-)
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 3cd696f..4b33e6d 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -198,9 +198,32 @@ static const TypeInfo xics_common_info = {
#define XISR(ss) (((ss)->xirr) & XISR_MASK)
#define CPPR(ss) (((ss)->xirr) >> 24)
-static void ics_reject(ICSState *ics, int nr);
-static void ics_resend(ICSState *ics);
-static void ics_eoi(ICSState *ics, int nr);
+static void ics_reject(ICSState *ics, uint32_t nr)
+{
+ ICSStateClass *k = ICS_GET_CLASS(ics);
+
+ if (k->reject) {
+ k->reject(ics, nr);
+ }
+}
+
+static void ics_resend(ICSState *ics)
+{
+ ICSStateClass *k = ICS_GET_CLASS(ics);
+
+ if (k->resend) {
+ k->resend(ics);
+ }
+}
+
+static void ics_eoi(ICSState *ics, int nr)
+{
+ ICSStateClass *k = ICS_GET_CLASS(ics);
+
+ if (k->eoi) {
+ k->eoi(ics, nr);
+ }
+}
static void icp_check_ipi(ICPState *ss, int server)
{
@@ -403,7 +426,7 @@ static const TypeInfo icp_info = {
/*
* ICS: Source layer
*/
-static void resend_msi(ICSState *ics, int srcno)
+static void ics_simple_resend_msi(ICSState *ics, int srcno)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -416,7 +439,7 @@ static void resend_msi(ICSState *ics, int srcno)
}
}
-static void resend_lsi(ICSState *ics, int srcno)
+static void ics_simple_resend_lsi(ICSState *ics, int srcno)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -428,7 +451,7 @@ static void resend_lsi(ICSState *ics, int srcno)
}
}
-static void set_irq_msi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -444,7 +467,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
}
}
-static void set_irq_lsi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -454,21 +477,21 @@ static void set_irq_lsi(ICSState *ics, int srcno, int val)
} else {
irq->status &= ~XICS_STATUS_ASSERTED;
}
- resend_lsi(ics, srcno);
+ ics_simple_resend_lsi(ics, srcno);
}
-static void ics_set_irq(void *opaque, int srcno, int val)
+static void ics_simple_set_irq(void *opaque, int srcno, int val)
{
ICSState *ics = (ICSState *)opaque;
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
- set_irq_lsi(ics, srcno, val);
+ ics_simple_set_irq_lsi(ics, srcno, val);
} else {
- set_irq_msi(ics, srcno, val);
+ ics_simple_set_irq_msi(ics, srcno, val);
}
}
-static void write_xive_msi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -481,31 +504,30 @@ static void write_xive_msi(ICSState *ics, int srcno)
icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
}
-static void write_xive_lsi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
{
- resend_lsi(ics, srcno);
+ ics_simple_resend_lsi(ics, srcno);
}
-void ics_write_xive(ICSState *ics, int nr, int server,
- uint8_t priority, uint8_t saved_priority)
+void ics_simple_write_xive(ICSState *ics, int srcno, int server,
+ uint8_t priority, uint8_t saved_priority)
{
- int srcno = nr - ics->offset;
ICSIRQState *irq = ics->irqs + srcno;
irq->server = server;
irq->priority = priority;
irq->saved_priority = saved_priority;
- trace_xics_ics_write_xive(nr, srcno, server, priority);
+ trace_xics_ics_write_xive(ics->offset + srcno, srcno, server, priority);
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
- write_xive_lsi(ics, srcno);
+ ics_simple_write_xive_lsi(ics, srcno);
} else {
- write_xive_msi(ics, srcno);
+ ics_simple_write_xive_msi(ics, srcno);
}
}
-static void ics_reject(ICSState *ics, int nr)
+static void ics_simple_reject(ICSState *ics, uint32_t nr)
{
ICSIRQState *irq = ics->irqs + nr - ics->offset;
@@ -514,21 +536,21 @@ static void ics_reject(ICSState *ics, int nr)
irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
}
-static void ics_resend(ICSState *ics)
+static void ics_simple_resend(ICSState *ics)
{
int i;
for (i = 0; i < ics->nr_irqs; i++) {
/* FIXME: filter by server#? */
if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
- resend_lsi(ics, i);
+ ics_simple_resend_lsi(ics, i);
} else {
- resend_msi(ics, i);
+ ics_simple_resend_msi(ics, i);
}
}
}
-static void ics_eoi(ICSState *ics, int nr)
+static void ics_simple_eoi(ICSState *ics, uint32_t nr)
{
int srcno = nr - ics->offset;
ICSIRQState *irq = ics->irqs + srcno;
@@ -540,9 +562,9 @@ static void ics_eoi(ICSState *ics, int nr)
}
}
-static void ics_reset(DeviceState *dev)
+static void ics_simple_reset(DeviceState *dev)
{
- ICSState *ics = ICS(dev);
+ ICSState *ics = ICS_SIMPLE(dev);
int i;
uint8_t flags[ics->nr_irqs];
@@ -559,7 +581,7 @@ static void ics_reset(DeviceState *dev)
}
}
-static int ics_post_load(ICSState *ics, int version_id)
+static int ics_simple_post_load(ICSState *ics, int version_id)
{
int i;
@@ -592,7 +614,7 @@ static int ics_dispatch_post_load(void *opaque, int
version_id)
return 0;
}
-static const VMStateDescription vmstate_ics_irq = {
+static const VMStateDescription vmstate_ics_simple_irq = {
.name = "ics/irq",
.version_id = 2,
.minimum_version_id = 1,
@@ -606,7 +628,7 @@ static const VMStateDescription vmstate_ics_irq = {
},
};
-static const VMStateDescription vmstate_ics = {
+static const VMStateDescription vmstate_ics_simple = {
.name = "ics",
.version_id = 1,
.minimum_version_id = 1,
@@ -617,48 +639,60 @@ static const VMStateDescription vmstate_ics = {
VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
- vmstate_ics_irq, ICSIRQState),
+ vmstate_ics_simple_irq,
+ ICSIRQState),
VMSTATE_END_OF_LIST()
},
};
-static void ics_initfn(Object *obj)
+static void ics_simple_initfn(Object *obj)
{
- ICSState *ics = ICS(obj);
+ ICSState *ics = ICS_SIMPLE(obj);
ics->offset = XICS_IRQ_BASE;
}
-static void ics_realize(DeviceState *dev, Error **errp)
+static void ics_simple_realize(DeviceState *dev, Error **errp)
{
- ICSState *ics = ICS(dev);
+ ICSState *ics = ICS_SIMPLE(dev);
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_set_irq, ics, ics->nr_irqs);
+ ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
}
-static void ics_class_init(ObjectClass *klass, void *data)
+static void ics_simple_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ICSStateClass *isc = ICS_CLASS(klass);
- dc->realize = ics_realize;
- dc->vmsd = &vmstate_ics;
- dc->reset = ics_reset;
- isc->post_load = ics_post_load;
+ dc->realize = ics_simple_realize;
+ dc->vmsd = &vmstate_ics_simple;
+ dc->reset = ics_simple_reset;
+ isc->post_load = ics_simple_post_load;
+ 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,
+ .instance_size = sizeof(ICSState),
+ .class_init = ics_simple_class_init,
+ .class_size = sizeof(ICSStateClass),
+ .instance_init = ics_simple_initfn,
+};
+
static const TypeInfo ics_info = {
.name = TYPE_ICS,
.parent = TYPE_DEVICE,
+ .abstract = true,
.instance_size = sizeof(ICSState),
- .class_init = ics_class_init,
.class_size = sizeof(ICSStateClass),
- .instance_init = ics_initfn,
};
/*
@@ -687,7 +721,7 @@ qemu_irq xics_get_qirq(XICSState *xics, int irq)
return NULL;
}
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
+void ics_simple_set_irq_type(ICSState *ics, int srcno, bool lsi)
{
assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
@@ -718,6 +752,7 @@ void xics_set_nr_servers(XICSState *xics, uint32_t
nr_servers, Error **errp)
static void xics_register_types(void)
{
type_register_static(&xics_common_info);
+ type_register_static(&ics_simple_info);
type_register_static(&ics_info);
type_register_static(&icp_info);
}
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 6fbc715..aeae68a 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -309,7 +309,7 @@ static void ics_kvm_class_init(ObjectClass *klass, void
*data)
static const TypeInfo ics_kvm_info = {
.name = TYPE_KVM_ICS,
- .parent = TYPE_ICS,
+ .parent = TYPE_ICS_SIMPLE,
.instance_size = sizeof(ICSState),
.class_init = ics_kvm_class_init,
};
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index fc331d8..f7d444a 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -112,7 +112,7 @@ static void rtas_set_xive(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t nret, target_ulong rets)
{
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
- uint32_t nr, server, priority;
+ uint32_t nr, src_no, server, priority;
if ((nargs != 3) || (nret != 1) || !ics) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -129,7 +129,8 @@ static void rtas_set_xive(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
return;
}
- ics_write_xive(ics, nr, server, priority, priority);
+ src_no = nr - ics->offset;
+ ics_simple_write_xive(ics, src_no, server, priority, priority);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
@@ -140,7 +141,7 @@ static void rtas_get_xive(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t nret, target_ulong rets)
{
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
- uint32_t nr;
+ uint32_t nr, src_no;
if ((nargs != 1) || (nret != 3) || !ics) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -155,8 +156,9 @@ static void rtas_get_xive(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
}
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
- rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+ src_no = nr - ics->offset;
+ rtas_st(rets, 1, ics->irqs[src_no].server);
+ rtas_st(rets, 2, ics->irqs[src_no].priority);
}
static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
@@ -165,7 +167,7 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState
*spapr,
uint32_t nret, target_ulong rets)
{
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
- uint32_t nr;
+ uint32_t nr, src_no;
if ((nargs != 1) || (nret != 1) || !ics) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -179,8 +181,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState
*spapr,
return;
}
- ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
- ics->irqs[nr - ics->offset].priority);
+ src_no = nr - ics->offset;
+ ics_simple_write_xive(ics, src_no, ics->irqs[src_no].server, 0xff,
+ ics->irqs[src_no].priority);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
@@ -191,7 +194,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState
*spapr,
uint32_t nret, target_ulong rets)
{
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
- uint32_t nr;
+ uint32_t nr, src_no;
if ((nargs != 1) || (nret != 1) || !ics) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -205,9 +208,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState
*spapr,
return;
}
- ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
- ics->irqs[nr - ics->offset].saved_priority,
- ics->irqs[nr - ics->offset].saved_priority);
+ src_no = nr - ics->offset;
+ ics_simple_write_xive(ics, src_no, ics->irqs[src_no].server,
+ ics->irqs[src_no].saved_priority,
+ ics->irqs[src_no].saved_priority);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
@@ -261,7 +265,7 @@ static void xics_spapr_initfn(Object *obj)
QLIST_INIT(&xics->ics);
- ics = ICS(object_new(TYPE_ICS));
+ ics = ICS(object_new(TYPE_ICS_SIMPLE));
object_property_add_child(obj, "ics", OBJECT(ics), NULL);
xics_add_ics(xics, ics);
}
@@ -343,7 +347,7 @@ int xics_spapr_alloc(XICSState *xics, int irq_hint, bool
lsi)
irq += ics->offset;
}
- ics_set_irq_type(ics, irq - ics->offset, lsi);
+ ics_simple_set_irq_type(ics, irq - ics->offset, lsi);
trace_xics_alloc(0, irq);
return irq;
@@ -379,7 +383,7 @@ int xics_spapr_alloc_block(XICSState *xics, int num, bool
lsi, bool align)
if (first >= 0) {
for (i = first; i < first + num; ++i) {
- ics_set_irq_type(ics, i, lsi);
+ ics_simple_set_irq_type(ics, i, lsi);
}
}
first += ics->offset;
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 5acb329..93a627b 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -116,6 +116,9 @@ struct ICPState {
#define TYPE_ICS "ics"
#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
+#define TYPE_ICS_SIMPLE "ics-simple"
+#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
+
#define TYPE_KVM_ICS "icskvm"
#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
@@ -129,6 +132,9 @@ struct ICSStateClass {
void (*pre_save)(ICSState *s);
int (*post_load)(ICSState *s, int version_id);
+ void (*reject)(ICSState *s, uint32_t irq);
+ void (*resend)(ICSState *s);
+ void (*eoi)(ICSState *s, uint32_t irq);
};
struct ICSState {
@@ -184,10 +190,10 @@ uint32_t icp_accept(ICPState *ss);
uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
void icp_eoi(XICSState *icp, int server, uint32_t xirr);
-void ics_write_xive(ICSState *ics, int nr, int server,
- uint8_t priority, uint8_t saved_priority);
+void ics_simple_write_xive(ICSState *ics, int nr, int server,
+ uint8_t priority, uint8_t saved_priority);
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
+void ics_simple_set_irq_type(ICSState *ics, int srcno, bool lsi);
void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers, Error **errp);
ICSState *xics_find_source(XICSState *icp, int irq);
--
2.5.0
- Re: [Qemu-ppc] [Qemu-devel] [PATCH 00/77] ppc: Add "native" POWER8 platform, (continued)
- Re: [Qemu-ppc] [PATCH 00/77] ppc: Add "native" POWER8 platform, Stewart Smith, 2015/11/10
- [Qemu-ppc] [PATCH 10/77] ppc: Fix hreg_store_msr() so that non-HV mode cannot alter MSR:HV, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 15/77] ppc: Fix sign extension issue in mtmsr(d) emulation, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 22/77] ppc: Add real mode CI load/store instructions for P7 and P8, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 37/77] ppc/xics: Split ICS into base class and "simple" implementation,
Benjamin Herrenschmidt <=
- [Qemu-ppc] [PATCH 24/77] ppc: Move exception generation code out of line, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 16/77] ppc: Get out of emulation on SMT "OR" ops, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 48/77] ppc/pnv: Add model for Power8 PHB3 PCIe Host bridge, Benjamin Herrenschmidt, 2015/11/10