diff mbox

[PULL,16/53] virtio-pci: call pci reset variant when guest requests reset.

Message ID 1457708548-14093-17-git-send-email-mst@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael S. Tsirkin March 11, 2016, 3:08 p.m. UTC
From: Gerd Hoffmann <kraxel@redhat.com>

Actually fixes linux not finding virtio 1.0 device virtqueues after
reboot.  Which is new I think, any chance linux kernel virtio code
became more strict in 4.3?

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Tested-by: Fam Zheng <famz@redhat.com>
---
 hw/virtio/virtio-pci.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

Comments

Laszlo Ersek March 14, 2016, 1:36 a.m. UTC | #1
On 03/11/16 16:08, Michael S. Tsirkin wrote:
> From: Gerd Hoffmann <kraxel@redhat.com>
> 
> Actually fixes linux not finding virtio 1.0 device virtqueues after
> reboot.  Which is new I think, any chance linux kernel virtio code
> became more strict in 4.3?
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> Reviewed-by: Fam Zheng <famz@redhat.com>
> Tested-by: Fam Zheng <famz@redhat.com>
> ---
>  hw/virtio/virtio-pci.c | 11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 440776c..0dadb66 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -47,6 +47,7 @@
>  
>  static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
>                                 VirtIOPCIProxy *dev);
> +static void virtio_pci_reset(DeviceState *qdev);
>  
>  /* virtio device */
>  /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
> @@ -404,9 +405,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>      case VIRTIO_PCI_QUEUE_PFN:
>          pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
>          if (pa == 0) {
> -            virtio_pci_stop_ioeventfd(proxy);
> -            virtio_reset(vdev);
> -            msix_unuse_all_vectors(&proxy->pci_dev);
> +            virtio_pci_reset(DEVICE(proxy));
>          }
>          else
>              virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
> @@ -432,8 +431,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>          }
>  
>          if (vdev->status == 0) {
> -            virtio_reset(vdev);
> -            msix_unuse_all_vectors(&proxy->pci_dev);
> +            virtio_pci_reset(DEVICE(proxy));
>          }
>  
>          /* Linux before 2.6.34 drives the device without enabling
> @@ -1353,8 +1351,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
>          }
>  
>          if (vdev->status == 0) {
> -            virtio_reset(vdev);
> -            msix_unuse_all_vectors(&proxy->pci_dev);
> +            virtio_pci_reset(DEVICE(proxy));
>          }
>  
>          break;
> 

I spent about two days hunting this, and was just about to send a patch.
Nice to see you've already gotten to it. :)

The specific problem was that the queue_enable field was not cleared
(for all possible queues of the device) on device reset, only on system
reset.

Thanks
Laszlo
Laszlo Ersek March 14, 2016, 1:45 a.m. UTC | #2
On 03/14/16 02:36, Laszlo Ersek wrote:
> On 03/11/16 16:08, Michael S. Tsirkin wrote:
>> From: Gerd Hoffmann <kraxel@redhat.com>
>>
>> Actually fixes linux not finding virtio 1.0 device virtqueues after
>> reboot.  Which is new I think, any chance linux kernel virtio code
>> became more strict in 4.3?
>>
>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>> Reviewed-by: Fam Zheng <famz@redhat.com>
>> Tested-by: Fam Zheng <famz@redhat.com>
>> ---
>>  hw/virtio/virtio-pci.c | 11 ++++-------
>>  1 file changed, 4 insertions(+), 7 deletions(-)
>>
>> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
>> index 440776c..0dadb66 100644
>> --- a/hw/virtio/virtio-pci.c
>> +++ b/hw/virtio/virtio-pci.c
>> @@ -47,6 +47,7 @@
>>  
>>  static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
>>                                 VirtIOPCIProxy *dev);
>> +static void virtio_pci_reset(DeviceState *qdev);
>>  
>>  /* virtio device */
>>  /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
>> @@ -404,9 +405,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>>      case VIRTIO_PCI_QUEUE_PFN:
>>          pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
>>          if (pa == 0) {
>> -            virtio_pci_stop_ioeventfd(proxy);
>> -            virtio_reset(vdev);
>> -            msix_unuse_all_vectors(&proxy->pci_dev);
>> +            virtio_pci_reset(DEVICE(proxy));
>>          }
>>          else
>>              virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
>> @@ -432,8 +431,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>>          }
>>  
>>          if (vdev->status == 0) {
>> -            virtio_reset(vdev);
>> -            msix_unuse_all_vectors(&proxy->pci_dev);
>> +            virtio_pci_reset(DEVICE(proxy));
>>          }
>>  
>>          /* Linux before 2.6.34 drives the device without enabling
>> @@ -1353,8 +1351,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
>>          }
>>  
>>          if (vdev->status == 0) {
>> -            virtio_reset(vdev);
>> -            msix_unuse_all_vectors(&proxy->pci_dev);
>> +            virtio_pci_reset(DEVICE(proxy));
>>          }
>>  
>>          break;
>>
> 
> I spent about two days hunting this, and was just about to send a patch.
> Nice to see you've already gotten to it. :)
> 
> The specific problem was that the queue_enable field was not cleared
> (for all possible queues of the device) on device reset, only on system
> reset.

... If you wonder, it is not only needed for after reboot, but also for
when OVMF hands off the devices to the kernel (but resets them first in
the appropriate ExitBootServices() callbacks). It took me so long
because when you work on new guest driver code and things break, you
don't immediately suspect the host! :) Oh the hours I spent
instrumenting the guest kernel. Sigh. :)

Thanks
Laszlo
diff mbox

Patch

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 440776c..0dadb66 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -47,6 +47,7 @@ 
 
 static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
                                VirtIOPCIProxy *dev);
+static void virtio_pci_reset(DeviceState *qdev);
 
 /* virtio device */
 /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
@@ -404,9 +405,7 @@  static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case VIRTIO_PCI_QUEUE_PFN:
         pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
         if (pa == 0) {
-            virtio_pci_stop_ioeventfd(proxy);
-            virtio_reset(vdev);
-            msix_unuse_all_vectors(&proxy->pci_dev);
+            virtio_pci_reset(DEVICE(proxy));
         }
         else
             virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
@@ -432,8 +431,7 @@  static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         }
 
         if (vdev->status == 0) {
-            virtio_reset(vdev);
-            msix_unuse_all_vectors(&proxy->pci_dev);
+            virtio_pci_reset(DEVICE(proxy));
         }
 
         /* Linux before 2.6.34 drives the device without enabling
@@ -1353,8 +1351,7 @@  static void virtio_pci_common_write(void *opaque, hwaddr addr,
         }
 
         if (vdev->status == 0) {
-            virtio_reset(vdev);
-            msix_unuse_all_vectors(&proxy->pci_dev);
+            virtio_pci_reset(DEVICE(proxy));
         }
 
         break;