qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Laszlo Ersek <lersek@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>,
	Stefan Hajnoczi <stefanha@gmail.com>,
	Kangjie Xu <kangjie.xu@linux.alibaba.com>,
	qemu-devel@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
	Xuan Zhuo <xuanzhuo@linux.alibaba.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [PULL v4 29/83] virtio: introduce virtio_queue_enable()
Date: Wed, 9 Nov 2022 06:00:53 -0500	[thread overview]
Message-ID: <20221109054049-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <ad04a8b3-b07d-a259-0b33-261f5784e48d@redhat.com>

On Wed, Nov 09, 2022 at 09:56:40AM +0100, Laszlo Ersek wrote:
> On 11/09/22 07:59, Michael S. Tsirkin wrote:
> > On Wed, Nov 09, 2022 at 01:52:01AM -0500, Michael S. Tsirkin wrote:
> >> On Wed, Nov 09, 2022 at 11:31:23AM +0800, Jason Wang wrote:
> >>> On Wed, Nov 9, 2022 at 3:43 AM Stefan Hajnoczi <stefanha@gmail.com> wrote:
> >>>>
> >>>> On Mon, 7 Nov 2022 at 18:10, Michael S. Tsirkin <mst@redhat.com> wrote:
> >>>>>
> >>>>> From: Kangjie Xu <kangjie.xu@linux.alibaba.com>
> >>>>>
> >>>>> Introduce the interface queue_enable() in VirtioDeviceClass and the
> >>>>> fucntion virtio_queue_enable() in virtio, it can be called when
> >>>>> VIRTIO_PCI_COMMON_Q_ENABLE is written and related virtqueue can be
> >>>>> started. It only supports the devices of virtio 1 or later. The
> >>>>> not-supported devices can only start the virtqueue when DRIVER_OK.
> >>>>>
> >>>>> Signed-off-by: Kangjie Xu <kangjie.xu@linux.alibaba.com>
> >>>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> >>>>> Acked-by: Jason Wang <jasowang@redhat.com>
> >>>>> Message-Id: <20221017092558.111082-4-xuanzhuo@linux.alibaba.com>
> >>>>> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
> >>>>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >>>>> ---
> >>>>>  include/hw/virtio/virtio.h |  2 ++
> >>>>>  hw/virtio/virtio.c         | 14 ++++++++++++++
> >>>>>  2 files changed, 16 insertions(+)
> >>>>>
> >>>>> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> >>>>> index 74d76c1dbc..b00b3fcf31 100644
> >>>>> --- a/include/hw/virtio/virtio.h
> >>>>> +++ b/include/hw/virtio/virtio.h
> >>>>> @@ -149,6 +149,7 @@ struct VirtioDeviceClass {
> >>>>>      void (*reset)(VirtIODevice *vdev);
> >>>>>      void (*set_status)(VirtIODevice *vdev, uint8_t val);
> >>>>>      void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
> >>>>> +    void (*queue_enable)(VirtIODevice *vdev, uint32_t queue_index);
> >>>>>      /* For transitional devices, this is a bitmap of features
> >>>>>       * that are only exposed on the legacy interface but not
> >>>>>       * the modern one.
> >>>>> @@ -288,6 +289,7 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, int n,
> >>>>>  int virtio_set_status(VirtIODevice *vdev, uint8_t val);
> >>>>>  void virtio_reset(void *opaque);
> >>>>>  void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
> >>>>> +void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index);
> >>>>>  void virtio_update_irq(VirtIODevice *vdev);
> >>>>>  int virtio_set_features(VirtIODevice *vdev, uint64_t val);
> >>>>>
> >>>>> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> >>>>> index cf5f9ca387..9683b2e158 100644
> >>>>> --- a/hw/virtio/virtio.c
> >>>>> +++ b/hw/virtio/virtio.c
> >>>>> @@ -2495,6 +2495,20 @@ void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
> >>>>>      __virtio_queue_reset(vdev, queue_index);
> >>>>>  }
> >>>>>
> >>>>> +void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
> >>>>> +{
> >>>>> +    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
> >>>>> +
> >>>>> +    if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
> >>>>> +        error_report("queue_enable is only suppported in devices of virtio "
> >>>>> +                     "1.0 or later.");
> >>>>
> >>>> Why is this triggering here? Maybe virtio_queue_enable() is called too
> >>>> early. I have verified that the Linux guest driver sets VERSION_1. I
> >>>> didn't check what SeaBIOS does.
> >>>
> >>> Looks like a bug, we should check device features here at least and it
> >>> should be guest errors instead of error_report() here.
> >>>
> >>> Thanks
> >>
> >> But it's weird, queue enable is written before guest features?
> >> How come?
> >
> > It's a bios bug:
> >
> >
> >
> >     vp_init_simple(&vdrive->vp, pci);
> >     if (vp_find_vq(&vdrive->vp, 0, &vdrive->vq) < 0 ) {
> >         dprintf(1, "fail to find vq for virtio-blk %pP\n", pci);
> >         goto fail;
> >     }
> >
> >     if (vdrive->vp.use_modern) {
> >         struct vp_device *vp = &vdrive->vp;
> >         u64 features = vp_get_features(vp);
> >         u64 version1 = 1ull << VIRTIO_F_VERSION_1;
> >         u64 iommu_platform = 1ull << VIRTIO_F_IOMMU_PLATFORM;
> >         u64 blk_size = 1ull << VIRTIO_BLK_F_BLK_SIZE;
> >         if (!(features & version1)) {
> >             dprintf(1, "modern device without virtio_1 feature bit: %pP\n", pci);
> >             goto fail;
> >         }
> >
> >         features = features & (version1 | iommu_platform | blk_size);
> >         vp_set_features(vp, features);
> >         status |= VIRTIO_CONFIG_S_FEATURES_OK;
> >         vp_set_status(vp, status);
> >
> >
> >
> > Not good - does not match the spec. Here's what the spec says:
> >
> >
> > The driver MUST follow this sequence to initialize a device:
> > 1. Reset the device.
> > 2. Set the ACKNOWLEDGE status bit: the guest OS has noticed the device.
> > 3. Set the DRIVER status bit: the guest OS knows how to drive the device.
> > 4. Read device feature bits, and write the subset of feature bits understood by the OS and driver to the
> > device. During this step the driver MAY read (but MUST NOT write) the device-specific configuration
> > fields to check that it can support the device before accepting it.
> > 5. Set the FEATURES_OK status bit. The driver MUST NOT accept new feature bits after this step.
> > 6. Re-read device status to ensure the FEATURES_OK bit is still set: otherwise, the device does not
> > support our subset of features and the device is unusable.
> > 7. Perform device-specific setup, including discovery of virtqueues for the device, optional per-bus setup,
> > reading and possibly writing the device’s virtio configuration space, and population of virtqueues.
> > 8. Set the DRIVER_OK status bit. At this point the device is “live”.
> 
> Thanks for the Cc.
> 
> This should work properly in the edk2 (OVMF) guest drivers. When I
> started work on the virtio-1.0 implementation, I noticed that the device
> initialization sequence that guest drivers needed to follow had
> *changed* from spec version 0.9.5 to spec version 1.0.
> 
> For example, in the virtio-rng driver, I addressed that with commit
> 0a781bdc7f87 ("OvmfPkg: VirtioRngDxe: adapt feature negotiation to
> virtio-1.0", 2016-04-06):
> 
>   https://github.com/tianocore/edk2/commit/0a781bdc7f87


Thanks, and great analysis below!

Yes, in 0.9 it was:

1. Reset the device. This is not required on initial start up.
2. The ACKNOWLEDGE status bit is set: we have noticed the device.
3. The DRIVER status bit is set: we know how to drive the device.
4. Device-specific setup, including reading the Device Feature Bits, discov-
ery of virtqueues for the device, optional MSI-X setup, and reading and
possibly writing the virtio configuration space.
5. The subset of Device Feature Bits understood by the driver is written to
the device.
6. The DRIVER_OK status bit is set.
7. The device can now be used (ie. buffers added to the virtqueues)

Interestingly, Linux stopped following this order even for 0.9.X:

commit ef688e151c00e5d529703be9a04fd506df8bc54e
Author: Rusty Russell <rusty@rustcorp.com.au>
Date:   Fri Jun 12 22:16:35 2009 -0600

    virtio: meet virtio spec by finalizing features before using device
    
    Virtio devices are supposed to negotiate features before they start using
    the device, but the current code doesn't do this.  This is because the
    driver's probe() function invariably has to add buffers to a virtqueue,
    or probe the disk (virtio_blk).
    
    This currently doesn't matter since no existing backend is strict about
    the feature negotiation.  But it's possible to imagine a future feature
    which completely changes how a device operates: in this case, we'd need
    to acknowledge it before using the device.
    
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>





So it's especially unfortunate that bios is still following
the 0.9 sequence even for 1.0.





> Therefore we have a larger context like this in edk2 (again the excerpt
> is from the virtio-rng driver, but all drivers follow this pattern whose
> devices can be either legacy or modern):
> 
> >   //
> >   // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
> >   //
> >   NextDevStat = 0;             // step 1 -- reset device
> >   Status      = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> 
> matches v1.0 spec step 1.
> 
> >
> >   NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence
> >   Status       = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> 
> matches v1.0 spec step 2.
> 
> >
> >   NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
> >   Status       = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> 
> matches v1.0 spec step 3.
> 
> >
> >   //
> >   // Set Page Size - MMIO VirtIo Specific
> >   //
> >   Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // step 4a -- retrieve and validate features
> >   //
> >   Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> 
> matches v1.0 spec step 4, the "read" part
> 
> >
> >   Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
> >
> >   //
> >   // In virtio-1.0, feature negotiation is expected to complete before queue
> >   // discovery, and the device can also reject the selected set of features.
> >   //
> >   if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
> >     Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
> >     if (EFI_ERROR (Status)) {
> >       goto Failed;
> >     }
> >   }
> 
> This is skipped for virtio-0.9.5. For virtio-1.0,
> Virtio10WriteFeatures() does the following:
> 
> >   Status = VirtIo->SetGuestFeatures (VirtIo, Features);
> >   if (EFI_ERROR (Status)) {
> >     return Status;
> >   }
> 
> Covers v1.0 spec step 4, the rest of it.
> 
> >
> >   *DeviceStatus |= VSTAT_FEATURES_OK;
> >   Status         = VirtIo->SetDeviceStatus (VirtIo, *DeviceStatus);
> >   if (EFI_ERROR (Status)) {
> >     return Status;
> >   }
> 
> Covers v1.0 spec step 5.
> 
> >
> >   Status = VirtIo->GetDeviceStatus (VirtIo, DeviceStatus);
> >   if (EFI_ERROR (Status)) {
> >     return Status;
> >   }
> >
> >   if ((*DeviceStatus & VSTAT_FEATURES_OK) == 0) {
> >     Status = EFI_UNSUPPORTED;
> >   }
> 
> Covers v1.0 spec step 6.
> 
> OK, return to the previous call frame:
> 
> >
> >   //
> >   // step 4b -- allocate request virtqueue, just use #0
> >   //
> >   Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // VirtioRngGetRNG() uses one descriptor
> >   //
> >   if (QueueSize < 1) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // If anything fails from here on, we must release the ring resources.
> >   //
> >   Status = VirtioRingMap (
> >              Dev->VirtIo,
> >              &Dev->Ring,
> >              &RingBaseShift,
> >              &Dev->RingMap
> >              );
> >   if (EFI_ERROR (Status)) {
> >     goto ReleaseQueue;
> >   }
> >
> >   //
> >   // Additional steps for MMIO: align the queue appropriately, and set the
> >   // size. If anything fails from here on, we must unmap the ring resources.
> >   //
> >   Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   //
> >   // step 4c -- Report GPFN (guest-physical frame number) of queue.
> >   //
> >   Status = Dev->VirtIo->SetQueueAddress (
> >                           Dev->VirtIo,
> >                           &Dev->Ring,
> >                           RingBaseShift
> >                           );
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> 
> These cover v1.0 spec step 7.
> 
> >
> >   //
> >   // step 5 -- Report understood features and guest-tuneables.
> >   //
> >   if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
> >     Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
> >     Status    = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
> >     if (EFI_ERROR (Status)) {
> >       goto UnmapQueue;
> >     }
> >   }
> 
> This is exclusive to virtio-0.9.5; the "step 5" reference in the comment
> pertains to that spec version. In virtio-0.9.5, this is the location
> (just before setting DRIVER_OK) where the guest driver has to report its
> desired features (and the device has no means to reject any feature set
> that is otherwise a subset of the host feature set).
> 
> >
> >   //
> >   // step 6 -- initialization complete
> >   //
> >   NextDevStat |= VSTAT_DRIVER_OK;
> >   Status       = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> 
> This covers v1.0 spec step 8 (and v0.9.5 spec step 6, as the comment
> shows).
> 
> Now, in drivers whose devices are virtio-1.0-only, such as
> virtio-gpu-pci, vhost-user-fs-pci, this "selectivity" is not there. The
> virtio-0.9.5 branch is simply eliminated, and the virtio-1.0 logic is
> unconditional. Additionally, in those drivers, the "step" references in
> the code comments match the v1.0 bullet list. For example, in the
> virtio-fs driver:
> 
> > EFI_STATUS
> > VirtioFsInit (
> >   IN OUT VIRTIO_FS  *VirtioFs
> >   )
> > {
> >   UINT8             NextDevStat;
> >   EFI_STATUS        Status;
> >   UINT64            Features;
> >   VIRTIO_FS_CONFIG  Config;
> >   UINTN             Idx;
> >   UINT64            RingBaseShift;
> >
> >   //
> >   // Execute virtio-v1.1-cs01-87fa6b5d8155, 3.1.1 Driver Requirements: Device
> >   // Initialization.
> >   //
> >   // 1. Reset the device.
> >   //
> >   NextDevStat = 0;
> >   Status      = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 2. Set the ACKNOWLEDGE status bit [...]
> >   //
> >   NextDevStat |= VSTAT_ACK;
> >   Status       = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 3. Set the DRIVER status bit [...]
> >   //
> >   NextDevStat |= VSTAT_DRIVER;
> >   Status       = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 4. Read device feature bits...
> >   //
> >   Status = VirtioFs->Virtio->GetDeviceFeatures (VirtioFs->Virtio, &Features);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   if ((Features & VIRTIO_F_VERSION_1) == 0) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   //
> >   // No device-specific feature bits have been defined in file "virtio-fs.tex"
> >   // of the virtio spec at <https://github.com/oasis-tcs/virtio-spec.git>, as
> >   // of commit 87fa6b5d8155.
> >   //
> >   Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
> >
> >   //
> >   // ... and write the subset of feature bits understood by the [...] driver to
> >   // the device. [...]
> >   // 5. Set the FEATURES_OK status bit.
> >   // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
> >   //
> >   Status = Virtio10WriteFeatures (VirtioFs->Virtio, Features, &NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 7. Perform device-specific setup, including discovery of virtqueues for
> >   // the device, [...] reading [...] the device's virtio configuration space
> >   //
> >   Status = VirtioFsReadConfig (VirtioFs->Virtio, &Config);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 7.a. Convert the filesystem label from UTF-8 to UCS-2. Only labels with
> >   // printable ASCII code points (U+0020 through U+007E) are supported.
> >   // NUL-terminate at either the terminator we find, or right after the
> >   // original label.
> >   //
> >   for (Idx = 0; Idx < VIRTIO_FS_TAG_BYTES && Config.Tag[Idx] != '\0'; Idx++) {
> >     if ((Config.Tag[Idx] < 0x20) || (Config.Tag[Idx] > 0x7E)) {
> >       Status = EFI_UNSUPPORTED;
> >       goto Failed;
> >     }
> >
> >     VirtioFs->Label[Idx] = Config.Tag[Idx];
> >   }
> >
> >   VirtioFs->Label[Idx] = L'\0';
> >
> >   //
> >   // 7.b. We need one queue for sending normal priority requests.
> >   //
> >   if (Config.NumReqQueues < 1) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   //
> >   // 7.c. Fetch and remember the number of descriptors we can place on the
> >   // queue at once. We'll need two descriptors per request, as a minimum --
> >   // request header, response header.
> >   //
> >   Status = VirtioFs->Virtio->SetQueueSel (
> >                                VirtioFs->Virtio,
> >                                VIRTIO_FS_REQUEST_QUEUE
> >                                );
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   Status = VirtioFs->Virtio->GetQueueNumMax (
> >                                VirtioFs->Virtio,
> >                                &VirtioFs->QueueSize
> >                                );
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   if (VirtioFs->QueueSize < 2) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   //
> >   // 7.d. [...] population of virtqueues [...]
> >   //
> >   Status = VirtioRingInit (
> >              VirtioFs->Virtio,
> >              VirtioFs->QueueSize,
> >              &VirtioFs->Ring
> >              );
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   Status = VirtioRingMap (
> >              VirtioFs->Virtio,
> >              &VirtioFs->Ring,
> >              &RingBaseShift,
> >              &VirtioFs->RingMap
> >              );
> >   if (EFI_ERROR (Status)) {
> >     goto ReleaseQueue;
> >   }
> >
> >   Status = VirtioFs->Virtio->SetQueueAddress (
> >                                VirtioFs->Virtio,
> >                                &VirtioFs->Ring,
> >                                RingBaseShift
> >                                );
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   //
> >   // 8. Set the DRIVER_OK status bit.
> >   //
> >   NextDevStat |= VSTAT_DRIVER_OK;
> >   Status       = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   return EFI_SUCCESS;
> >
> > UnmapQueue:
> >   VirtioFs->Virtio->UnmapSharedBuffer (VirtioFs->Virtio, VirtioFs->RingMap);
> >
> > ReleaseQueue:
> >   VirtioRingUninit (VirtioFs->Virtio, &VirtioFs->Ring);
> >
> > Failed:
> >   //
> >   // If any of these steps go irrecoverably wrong, the driver SHOULD set the
> >   // FAILED status bit to indicate that it has given up on the device (it can
> >   // reset the device later to restart if desired). [...]
> >   //
> >   // Virtio access failure here should not mask the original error.
> >   //
> >   NextDevStat |= VSTAT_FAILED;
> >   VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
> >
> >   return Status;
> > }
> 
> In the virtio-gpu driver:
> 
> > EFI_STATUS
> > VirtioGpuInit (
> >   IN OUT VGPU_DEV  *VgpuDev
> >   )
> > {
> >   UINT8       NextDevStat;
> >   EFI_STATUS  Status;
> >   UINT64      Features;
> >   UINT16      QueueSize;
> >   UINT64      RingBaseShift;
> >
> >   //
> >   // Execute virtio-v1.0-cs04, 3.1.1 Driver Requirements: Device
> >   // Initialization.
> >   //
> >   // 1. Reset the device.
> >   //
> >   NextDevStat = 0;
> >   Status      = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 2. Set the ACKNOWLEDGE status bit [...]
> >   //
> >   NextDevStat |= VSTAT_ACK;
> >   Status       = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 3. Set the DRIVER status bit [...]
> >   //
> >   NextDevStat |= VSTAT_DRIVER;
> >   Status       = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 4. Read device feature bits...
> >   //
> >   Status = VgpuDev->VirtIo->GetDeviceFeatures (VgpuDev->VirtIo, &Features);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   if ((Features & VIRTIO_F_VERSION_1) == 0) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   //
> >   // We only want the most basic 2D features.
> >   //
> >   Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
> >
> >   //
> >   // ... and write the subset of feature bits understood by the [...] driver to
> >   // the device. [...]
> >   // 5. Set the FEATURES_OK status bit.
> >   // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
> >   //
> >   Status = Virtio10WriteFeatures (VgpuDev->VirtIo, Features, &NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // 7. Perform device-specific setup, including discovery of virtqueues for
> >   // the device [...]
> >   //
> >   Status = VgpuDev->VirtIo->SetQueueSel (
> >                               VgpuDev->VirtIo,
> >                               VIRTIO_GPU_CONTROL_QUEUE
> >                               );
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   Status = VgpuDev->VirtIo->GetQueueNumMax (VgpuDev->VirtIo, &QueueSize);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // We implement each VirtIo GPU command that we use with two descriptors:
> >   // request, response.
> >   //
> >   if (QueueSize < 2) {
> >     Status = EFI_UNSUPPORTED;
> >     goto Failed;
> >   }
> >
> >   //
> >   // [...] population of virtqueues [...]
> >   //
> >   Status = VirtioRingInit (VgpuDev->VirtIo, QueueSize, &VgpuDev->Ring);
> >   if (EFI_ERROR (Status)) {
> >     goto Failed;
> >   }
> >
> >   //
> >   // If anything fails from here on, we have to release the ring.
> >   //
> >   Status = VirtioRingMap (
> >              VgpuDev->VirtIo,
> >              &VgpuDev->Ring,
> >              &RingBaseShift,
> >              &VgpuDev->RingMap
> >              );
> >   if (EFI_ERROR (Status)) {
> >     goto ReleaseQueue;
> >   }
> >
> >   //
> >   // If anything fails from here on, we have to unmap the ring.
> >   //
> >   Status = VgpuDev->VirtIo->SetQueueAddress (
> >                               VgpuDev->VirtIo,
> >                               &VgpuDev->Ring,
> >                               RingBaseShift
> >                               );
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   //
> >   // 8. Set the DRIVER_OK status bit.
> >   //
> >   NextDevStat |= VSTAT_DRIVER_OK;
> >   Status       = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
> >   if (EFI_ERROR (Status)) {
> >     goto UnmapQueue;
> >   }
> >
> >   return EFI_SUCCESS;
> >
> > UnmapQueue:
> >   VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
> >
> > ReleaseQueue:
> >   VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
> >
> > Failed:
> >   //
> >   // If any of these steps go irrecoverably wrong, the driver SHOULD set the
> >   // FAILED status bit to indicate that it has given up on the device (it can
> >   // reset the device later to restart if desired). [...]
> >   //
> >   // VirtIo access failure here should not mask the original error.
> >   //
> >   NextDevStat |= VSTAT_FAILED;
> >   VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
> >
> >   return Status;
> > }
> 
> Laszlo



  reply	other threads:[~2022-11-09 11:01 UTC|newest]

Thread overview: 150+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-07 22:47 [PULL v4 00/83] pci,pc,virtio: features, tests, fixes, cleanups Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 01/83] hw/i386/e820: remove legacy reserved entries for e820 Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 02/83] tests/acpi: allow SSDT changes Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 03/83] acpi/ssdt: Fix aml_or() and aml_and() in if clause Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 04/83] acpi/nvdimm: define macro for NVDIMM Device _DSM Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 05/83] acpi/nvdimm: Implement ACPI NVDIMM Label Methods Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 06/83] test/acpi/bios-tables-test: SSDT: update golden master binaries Michael S. Tsirkin
2022-11-07 22:47 ` [PULL v4 07/83] virtio-crypto: Support asynchronous mode Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 08/83] crypto: Support DER encodings Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 09/83] crypto: Support export akcipher to pkcs8 Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 10/83] cryptodev: Add a lkcf-backend for cryptodev Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 11/83] acpi/tests/avocado/bits: initial commit of test scripts that are run by biosbits Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 12/83] acpi/tests/avocado/bits: disable acpi PSS tests that are failing in biosbits Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 13/83] acpi/tests/avocado/bits: add biosbits config file for running bios tests Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 14/83] acpi/tests/avocado/bits: add acpi and smbios avocado tests that uses biosbits Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 15/83] acpi/tests/avocado/bits/doc: add a doc file to describe the acpi bits test Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 16/83] MAINTAINERS: add myself as the maintainer for acpi biosbits avocado tests Michael S. Tsirkin
2022-11-07 22:48 ` [PULL v4 17/83] tests/acpi: virt: allow acpi MADT and FADT changes Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 18/83] acpi: fadt: support revision 6.0 of the ACPI specification Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 19/83] acpi: arm/virt: madt: bump to revision 4 accordingly to ACPI 6.0 Errata A Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 20/83] tests/acpi: virt: update ACPI MADT and FADT binaries Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 21/83] hw/pci: PCIe Data Object Exchange emulation Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 22/83] hw/mem/cxl-type3: Add MSIX support Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 23/83] hw/cxl/cdat: CXL CDAT Data Object Exchange implementation Michael S. Tsirkin
2023-04-11 15:52   ` Peter Maydell
2023-04-12 13:08     ` Jonathan Cameron via
2023-04-12 14:39     ` Jonathan Cameron via
2022-11-07 22:49 ` [PULL v4 24/83] hw/mem/cxl-type3: Add CXL CDAT Data Object Exchange Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 25/83] hw/pci-bridge/cxl-upstream: Add a CDAT table access DOE Michael S. Tsirkin
2023-06-23 13:23   ` Peter Maydell
2022-11-07 22:49 ` [PULL v4 26/83] hw/virtio/virtio-iommu-pci: Enforce the device is plugged on the root bus Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 27/83] virtio: introduce __virtio_queue_reset() Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 28/83] virtio: introduce virtio_queue_reset() Michael S. Tsirkin
2022-11-07 22:49 ` [PULL v4 29/83] virtio: introduce virtio_queue_enable() Michael S. Tsirkin
2022-11-08 19:43   ` Stefan Hajnoczi
2022-11-09  3:31     ` Jason Wang
2022-11-09  6:39       ` Michael S. Tsirkin
2022-11-09  6:48         ` Xuan Zhuo
2022-11-09  7:01           ` Michael S. Tsirkin
2022-11-09  7:11             ` Xuan Zhuo
2022-11-09  6:51       ` Michael S. Tsirkin
2022-11-09  6:55         ` Jason Wang
2022-11-09  6:56           ` Xuan Zhuo
2022-11-09  7:04             ` Michael S. Tsirkin
2022-11-09  7:12               ` Xuan Zhuo
2022-11-09  6:59         ` Michael S. Tsirkin
2022-11-09  8:56           ` Laszlo Ersek
2022-11-09 11:00             ` Michael S. Tsirkin [this message]
2022-11-07 22:50 ` [PULL v4 30/83] virtio: core: vq reset feature negotation support Michael S. Tsirkin
2022-11-18 14:32   ` Stefano Garzarella
2022-11-18 14:39     ` Stefano Garzarella
2022-11-19 17:19     ` Michael S. Tsirkin
2022-11-21  6:17       ` Jason Wang
2022-11-21  7:07         ` Michael S. Tsirkin
2022-11-21  8:20           ` Stefano Garzarella
2022-11-07 22:50 ` [PULL v4 31/83] virtio-pci: support queue reset Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 32/83] virtio-pci: support queue enable Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 33/83] vhost: expose vhost_virtqueue_start() Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 34/83] vhost: expose vhost_virtqueue_stop() Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 35/83] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset() Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 36/83] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart() Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 37/83] virtio-net: introduce flush_or_purge_queued_packets() Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 38/83] virtio-net: support queue reset Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 39/83] virtio-net: support queue_enable Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 40/83] vhost: vhost-kernel: enable vq reset feature Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 41/83] virtio-net: " Michael S. Tsirkin
2022-11-07 22:50 ` [PULL v4 42/83] virtio-rng-pci: Allow setting nvectors, so we can use MSI-X Michael S. Tsirkin
2023-01-09 10:20   ` Dr. David Alan Gilbert
2023-01-09 10:38     ` Michael S. Tsirkin
2023-01-09 10:43       ` Dr. David Alan Gilbert
2022-11-07 22:51 ` [PULL v4 43/83] vhost-user: Fix out of order vring host notification handling Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 44/83] acpi: pc: vga: use AcpiDevAmlIf interface to build VGA device descriptors Michael S. Tsirkin
2022-11-09 17:39   ` Laurent Vivier
2022-11-09 21:42     ` Michael S. Tsirkin
2022-11-10  9:28       ` Peter Maydell
2022-11-11  9:43         ` Igor Mammedov
2022-11-11 10:25           ` Igor Mammedov
2022-11-10  2:55     ` Ani Sinha
2022-11-07 22:51 ` [PULL v4 45/83] tests: acpi: whitelist DSDT before generating PCI-ISA bridge AML automatically Michael S. Tsirkin
2022-11-08 13:36   ` Igor Mammedov
2022-11-08 13:39     ` Ani Sinha
2022-11-08 14:06       ` Ani Sinha
2022-11-08 13:49     ` Michael S. Tsirkin
2022-11-08 14:31       ` Igor Mammedov
2022-11-07 22:51 ` [PULL v4 46/83] acpi: pc/q35: drop ad-hoc PCI-ISA bridge AML routines and let bus ennumeration generate AML Michael S. Tsirkin
2022-11-17 21:51   ` Volker Rümelin
2022-11-18 13:08     ` Igor Mammedov
2022-11-18 14:55       ` Igor Mammedov
2022-11-19  8:49         ` Volker Rümelin
2022-11-21  7:27           ` Igor Mammedov
2022-11-19 17:22         ` Michael S. Tsirkin
2022-11-21  7:23           ` Igor Mammedov
2022-11-21  7:50             ` Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 47/83] tests: acpi: update expected DSDT after ISA bridge is moved directly under PCI host bridge Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 48/83] tests: acpi: whitelist DSDT before generating ICH9_SMB AML automatically Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 49/83] acpi: add get_dev_aml_func() helper Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 50/83] acpi: enumerate SMB bridge automatically along with other PCI devices Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 51/83] tests: acpi: update expected blobs Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 52/83] tests: acpi: pc/q35 whitelist DSDT before \_GPE cleanup Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 53/83] acpi: pc/35: sanitize _GPE declaration order Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 54/83] tests: acpi: update expected blobs Michael S. Tsirkin
2022-11-07 22:51 ` [PULL v4 55/83] hw/acpi/erst.c: Fix memory handling issues Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 56/83] MAINTAINERS: Add qapi/virtio.json to section "virtio" Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 57/83] msix: Assert that specified vector is in range Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 58/83] hw/i386/pc.c: CXL Fixed Memory Window should not reserve e820 in bios Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 59/83] hw/i386/acpi-build: Remove unused struct Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 60/83] hw/i386/acpi-build: Resolve redundant attribute Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 61/83] hw/i386/acpi-build: Resolve north rather than south bridges Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 62/83] hmat acpi: Don't require initiator value in -numa Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 63/83] tests: acpi: add and whitelist *.hmat-noinitiator expected blobs Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 64/83] tests: acpi: q35: add test for hmat nodes without initiators Michael S. Tsirkin
2022-11-07 22:52 ` [PULL v4 65/83] tests: acpi: q35: update expected blobs *.hmat-noinitiators expected HMAT: Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 66/83] tests: Add HMAT AArch64/virt empty table files Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 67/83] hw/arm/virt: Enable HMAT on arm virt machine Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 68/83] tests: acpi: aarch64/virt: add a test for hmat nodes with no initiators Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 69/83] tests: virt: Update expected *.acpihmatvirt tables Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 70/83] vfio: move implement of vfio_get_xlat_addr() to memory.c Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 71/83] intel-iommu: don't warn guest errors when getting rid2pasid entry Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 72/83] intel-iommu: drop VTDBus Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 73/83] intel-iommu: convert VTD_PE_GET_FPD_ERR() to be a function Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 74/83] intel-iommu: PASID support Michael S. Tsirkin
2023-04-06 16:22   ` Peter Maydell
2023-04-10  2:55     ` Jason Wang
2022-11-07 22:53 ` [PULL v4 75/83] vhost: Change the sequence of device start Michael S. Tsirkin
2022-11-07 22:53 ` [PULL v4 76/83] vhost-user: Support vhost_dev_start Michael S. Tsirkin
2023-01-06 14:21   ` Laurent Vivier
2023-01-09 10:55     ` Michael S. Tsirkin
2023-01-11  9:50       ` Laurent Vivier
2023-01-12  5:46         ` Yajun Wu
2023-01-12  9:25         ` Maxime Coquelin
2023-01-16  7:14           ` Yajun Wu
2023-01-17  9:49             ` Maxime Coquelin
2023-01-17 12:12               ` Greg Kurz
2023-01-17 12:36                 ` Greg Kurz
2023-01-17 15:07                   ` Maxime Coquelin
2023-01-17 17:55                     ` Greg Kurz
2023-01-17 18:21                       ` Greg Kurz
2023-01-18 11:01                         ` Michael S. Tsirkin
2023-01-19 19:48                   ` Dr. David Alan Gilbert
2022-11-07 22:53 ` [PULL v4 77/83] hw/smbios: add core_count2 to smbios table type 4 Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 78/83] bios-tables-test: teach test to use smbios 3.0 tables Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 79/83] tests/acpi: allow changes for core_count2 test Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 80/83] bios-tables-test: add test for number of cores > 255 Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 81/83] tests/acpi: update tables for new core count test Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 82/83] hw/virtio: introduce virtio_device_should_start Michael S. Tsirkin
2022-11-07 22:54 ` [PULL v4 83/83] checkpatch: better pattern for inline comments Michael S. Tsirkin
2022-11-08  6:23 ` [PULL v4 00/83] pci,pc,virtio: features, tests, fixes, cleanups Michael S. Tsirkin
2022-11-08 13:47   ` Stefan Hajnoczi
2022-11-15 14:01 ` Philippe Mathieu-Daudé
2022-11-16 10:42   ` Igor Mammedov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221109054049-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=kangjie.xu@linux.alibaba.com \
    --cc=kraxel@redhat.com \
    --cc=lersek@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).