Skip to content

Commit

Permalink
openpic: convert to vmstate
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
mcayland authored and agraf committed Mar 9, 2015
1 parent 2ada66f commit e5f6e73
Showing 1 changed file with 119 additions and 134 deletions.
253 changes: 119 additions & 134 deletions hw/intc/openpic.c
Expand Up @@ -207,6 +207,7 @@ typedef enum IRQType {

typedef struct IRQQueue {
unsigned long *queue;
int32_t queue_size; /* Only used for VMSTATE_BITMAP */
int next;
int priority;
} IRQQueue;
Expand Down Expand Up @@ -242,6 +243,15 @@ typedef struct IRQSource {
#define IDR_EP 0x80000000 /* external pin */
#define IDR_CI 0x40000000 /* critical interrupt */

typedef struct OpenPICTimer {
uint32_t tccr; /* Global timer current count register */
uint32_t tbcr; /* Global timer base count register */
} OpenPICTimer;

typedef struct OpenPICMSI {
uint32_t msir; /* Shared Message Signaled Interrupt Register */
} OpenPICMSI;

typedef struct IRQDest {
int32_t ctpr; /* CPU current task priority */
IRQQueue raised;
Expand Down Expand Up @@ -290,14 +300,9 @@ typedef struct OpenPICState {
IRQDest dst[MAX_CPU];
uint32_t nb_cpus;
/* Timer registers */
struct {
uint32_t tccr; /* Global timer current count register */
uint32_t tbcr; /* Global timer base count register */
} timers[OPENPIC_MAX_TMR];
OpenPICTimer timers[OPENPIC_MAX_TMR];
/* Shared MSI registers */
struct {
uint32_t msir; /* Shared Message Signaled Interrupt Register */
} msi[MAX_MSI];
OpenPICMSI msi[MAX_MSI];
uint32_t max_irq;
uint32_t irq_ipi0;
uint32_t irq_tim0;
Expand Down Expand Up @@ -1289,130 +1294,6 @@ static const MemoryRegionOps openpic_summary_ops_be = {
},
};

static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
{
unsigned int i;

for (i = 0; i < BITS_TO_LONGS(IRQQUEUE_SIZE_BITS); i++) {
/* Always put the lower half of a 64-bit long first, in case we
* restore on a 32-bit host. The least significant bits correspond
* to lower IRQ numbers in the bitmap.
*/
qemu_put_be32(f, (uint32_t)q->queue[i]);
#if LONG_MAX > 0x7FFFFFFF
qemu_put_be32(f, (uint32_t)(q->queue[i] >> 32));
#endif
}

qemu_put_sbe32s(f, &q->next);
qemu_put_sbe32s(f, &q->priority);
}

static void openpic_save(QEMUFile* f, void *opaque)
{
OpenPICState *opp = (OpenPICState *)opaque;
unsigned int i;

qemu_put_be32s(f, &opp->gcr);
qemu_put_be32s(f, &opp->vir);
qemu_put_be32s(f, &opp->pir);
qemu_put_be32s(f, &opp->spve);
qemu_put_be32s(f, &opp->tfrr);

qemu_put_be32s(f, &opp->nb_cpus);

for (i = 0; i < opp->nb_cpus; i++) {
qemu_put_sbe32s(f, &opp->dst[i].ctpr);
openpic_save_IRQ_queue(f, &opp->dst[i].raised);
openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
qemu_put_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
sizeof(opp->dst[i].outputs_active));
}

for (i = 0; i < OPENPIC_MAX_TMR; i++) {
qemu_put_be32s(f, &opp->timers[i].tccr);
qemu_put_be32s(f, &opp->timers[i].tbcr);
}

for (i = 0; i < opp->max_irq; i++) {
qemu_put_be32s(f, &opp->src[i].ivpr);
qemu_put_be32s(f, &opp->src[i].idr);
qemu_put_be32s(f, &opp->src[i].destmask);
qemu_put_sbe32s(f, &opp->src[i].last_cpu);
qemu_put_sbe32s(f, &opp->src[i].pending);
}
}

static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
{
unsigned int i;

for (i = 0; i < BITS_TO_LONGS(IRQQUEUE_SIZE_BITS); i++) {
unsigned long val;

val = qemu_get_be32(f);
#if LONG_MAX > 0x7FFFFFFF
val <<= 32;
val |= qemu_get_be32(f);
#endif

q->queue[i] = val;
}

qemu_get_sbe32s(f, &q->next);
qemu_get_sbe32s(f, &q->priority);
}

static int openpic_load(QEMUFile* f, void *opaque, int version_id)
{
OpenPICState *opp = (OpenPICState *)opaque;
unsigned int i, nb_cpus;

if (version_id != 2) {
return -EINVAL;
}

qemu_get_be32s(f, &opp->gcr);
qemu_get_be32s(f, &opp->vir);
qemu_get_be32s(f, &opp->pir);
qemu_get_be32s(f, &opp->spve);
qemu_get_be32s(f, &opp->tfrr);

qemu_get_be32s(f, &nb_cpus);
if (opp->nb_cpus != nb_cpus) {
return -EINVAL;
}
assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);

for (i = 0; i < opp->nb_cpus; i++) {
qemu_get_sbe32s(f, &opp->dst[i].ctpr);
openpic_load_IRQ_queue(f, &opp->dst[i].raised);
openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
qemu_get_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
sizeof(opp->dst[i].outputs_active));
}

for (i = 0; i < OPENPIC_MAX_TMR; i++) {
qemu_get_be32s(f, &opp->timers[i].tccr);
qemu_get_be32s(f, &opp->timers[i].tbcr);
}

for (i = 0; i < opp->max_irq; i++) {
uint32_t val;

val = qemu_get_be32(f);
write_IRQreg_ivpr(opp, i, val);
val = qemu_get_be32(f);
write_IRQreg_idr(opp, i, val);

qemu_get_be32s(f, &opp->src[i].destmask);
qemu_get_sbe32s(f, &opp->src[i].last_cpu);
qemu_get_sbe32s(f, &opp->src[i].pending);
}

return 0;
}

