Reviewed-by: Jordan Justen <[email protected]>

On 2016-02-19 09:15:07, Laszlo Ersek wrote:
> VirtioLib provides an API for simple, synchronous (request/response-style)
> virtio communication. The guest driver builds one descriptor chain, link
> for link, with VirtioPrepare() and VirtioAppendDesc(), then submits the
> chain, and awaits the processing, with VirtioFlush().
> 
> The descriptor chain is always built at the beginning of the descriptor
> area, with the head descriptor having descriptor index 0.
> 
> In order to submit the descriptor chain to the host, the guest always
> pushes a new "available element" to the Available Ring, in genuine
> queue-like fashion, with the new element referencing the head descriptor
> (which always has index 0, see above).
> 
> In turn, after processing, the host always pushes a new "used element" to
> the Used Ring, in genuine queue-like fashion, with the new element
> referencing the head descriptor of the chain that was just processed. The
> same element also reports the number of bytes that the host wrote,
> consecutively across the host-writeable buffers that were linked by the
> descriptors.
> 
> (See "OvmfPkg/VirtioNetDxe/TechNotes.txt" for a diagram about the
> descriptor area and the rings.)
> 
> Because at most one descriptor chain can be in flight with VirtioLib at
> any time,
> 
> - the Available Ring and the Used Ring proceed in lock-step,
> 
> - and the head descriptor that the new "available" and "used" elements can
>   ever reference has index 0.
> 
> Based on the above, we can modify VirtioFlush() to return the number of
> bytes written by the host across the descriptor chain. The virtio-block
> and virtio-scsi drivers don't care (they have other ways to parse the data
> produced by the host), while the virtio-net driver doesn't use
> VirtioFlush() at all (it employs VirtioLib only to set up its rings).
> 
> However, the virtio entropy device,  to be covered in the upcoming
> patches, reports the amount of randomness produced by the host only
> through this quantity.
> 
> Cc: Ard Biesheuvel <[email protected]>
> Cc: Jordan Justen <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <[email protected]>
> ---
>  OvmfPkg/Include/Library/VirtioLib.h   | 11 +++++++--
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 26 ++++++++++++++++++--
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c      |  3 ++-
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c    |  2 +-
>  4 files changed, 36 insertions(+), 6 deletions(-)
> 
> diff --git a/OvmfPkg/Include/Library/VirtioLib.h 
> b/OvmfPkg/Include/Library/VirtioLib.h
> index 36527a523f28..decd4418af3d 100644
> --- a/OvmfPkg/Include/Library/VirtioLib.h
> +++ b/OvmfPkg/Include/Library/VirtioLib.h
> @@ -2,7 +2,7 @@
>  
>    Declarations of utility functions used by virtio device drivers.
>  
> -  Copyright (C) 2012, Red Hat, Inc.
> +  Copyright (C) 2012-2016, Red Hat, Inc.
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -167,6 +167,12 @@ VirtioAppendDesc (
>                            Indices->HeadDescIdx identifies the head descriptor
>                            of the descriptor chain.
>  
> +  @param[out] UsedLen     On success, the total number of bytes, 
> consecutively
> +                          across the buffers linked by the descriptor chain,
> +                          that the host wrote. May be NULL if the caller
> +                          doesn't care, or can compute the same information
> +                          from device-specific request structures linked by 
> the
> +                          descriptor chain.
>  
>    @return              Error code from VirtIo->SetQueueNotify() if it fails.
>  
> @@ -179,7 +185,8 @@ VirtioFlush (
>    IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
>    IN     UINT16                 VirtQueueId,
>    IN OUT VRING                  *Ring,
> -  IN     DESC_INDICES           *Indices
> +  IN     DESC_INDICES           *Indices,
> +  OUT    UINT32                 *UsedLen    OPTIONAL
>    );
>  
>  #endif // _VIRTIO_LIB_H_
> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c 
> b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 54cf225c9885..4b1d78b5a03e 100644
> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> @@ -2,7 +2,7 @@
>  
>    Utility functions used by virtio device drivers.
>  
> -  Copyright (C) 2012, Red Hat, Inc.
> +  Copyright (C) 2012-2016, Red Hat, Inc.
>    Portion of Copyright (C) 2013, ARM Ltd.
>  
>    This program and the accompanying materials are licensed and made available
> @@ -249,6 +249,12 @@ VirtioAppendDesc (
>                            Indices->HeadDescIdx identifies the head descriptor
>                            of the descriptor chain.
>  
> +  @param[out] UsedLen     On success, the total number of bytes, 
> consecutively
> +                          across the buffers linked by the descriptor chain,
> +                          that the host wrote. May be NULL if the caller
> +                          doesn't care, or can compute the same information
> +                          from device-specific request structures linked by 
> the
> +                          descriptor chain.
>  
>    @return              Error code from VirtIo->SetQueueNotify() if it fails.
>  
> @@ -261,10 +267,12 @@ VirtioFlush (
>    IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
>    IN     UINT16                 VirtQueueId,
>    IN OUT VRING                  *Ring,
> -  IN     DESC_INDICES           *Indices
> +  IN     DESC_INDICES           *Indices,
> +  OUT    UINT32                 *UsedLen    OPTIONAL
>    )
>  {
>    UINT16     NextAvailIdx;
> +  UINT16     LastUsedIdx;
>    EFI_STATUS Status;
>    UINTN      PollPeriodUsecs;
>  
> @@ -276,6 +284,11 @@ VirtioFlush (
>    // head descriptor of any given descriptor chain.
>    //
>    NextAvailIdx = *Ring->Avail.Idx;
> +  //
> +  // (Due to our lock-step progress, this is where the host will produce the
> +  // used element with the head descriptor's index in it.)
> +  //
> +  LastUsedIdx = NextAvailIdx;
>    Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] =
>      Indices->HeadDescIdx % Ring->QueueSize;
>  
> @@ -315,5 +328,14 @@ VirtioFlush (
>    }
>  
>    MemoryFence();
> +
> +  if (UsedLen != NULL) {
> +    volatile CONST VRING_USED_ELEM *UsedElem;
> +
> +    UsedElem = &Ring->Used.UsedElem[LastUsedIdx % Ring->QueueSize];
> +    ASSERT (UsedElem->Id == Indices->HeadDescIdx);
> +    *UsedLen = UsedElem->Len;
> +  }
> +
>    return EFI_SUCCESS;
>  }
> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c 
> b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> index 75f85ca6e09a..50511a1e446b 100644
> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> @@ -324,7 +324,8 @@ SynchronousRequest (
>    //
>    // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
>    //
> -  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
> +  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
> +        NULL) == EFI_SUCCESS &&
>        HostStatus == VIRTIO_BLK_S_OK) {
>      return EFI_SUCCESS;
>    }
> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c 
> b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> index e1e12039b359..f5f412a32e9b 100644
> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> @@ -470,7 +470,7 @@ VirtioScsiPassThru (
>    // caller retry.
>    //
>    if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
> -        &Indices) != EFI_SUCCESS) {
> +        &Indices, NULL) != EFI_SUCCESS) {
>      Packet->InTransferLength  = 0;
>      Packet->OutTransferLength = 0;
>      Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> -- 
> 1.8.3.1
> 
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to