diff mbox

[master+0.12] pci: irq_state vmstate breakage

Message ID 20100509161503.GA20492@redhat.com
State New
Headers show

Commit Message

Michael S. Tsirkin May 9, 2010, 4:15 p.m. UTC
Code for saving irq_state got vm_state
macros wrong, passing in the wrong parameter.
As a result, we both saved a wrong value
and restored it to a wrong offset.

This leads to device and bus irq counts getting
out of sync, which in turn leads to interrupts getting lost or
never cleared, such as
https://bugzilla.redhat.com/show_bug.cgi?id=588133

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---

Juan, could you please take a look at this patch?
I managed to catch this bug by looking at
a savevm image which already has a wrong value,
but I could not reproduce it locally so I don't know
for sure whether patch is enough, or there are other bugs.

Anthony, this is a regression introduced in
eea4acfa5c1ef26439a718375475fe468b7f2fba
so we need the fix on 0.12 branch as well.

 hw/pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

Comments

Juan Quintela May 9, 2010, 6:07 p.m. UTC | #1
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> Code for saving irq_state got vm_state
> macros wrong, passing in the wrong parameter.
> As a result, we both saved a wrong value
> and restored it to a wrong offset.
>
> This leads to device and bus irq counts getting
> out of sync, which in turn leads to interrupts getting lost or
> never cleared, such as
> https://bugzilla.redhat.com/show_bug.cgi?id=588133
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Acked-by: Juan Quintela <quintela@redhat.com>

Code is "obviously" wrong (TM).  I didn't catch it when it was
introduced.  How can it ever have worked since that commit?

> ---
>
> Juan, could you please take a look at this patch?
> I managed to catch this bug by looking at
> a savevm image which already has a wrong value,
> but I could not reproduce it locally so I don't know
> for sure whether patch is enough, or there are other bugs.
>
> Anthony, this is a regression introduced in
> eea4acfa5c1ef26439a718375475fe468b7f2fba
> so we need the fix on 0.12 branch as well.
>
>  hw/pci.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/pci.c b/hw/pci.c
> index 95bfa3d..5452b86 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -325,7 +325,7 @@ static VMStateInfo vmstate_info_pci_config = {
>  
>  static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
>  {
> -    PCIDevice *s = container_of(pv, PCIDevice, config);
> +    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
>      uint32_t irq_state[PCI_NUM_PINS];
>      int i;
>      for (i = 0; i < PCI_NUM_PINS; ++i) {
> @@ -347,7 +347,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
>  static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
>  {
>      int i;
> -    PCIDevice *s = container_of(pv, PCIDevice, config);
> +    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
>  
>      for (i = 0; i < PCI_NUM_PINS; ++i) {
>          qemu_put_be32(f, pci_irq_state(s, i));
Michael S. Tsirkin May 9, 2010, 9:08 p.m. UTC | #2
On Sun, May 09, 2010 at 08:07:14PM +0200, Juan Quintela wrote:
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > Code for saving irq_state got vm_state
> > macros wrong, passing in the wrong parameter.
> > As a result, we both saved a wrong value
> > and restored it to a wrong offset.
> >
> > This leads to device and bus irq counts getting
> > out of sync, which in turn leads to interrupts getting lost or
> > never cleared, such as
> > https://bugzilla.redhat.com/show_bug.cgi?id=588133
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> 
> Acked-by: Juan Quintela <quintela@redhat.com>
> 
> Code is "obviously" wrong (TM).  I didn't catch it when it was
> introduced.  How can it ever have worked since that commit?

irq_state is often 0, that's why.

> > ---
> >
> > Juan, could you please take a look at this patch?
> > I managed to catch this bug by looking at
> > a savevm image which already has a wrong value,
> > but I could not reproduce it locally so I don't know
> > for sure whether patch is enough, or there are other bugs.
> >
> > Anthony, this is a regression introduced in
> > eea4acfa5c1ef26439a718375475fe468b7f2fba
> > so we need the fix on 0.12 branch as well.
> >
> >  hw/pci.c |    4 ++--
> >  1 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 95bfa3d..5452b86 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -325,7 +325,7 @@ static VMStateInfo vmstate_info_pci_config = {
> >  
> >  static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
> >  {
> > -    PCIDevice *s = container_of(pv, PCIDevice, config);
> > +    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
> >      uint32_t irq_state[PCI_NUM_PINS];
> >      int i;
> >      for (i = 0; i < PCI_NUM_PINS; ++i) {
> > @@ -347,7 +347,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
> >  static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
> >  {
> >      int i;
> > -    PCIDevice *s = container_of(pv, PCIDevice, config);
> > +    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
> >  
> >      for (i = 0; i < PCI_NUM_PINS; ++i) {
> >          qemu_put_be32(f, pci_irq_state(s, i));
diff mbox

Patch

diff --git a/hw/pci.c b/hw/pci.c
index 95bfa3d..5452b86 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -325,7 +325,7 @@  static VMStateInfo vmstate_info_pci_config = {
 
 static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 {
-    PCIDevice *s = container_of(pv, PCIDevice, config);
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
     uint32_t irq_state[PCI_NUM_PINS];
     int i;
     for (i = 0; i < PCI_NUM_PINS; ++i) {
@@ -347,7 +347,7 @@  static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 {
     int i;
-    PCIDevice *s = container_of(pv, PCIDevice, config);
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
 
     for (i = 0; i < PCI_NUM_PINS; ++i) {
         qemu_put_be32(f, pci_irq_state(s, i));