qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] vfio/pci: fix out-of-sync BAR information on re


From: Ido Yariv
Subject: Re: [Qemu-devel] [PATCH] vfio/pci: fix out-of-sync BAR information on reset
Date: Fri, 21 Oct 2016 14:35:56 -0400

Hi Alex,

On Fri, Oct 21, 2016 at 2:03 PM, Alex Williamson <address@hidden
> wrote:

> On Fri, 21 Oct 2016 13:00:33 -0400
> Ido Yariv <address@hidden> wrote:
>
> > When a PCI device is reset, pci_do_device_reset resets all BAR addresses
> > in the relevant PCIDevice's config buffer.
> >
> > The VFIO configuration space stays untouched, so the guest OS may choose
> > to skip restoring the BAR addresses as they would seem intact. The PCI
> > device may be left non-operational.
> > One example of such a scenario is when the guest exits S3.
> >
> > Fix this by resetting the BAR addresses in the VFIO configuration space
> > as well.
> >
> > Signed-off-by: Ido Yariv <address@hidden>
> > ---
> >  hw/vfio/pci.c | 30 ++++++++++++++++++++++++++++++
> >  1 file changed, 30 insertions(+)
> >
> > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> > index 65d30fd..9e1dee0 100644
> > --- a/hw/vfio/pci.c
> > +++ b/hw/vfio/pci.c
> > @@ -1922,11 +1922,41 @@ static void vfio_pci_pre_reset(VFIOPCIDevice
> *vdev)
> >  static void vfio_pci_post_reset(VFIOPCIDevice *vdev)
> >  {
> >      Error *err = NULL;
> > +    int nr;
> >
> >      vfio_intx_enable(vdev, &err);
> >      if (err) {
> >          error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name);
> >      }
> > +
> > +    for (nr = 0; nr < PCI_NUM_REGIONS - 1; ++nr) {
> > +        VFIOBAR *bar = &vdev->bars[nr];
> > +        off_t addr = vdev->config_offset + PCI_BASE_ADDRESS_0 + (4 *
> nr);
> > +        uint32_t org = 0;
> > +        uint64_t val = 0;
> > +        uint32_t len;
> > +
> > +        if (!bar->region.size) {
> > +            continue;
> > +        }
> > +
> > +        if (pread(vdev->vbasedev.fd, &org, sizeof(org), addr) < 0) {
> > +            error_report("%s(%s) read bar %d failed: %m", __func__,
> > +                         vdev->vbasedev.name, nr);
> > +            continue;
> > +        }
> > +
> > +        val = le32_to_cpu(org);
> > +        val &= (bar->ioport ? ~PCI_BASE_ADDRESS_IO_MASK :
> > +                              ~PCI_BASE_ADDRESS_MEM_MASK);
> > +        val = cpu_to_le64(val);
> > +
> > +        len = bar->mem64 ? sizeof(uint64_t) : sizeof(uint32_t);
> > +        if (pwrite(vdev->vbasedev.fd, &val, len, addr) != len) {
> > +            error_report("%s(%s) reset bar %d failed: %m", __func__,
> > +                         vdev->vbasedev.name, nr);
> > +        }
> > +    }
>
> Why do we care to be so precise, can't we just blindly do 4-byte writes
> of zero to each of the 6 BAR registers?  The bits you're trying to
> preserve should be read-only anyway.  Nothing is saved by trying to do
> an 8-byte write for 64-bit BARs.  Thanks,
>

​I wasn't sure if the vfio-pci driver masks these bits, but I see
vfio_bar_fixup takes care of that.
I'll send a revised patch then.

Cheers,
Ido.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]