diff mbox

[05/17] pseries: savevm support for XICS interrupt controller

Message ID 1372315560-5478-6-git-send-email-aik@ozlabs.ru
State New
Headers show

Commit Message

Alexey Kardashevskiy June 27, 2013, 6:45 a.m. UTC
From: David Gibson <david@gibson.dropbear.id.au>

This patch adds the necessary VMStateDescription information to support
savevm/loadvm for the XICS interrupt controller used on the pseries
machine.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[aik: added ics_resend() on post_load]
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/intc/xics.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

Comments

Anthony Liguori July 8, 2013, 6:31 p.m. UTC | #1
Alexey Kardashevskiy <aik@ozlabs.ru> writes:

> From: David Gibson <david@gibson.dropbear.id.au>
>
> This patch adds the necessary VMStateDescription information to support
> savevm/loadvm for the XICS interrupt controller used on the pseries
> machine.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> [aik: added ics_resend() on post_load]
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
>  hw/intc/xics.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
>
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 0e374c8..3e8f48f 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -497,6 +497,61 @@ static void xics_reset(DeviceState *d)
>      xics_common_reset(XICS(d));
>  }
>  
> +static int ics_post_load(void *opaque, int version_id)
> +{
> +    int i;
> +    struct ics_state *ics = opaque;
> +
> +    for (i = 0; i < ics->icp->nr_servers; i++) {
> +        icp_resend(ics->icp, i);
> +    }
> +
> +    return 0;
> +}
> +
> +const VMStateDescription vmstate_icp_server = {
> +    .name = "icp/server",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField []) {
> +        /* Sanity check */
> +        VMSTATE_UINT32(xirr, struct icp_server_state),
> +        VMSTATE_UINT8(pending_priority, struct icp_server_state),
> +        VMSTATE_UINT8(mfrr, struct icp_server_state),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +static const VMStateDescription vmstate_ics_irq = {
> +    .name = "ics/irq",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField []) {
> +        VMSTATE_UINT32(server, struct ics_irq_state),
> +        VMSTATE_UINT8(priority, struct ics_irq_state),
> +        VMSTATE_UINT8(saved_priority, struct ics_irq_state),
> +        VMSTATE_UINT8(status, struct ics_irq_state),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +const VMStateDescription vmstate_ics = {
> +    .name = "ics",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .post_load = ics_post_load,
> +    .fields      = (VMStateField []) {
> +        /* Sanity check */
> +        VMSTATE_UINT32_EQUAL(nr_irqs, struct ics_state),
> +
> +        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, struct ics_state, nr_irqs, vmstate_ics_irq, struct ics_irq_state),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
>  void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>  {
>      CPUState *cs = CPU(cpu);
> @@ -523,7 +578,11 @@ void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>  
>  void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>  {
> +    CPUState *cs = CPU(cpu);
> +    struct icp_server_state *ss = &icp->ss[cs->cpu_index];
> +
>      xics_common_cpu_setup(icp, cpu);
> +    vmstate_register(NULL, cs->cpu_index, &vmstate_icp_server, ss);

This is an indication that something is wrong.

You should tie the vmstate section to DeviceState::vmsd.  You only need
to do this because you haven't converted everything to QOM yet.

Please do that to avoid these hacks.

Regards,

Anthony Liguori

>  }
>  
>  void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
> @@ -555,6 +614,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
>      spapr_rtas_register("ibm,int-off", rtas_int_off);
>      spapr_rtas_register("ibm,int-on", rtas_int_on);
>  
> +    /* We use each the ICS's offset into the global irq number space
> +     * as an instance id.  This means we can extend to multiple ICS
> +     * instances without needing to change the savevm format */
> +    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
>  }
>  
>  static Property xics_properties[] = {
> -- 
> 1.7.10.4
Alexey Kardashevskiy July 9, 2013, 12:06 a.m. UTC | #2
On 07/09/2013 04:31 AM, Anthony Liguori wrote:
> Alexey Kardashevskiy <aik@ozlabs.ru> writes:
> 
>> From: David Gibson <david@gibson.dropbear.id.au>
>>
>> This patch adds the necessary VMStateDescription information to support
>> savevm/loadvm for the XICS interrupt controller used on the pseries
>> machine.
>>
>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>> [aik: added ics_resend() on post_load]
>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>> ---
>>  hw/intc/xics.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 63 insertions(+)
>>
>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>> index 0e374c8..3e8f48f 100644
>> --- a/hw/intc/xics.c
>> +++ b/hw/intc/xics.c
>> @@ -497,6 +497,61 @@ static void xics_reset(DeviceState *d)
>>      xics_common_reset(XICS(d));
>>  }
>>  
>> +static int ics_post_load(void *opaque, int version_id)
>> +{
>> +    int i;
>> +    struct ics_state *ics = opaque;
>> +
>> +    for (i = 0; i < ics->icp->nr_servers; i++) {
>> +        icp_resend(ics->icp, i);
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +const VMStateDescription vmstate_icp_server = {
>> +    .name = "icp/server",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .fields      = (VMStateField []) {
>> +        /* Sanity check */
>> +        VMSTATE_UINT32(xirr, struct icp_server_state),
>> +        VMSTATE_UINT8(pending_priority, struct icp_server_state),
>> +        VMSTATE_UINT8(mfrr, struct icp_server_state),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
>> +
>> +static const VMStateDescription vmstate_ics_irq = {
>> +    .name = "ics/irq",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .fields      = (VMStateField []) {
>> +        VMSTATE_UINT32(server, struct ics_irq_state),
>> +        VMSTATE_UINT8(priority, struct ics_irq_state),
>> +        VMSTATE_UINT8(saved_priority, struct ics_irq_state),
>> +        VMSTATE_UINT8(status, struct ics_irq_state),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
>> +
>> +const VMStateDescription vmstate_ics = {
>> +    .name = "ics",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .post_load = ics_post_load,
>> +    .fields      = (VMStateField []) {
>> +        /* Sanity check */
>> +        VMSTATE_UINT32_EQUAL(nr_irqs, struct ics_state),
>> +
>> +        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, struct ics_state, nr_irqs, vmstate_ics_irq, struct ics_irq_state),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
>> +
>>  void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>>  {
>>      CPUState *cs = CPU(cpu);
>> @@ -523,7 +578,11 @@ void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>>  
>>  void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
>>  {
>> +    CPUState *cs = CPU(cpu);
>> +    struct icp_server_state *ss = &icp->ss[cs->cpu_index];
>> +
>>      xics_common_cpu_setup(icp, cpu);
>> +    vmstate_register(NULL, cs->cpu_index, &vmstate_icp_server, ss);
> 
> This is an indication that something is wrong.
> 
> You should tie the vmstate section to DeviceState::vmsd.  You only need
> to do this because you haven't converted everything to QOM yet.
> 
> Please do that to avoid these hacks.


How? I want to support migration from xics to xics-kvm and vice versa.
vmsd cannot be inherited and even if they could, different device names
would kill that support.


> 
> Regards,
> 
> Anthony Liguori
> 
>>  }
>>  
>>  void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
>> @@ -555,6 +614,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
>>      spapr_rtas_register("ibm,int-off", rtas_int_off);
>>      spapr_rtas_register("ibm,int-on", rtas_int_on);
>>  
>> +    /* We use each the ICS's offset into the global irq number space
>> +     * as an instance id.  This means we can extend to multiple ICS
>> +     * instances without needing to change the savevm format */
>> +    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
>>  }
>>  
>>  static Property xics_properties[] = {
>> -- 
>> 1.7.10.4
>
Anthony Liguori July 9, 2013, 12:49 a.m. UTC | #3
On Mon, Jul 8, 2013 at 7:06 PM, Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
>> You should tie the vmstate section to DeviceState::vmsd.  You only need
>> to do this because you haven't converted everything to QOM yet.
>>
>> Please do that to avoid these hacks.
>
>
> How? I want to support migration from xics to xics-kvm and vice versa.
> vmsd cannot be inherited and even if they could, different device names
> would kill that support.

Please look at hw/intc/i8259_common.c and then hw/i386/kvm/i8259.c and
hw/i386/intc/i8259.c.

The vmsd is in the common base class shared between the KVM version
and the non-KVM version.  As long as the subclasses don't introduce
any new state members, you can safely migrate between the two devices.

You should consider splitting the implementations up into separate
files just like i8259 too.

Regards,

Anthony Liguori

>
>
>>
>> Regards,
>>
>> Anthony Liguori
>>
>>>  }
>>>
>>>  void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
>>> @@ -555,6 +614,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
>>>      spapr_rtas_register("ibm,int-off", rtas_int_off);
>>>      spapr_rtas_register("ibm,int-on", rtas_int_on);
>>>
>>> +    /* We use each the ICS's offset into the global irq number space
>>> +     * as an instance id.  This means we can extend to multiple ICS
>>> +     * instances without needing to change the savevm format */
>>> +    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
>>>  }
>>>
>>>  static Property xics_properties[] = {
>>> --
>>> 1.7.10.4
>>
>
>
> --
> Alexey
>
Alexey Kardashevskiy July 9, 2013, 12:59 a.m. UTC | #4
On 07/09/2013 10:49 AM, Anthony Liguori wrote:
> On Mon, Jul 8, 2013 at 7:06 PM, Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
>>> You should tie the vmstate section to DeviceState::vmsd.  You only need
>>> to do this because you haven't converted everything to QOM yet.
>>>
>>> Please do that to avoid these hacks.
>>
>>
>> How? I want to support migration from xics to xics-kvm and vice versa.
>> vmsd cannot be inherited and even if they could, different device names
>> would kill that support.
> 
> Please look at hw/intc/i8259_common.c and then hw/i386/kvm/i8259.c and
> hw/i386/intc/i8259.c.
> 
> The vmsd is in the common base class shared between the KVM version
> and the non-KVM version.  As long as the subclasses don't introduce
> any new state members, you can safely migrate between the two devices.

Ok, thanks.

> You should consider splitting the implementations up into separate
> files just like i8259 too.


I  already split it to xics and xics-kvm devices so you are are definitely
talking about something else but I do not understand what exactly...



> Regards,
> 
> Anthony Liguori
> 
>>
>>
>>>
>>> Regards,
>>>
>>> Anthony Liguori
>>>
>>>>  }
>>>>
>>>>  void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
>>>> @@ -555,6 +614,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
>>>>      spapr_rtas_register("ibm,int-off", rtas_int_off);
>>>>      spapr_rtas_register("ibm,int-on", rtas_int_on);
>>>>
>>>> +    /* We use each the ICS's offset into the global irq number space
>>>> +     * as an instance id.  This means we can extend to multiple ICS
>>>> +     * instances without needing to change the savevm format */
>>>> +    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
>>>>  }
>>>>
>>>>  static Property xics_properties[] = {
>>>> --
>>>> 1.7.10.4
>>>
>>
>>
>> --
>> Alexey
>>
Anthony Liguori July 9, 2013, 1:25 a.m. UTC | #5
Alexey Kardashevskiy <aik@ozlabs.ru> writes:

> On 07/09/2013 10:49 AM, Anthony Liguori wrote:
>> On Mon, Jul 8, 2013 at 7:06 PM, Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
>>>> You should tie the vmstate section to DeviceState::vmsd.  You only need
>>>> to do this because you haven't converted everything to QOM yet.
>>>>
>>>> Please do that to avoid these hacks.
>>>
>>>
>>> How? I want to support migration from xics to xics-kvm and vice versa.
>>> vmsd cannot be inherited and even if they could, different device names
>>> would kill that support.
>> 
>> Please look at hw/intc/i8259_common.c and then hw/i386/kvm/i8259.c and
>> hw/i386/intc/i8259.c.
>> 
>> The vmsd is in the common base class shared between the KVM version
>> and the non-KVM version.  As long as the subclasses don't introduce
>> any new state members, you can safely migrate between the two devices.
>
> Ok, thanks.
>
>> You should consider splitting the implementations up into separate
>> files just like i8259 too.
>
>
> I  already split it to xics and xics-kvm devices so you are are definitely
> talking about something else but I do not understand what exactly...

There are three classes for the i8259 split between three files.  I was
suggesting factoring out a base class and putting that in a separate
file.

Regards,

Anthony Liguori

>
>
>
>> Regards,
>> 
>> Anthony Liguori
>> 
>>>
>>>
>>>>
>>>> Regards,
>>>>
>>>> Anthony Liguori
>>>>
>>>>>  }
>>>>>
>>>>>  void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
>>>>> @@ -555,6 +614,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
>>>>>      spapr_rtas_register("ibm,int-off", rtas_int_off);
>>>>>      spapr_rtas_register("ibm,int-on", rtas_int_on);
>>>>>
>>>>> +    /* We use each the ICS's offset into the global irq number space
>>>>> +     * as an instance id.  This means we can extend to multiple ICS
>>>>> +     * instances without needing to change the savevm format */
>>>>> +    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
>>>>>  }
>>>>>
>>>>>  static Property xics_properties[] = {
>>>>> --
>>>>> 1.7.10.4
>>>>
>>>
>>>
>>> --
>>> Alexey
>>>
>
>
> -- 
> Alexey
Alexey Kardashevskiy July 9, 2013, 3:37 a.m. UTC | #6
On 07/09/2013 10:49 AM, Anthony Liguori wrote:
> On Mon, Jul 8, 2013 at 7:06 PM, Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
>>> You should tie the vmstate section to DeviceState::vmsd.  You only need
>>> to do this because you haven't converted everything to QOM yet.
>>>
>>> Please do that to avoid these hacks.
>>
>>
>> How? I want to support migration from xics to xics-kvm and vice versa.
>> vmsd cannot be inherited and even if they could, different device names
>> would kill that support.
> 
> Please look at hw/intc/i8259_common.c and then hw/i386/kvm/i8259.c and
> hw/i386/intc/i8259.c.

btw do I have to put xics_kvm.c to hw/ppc64/kvm (which does not exist yet)
or to hw/intc? What is the system here? I am really confused.

> The vmsd is in the common base class shared between the KVM version
> and the non-KVM version.  As long as the subclasses don't introduce
> any new state members, you can safely migrate between the two devices.


btw xics-kvm does not introduce new members but does have very different
.pre_save and .post_load. This actually was the whole point of splitting
xics into xics and xics-kvm. I cannot see how I can fix it without hacks.
Property's can be inherited from a parent class (?) but VMStateDescription
cannot.


> You should consider splitting the implementations up into separate
> files just like i8259 too.
David Gibson July 9, 2013, 7:17 a.m. UTC | #7
On Mon, Jul 08, 2013 at 01:31:59PM -0500, Anthony Liguori wrote:
> Alexey Kardashevskiy <aik@ozlabs.ru> writes:
> > From: David Gibson <david@gibson.dropbear.id.au>
[snip]
> >  void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
> >  {
> >      CPUState *cs = CPU(cpu);
> > @@ -523,7 +578,11 @@ void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
> >  
> >  void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
> >  {
> > +    CPUState *cs = CPU(cpu);
> > +    struct icp_server_state *ss = &icp->ss[cs->cpu_index];
> > +
> >      xics_common_cpu_setup(icp, cpu);
> > +    vmstate_register(NULL, cs->cpu_index, &vmstate_icp_server, ss);
> 
> This is an indication that something is wrong.
> 
> You should tie the vmstate section to DeviceState::vmsd.  You only need
> to do this because you haven't converted everything to QOM yet.
> 
> Please do that to avoid these hacks.

So, Alexey addressed the xics vs. xics-kvm issues.  But there's
another factor here.  It's not clear to me how you'd QOM this
component.

What's being registered here is the "presentation server".  That's the
per-CPU part - vaguely equivalent to the LAPIC on x86.  x86 doesn't
have something equivalent here, because they register the LAPIC state
as part of the CPU state, but we can't do that because the ICP is not
bound to the CPU as tightly - a POWER7 using a different interrupt
architecture would certainly be possible.

So to do this with QOM, would the ICP need to be registered as a child
of the cpu object?
Paolo Bonzini July 15, 2013, 1:05 p.m. UTC | #8
Il 09/07/2013 05:37, Alexey Kardashevskiy ha scritto:
> 
> btw xics-kvm does not introduce new members but does have very different
> .pre_save and .post_load. This actually was the whole point of splitting
> xics into xics and xics-kvm. I cannot see how I can fix it without hacks.
> Property's can be inherited from a parent class (?) but VMStateDescription
> cannot.

The vmstate's pre_save and post_load functions can dispatch to a method
in the subclass.  Again, i8259 does exactly what you want:

static void pic_dispatch_pre_save(void *opaque)
{
    PICCommonState *s = opaque;
    PICCommonClass *info = PIC_COMMON_GET_CLASS(s);

    if (info->pre_save) {
        info->pre_save(s);
    }
}

Paolo
Paolo Bonzini July 15, 2013, 1:10 p.m. UTC | #9
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 09/07/2013 09:17, David Gibson ha scritto:
> So, Alexey addressed the xics vs. xics-kvm issues.  But there's 
> another factor here.  It's not clear to me how you'd QOM this 
> component.
> 
> What's being registered here is the "presentation server".  That's
> the per-CPU part - vaguely equivalent to the LAPIC on x86.  x86
> doesn't have something equivalent here, because they register the
> LAPIC state as part of the CPU state, but we can't do that because
> the ICP is not bound to the CPU as tightly - a POWER7 using a
> different interrupt architecture would certainly be possible.

That's also possible with x86, in fact there is a command line option
to only use the legacy 8259 interrupt controller.

The LAPIC is a separate device from the CPU, it just happens that the
CPU also needs a back-pointer to the LAPIC.  If you do not need that
back-pointer, just do not put it in.  The ICP can still have a link
property that points to the CPU.

Paolo

> So to do this with QOM, would the ICP need to be registered as a
> child of the cpu object?

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJR4/StAAoJEBvWZb6bTYbyxmQQAJi8B6Dlyrg/6EKwtK834MQ/
+XWQda+EfYVzFgECIxzQtiumUMNv2pxOEJ1Ij1jgs4o+n18mH14moO1A1r2YAONx
8eXpmxwd3vt0ka/fiW7BP4mDThUT8u0EYhyLkRnMkXfw2RTElw/E+Cx5v2aCK43C
bz1Ws7Dtjsw3pDinobrl32NhwiJZ+SQvEGnxZiMt1R3PFu7m5cuBdr7Cmc6ZWFAq
lvnUXNqOaAI8sywcsXLMFTan9rzdz0eNRxpMBB9F60szRFmTIGDv8kww0LLwJE1/
pTXv0Ts7jwdA0wykIQQKFLtmLKJGfuq8U4qe/uH+AnevC0CZ0A3/g3y+juC8qKnA
8vUPZdwUy+J4NqdZM1wMMd2QOA1XO4Pd6RTHY5kU7ITDma5A/sHsrysz8XfrcL4T
X8sEDCoUprMn/qF+52671Ol4T8mT5N0pwkjak5yjtQbcmAk4uSXMCS+eAbQ2i8ae
2KCLuCAFTuDIon52UtqEcV/7QHUVp1vB8qjhZjqkLpEgrR7ojINCmUpNaxLddOmz
b3v64JOYk4QNEJ0yccFSSib7LwIxYqilx0Pyk0pl5f5G+eqMFlJhxFSS26QxxIqR
fJMObjZxdoCeH49TLOshRUKJpRi1f7ChxlREiY0xC2eMF0k3fDEWCHqg4K5vMidd
eloFvLkkygN52W9C8f1E
=NpYW
-----END PGP SIGNATURE-----
Alexey Kardashevskiy July 15, 2013, 1:13 p.m. UTC | #10
On 07/15/2013 11:05 PM, Paolo Bonzini wrote:
> Il 09/07/2013 05:37, Alexey Kardashevskiy ha scritto:
>>
>> btw xics-kvm does not introduce new members but does have very different
>> .pre_save and .post_load. This actually was the whole point of splitting
>> xics into xics and xics-kvm. I cannot see how I can fix it without hacks.
>> Property's can be inherited from a parent class (?) but VMStateDescription
>> cannot.
> 
> The vmstate's pre_save and post_load functions can dispatch to a method
> in the subclass.  Again, i8259 does exactly what you want:
> 
> static void pic_dispatch_pre_save(void *opaque)
> {
>     PICCommonState *s = opaque;
>     PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
> 
>     if (info->pre_save) {
>         info->pre_save(s);
>     }
> }

And this is not a hack. Hm. I do not get it. There is even INTERFACE_CLASS
defined but noone is using it. Instead you are proposing to add callbacks
called from callbacks. And this is all for not having dev==NULL in
vmstate_register()... Gosh :(
Paolo Bonzini July 15, 2013, 1:17 p.m. UTC | #11
Il 15/07/2013 15:13, Alexey Kardashevskiy ha scritto:
>> > 
>> > The vmstate's pre_save and post_load functions can dispatch to a method
>> > in the subclass.  Again, i8259 does exactly what you want:
>> > 
>> > static void pic_dispatch_pre_save(void *opaque)
>> > {
>> >     PICCommonState *s = opaque;
>> >     PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
>> > 
>> >     if (info->pre_save) {
>> >         info->pre_save(s);
>> >     }
>> > }
> And this is not a hack. Hm. I do not get it. There is even INTERFACE_CLASS
> defined but noone is using it. Instead you are proposing to add callbacks
> called from callbacks. And this is all for not having dev==NULL in
> vmstate_register()... Gosh :(

This is not about having dev!=NULL.  It is about not using
vmstate_register at all.

Paolo
diff mbox

Patch

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 0e374c8..3e8f48f 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -497,6 +497,61 @@  static void xics_reset(DeviceState *d)
     xics_common_reset(XICS(d));
 }
 
+static int ics_post_load(void *opaque, int version_id)
+{
+    int i;
+    struct ics_state *ics = opaque;
+
+    for (i = 0; i < ics->icp->nr_servers; i++) {
+        icp_resend(ics->icp, i);
+    }
+
+    return 0;
+}
+
+const VMStateDescription vmstate_icp_server = {
+    .name = "icp/server",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        /* Sanity check */
+        VMSTATE_UINT32(xirr, struct icp_server_state),
+        VMSTATE_UINT8(pending_priority, struct icp_server_state),
+        VMSTATE_UINT8(mfrr, struct icp_server_state),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static const VMStateDescription vmstate_ics_irq = {
+    .name = "ics/irq",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32(server, struct ics_irq_state),
+        VMSTATE_UINT8(priority, struct ics_irq_state),
+        VMSTATE_UINT8(saved_priority, struct ics_irq_state),
+        VMSTATE_UINT8(status, struct ics_irq_state),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+const VMStateDescription vmstate_ics = {
+    .name = "ics",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ics_post_load,
+    .fields      = (VMStateField []) {
+        /* Sanity check */
+        VMSTATE_UINT32_EQUAL(nr_irqs, struct ics_state),
+
+        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, struct ics_state, nr_irqs, vmstate_ics_irq, struct ics_irq_state),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
@@ -523,7 +578,11 @@  void xics_common_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
 
 void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
+    struct icp_server_state *ss = &icp->ss[cs->cpu_index];
+
     xics_common_cpu_setup(icp, cpu);
+    vmstate_register(NULL, cs->cpu_index, &vmstate_icp_server, ss);
 }
 
 void xics_common_init(struct icp_state *icp, qemu_irq_handler handler)
@@ -555,6 +614,10 @@  static void xics_realize(DeviceState *dev, Error **errp)
     spapr_rtas_register("ibm,int-off", rtas_int_off);
     spapr_rtas_register("ibm,int-on", rtas_int_on);
 
+    /* We use each the ICS's offset into the global irq number space
+     * as an instance id.  This means we can extend to multiple ICS
+     * instances without needing to change the savevm format */
+    vmstate_register(NULL, icp->ics->offset, &vmstate_ics, icp->ics);
 }
 
 static Property xics_properties[] = {