static void openpic_reset(DeviceState *d)
{
OpenPICState *opp = OPENPIC(d);
Expand Down Expand Up @@ -1527,6 +1408,110 @@ static void map_list(OpenPICState *opp, const MemReg *list, int *count)
}
}

static const VMStateDescription vmstate_openpic_irq_queue = {
.name = "openpic_irq_queue",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size),
VMSTATE_INT32(next, IRQQueue),
VMSTATE_INT32(priority, IRQQueue),
VMSTATE_END_OF_LIST()
}
};

static const VMStateDescription vmstate_openpic_irqdest = {
.name = "openpic_irqdest",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_INT32(ctpr, IRQDest),
VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue,
IRQQueue),
VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue,
IRQQueue),
VMSTATE_UINT32_ARRAY(outputs_active, IRQDest, OPENPIC_OUTPUT_NB),
VMSTATE_END_OF_LIST()
}
};

static const VMStateDescription vmstate_openpic_irqsource = {
.name = "openpic_irqsource",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(ivpr, IRQSource),
VMSTATE_UINT32(idr, IRQSource),
VMSTATE_UINT32(destmask, IRQSource),
VMSTATE_INT32(last_cpu, IRQSource),
VMSTATE_INT32(pending, IRQSource),
VMSTATE_END_OF_LIST()
}
};

static const VMStateDescription vmstate_openpic_timer = {
.name = "openpic_timer",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(tccr, OpenPICTimer),
VMSTATE_UINT32(tbcr, OpenPICTimer),
VMSTATE_END_OF_LIST()
}
};

static const VMStateDescription vmstate_openpic_msi = {
.name = "openpic_msi",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(msir, OpenPICMSI),
VMSTATE_END_OF_LIST()
}
};

static int openpic_post_load(void *opaque, int version_id)
{
OpenPICState *opp = (OpenPICState *)opaque;
int i;

/* Update internal ivpr and idr variables */
for (i = 0; i < opp->max_irq; i++) {
write_IRQreg_idr(opp, i, opp->src[i].idr);
write_IRQreg_ivpr(opp, i, opp->src[i].ivpr);
}

return 0;
}

static const VMStateDescription vmstate_openpic = {
.name = "openpic",
.version_id = 3,
.minimum_version_id = 3,
.post_load = openpic_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(gcr, OpenPICState),
VMSTATE_UINT32(vir, OpenPICState),
VMSTATE_UINT32(pir, OpenPICState),
VMSTATE_UINT32(spve, OpenPICState),
VMSTATE_UINT32(tfrr, OpenPICState),
VMSTATE_UINT32(max_irq, OpenPICState),
VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0,
vmstate_openpic_irqsource, IRQSource),
VMSTATE_UINT32_EQUAL(nb_cpus, OpenPICState),
VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0,
vmstate_openpic_irqdest, IRQDest),
VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0,
vmstate_openpic_timer, OpenPICTimer),
VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0,
vmstate_openpic_msi, OpenPICMSI),
VMSTATE_UINT32(irq_ipi0, OpenPICState),
VMSTATE_UINT32(irq_tim0, OpenPICState),
VMSTATE_UINT32(irq_msi, OpenPICState),
VMSTATE_END_OF_LIST()
}
};

static void openpic_init(Object *obj)
{
OpenPICState *opp = OPENPIC(obj);
Expand Down Expand Up @@ -1634,13 +1619,12 @@ static void openpic_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(d, &opp->dst[i].irqs[j]);
}

opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS;
opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS;
opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
}

register_savevm(dev, "openpic", 0, 2,
openpic_save, openpic_load, opp);

sysbus_init_mmio(d, &opp->mem);
qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq);
}
Expand All @@ -1658,6 +1642,7 @@ static void openpic_class_init(ObjectClass *oc, void *data)
dc->realize = openpic_realize;
dc->props = openpic_properties;
dc->reset = openpic_reset;
dc->vmsd = &vmstate_openpic;
}

static const TypeInfo openpic_info = {
Expand Down

0 comments on commit e5f6e73

Please sign in to comment.