]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: VirtioFlush(): return the number of bytes written by the host
authorLaszlo Ersek <lersek@redhat.com>
Fri, 19 Feb 2016 17:15:07 +0000 (18:15 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 24 Feb 2016 11:07:32 +0000 (12:07 +0100)
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: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
OvmfPkg/Include/Library/VirtioLib.h
OvmfPkg/Library/VirtioLib/VirtioLib.c
OvmfPkg/VirtioBlkDxe/VirtioBlk.c
OvmfPkg/VirtioScsiDxe/VirtioScsi.c

index 36527a523f28814b4e0ce0c0b5f53f12ca7da3d9..decd4418af3d997739e8f39fef3c32fa2bc23759 100644 (file)
@@ -2,7 +2,7 @@
 \r
   Declarations of utility functions used by virtio device drivers.\r
 \r
-  Copyright (C) 2012, Red Hat, Inc.\r
+  Copyright (C) 2012-2016, Red Hat, Inc.\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
@@ -167,6 +167,12 @@ VirtioAppendDesc (
                           Indices->HeadDescIdx identifies the head descriptor\r
                           of the descriptor chain.\r
 \r
+  @param[out] UsedLen     On success, the total number of bytes, consecutively\r
+                          across the buffers linked by the descriptor chain,\r
+                          that the host wrote. May be NULL if the caller\r
+                          doesn't care, or can compute the same information\r
+                          from device-specific request structures linked by the\r
+                          descriptor chain.\r
 \r
   @return              Error code from VirtIo->SetQueueNotify() if it fails.\r
 \r
@@ -179,7 +185,8 @@ VirtioFlush (
   IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
   IN     UINT16                 VirtQueueId,\r
   IN OUT VRING                  *Ring,\r
-  IN     DESC_INDICES           *Indices\r
+  IN     DESC_INDICES           *Indices,\r
+  OUT    UINT32                 *UsedLen    OPTIONAL\r
   );\r
 \r
 #endif // _VIRTIO_LIB_H_\r
index 54cf225c9885d666944f14718f67fa127e2927f4..4b1d78b5a03eb45a808b8e09ef89561d8082e468 100644 (file)
@@ -2,7 +2,7 @@
 \r
   Utility functions used by virtio device drivers.\r
 \r
-  Copyright (C) 2012, Red Hat, Inc.\r
+  Copyright (C) 2012-2016, Red Hat, Inc.\r
   Portion of Copyright (C) 2013, ARM Ltd.\r
 \r
   This program and the accompanying materials are licensed and made available\r
@@ -249,6 +249,12 @@ VirtioAppendDesc (
                           Indices->HeadDescIdx identifies the head descriptor\r
                           of the descriptor chain.\r
 \r
+  @param[out] UsedLen     On success, the total number of bytes, consecutively\r
+                          across the buffers linked by the descriptor chain,\r
+                          that the host wrote. May be NULL if the caller\r
+                          doesn't care, or can compute the same information\r
+                          from device-specific request structures linked by the\r
+                          descriptor chain.\r
 \r
   @return              Error code from VirtIo->SetQueueNotify() if it fails.\r
 \r
@@ -261,10 +267,12 @@ VirtioFlush (
   IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
   IN     UINT16                 VirtQueueId,\r
   IN OUT VRING                  *Ring,\r
-  IN     DESC_INDICES           *Indices\r
+  IN     DESC_INDICES           *Indices,\r
+  OUT    UINT32                 *UsedLen    OPTIONAL\r
   )\r
 {\r
   UINT16     NextAvailIdx;\r
+  UINT16     LastUsedIdx;\r
   EFI_STATUS Status;\r
   UINTN      PollPeriodUsecs;\r
 \r
@@ -276,6 +284,11 @@ VirtioFlush (
   // head descriptor of any given descriptor chain.\r
   //\r
   NextAvailIdx = *Ring->Avail.Idx;\r
+  //\r
+  // (Due to our lock-step progress, this is where the host will produce the\r
+  // used element with the head descriptor's index in it.)\r
+  //\r
+  LastUsedIdx = NextAvailIdx;\r
   Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] =\r
     Indices->HeadDescIdx % Ring->QueueSize;\r
 \r
@@ -315,5 +328,14 @@ VirtioFlush (
   }\r
 \r
   MemoryFence();\r
+\r
+  if (UsedLen != NULL) {\r
+    volatile CONST VRING_USED_ELEM *UsedElem;\r
+\r
+    UsedElem = &Ring->Used.UsedElem[LastUsedIdx % Ring->QueueSize];\r
+    ASSERT (UsedElem->Id == Indices->HeadDescIdx);\r
+    *UsedLen = UsedElem->Len;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
index 75f85ca6e09ad01fdadf8bc3245596c8cac45873..50511a1e446bb2d2433b20238cf42a13468eed4b 100644 (file)
@@ -324,7 +324,8 @@ SynchronousRequest (
   //\r
   // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
   //\r
-  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
+  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,\r
+        NULL) == EFI_SUCCESS &&\r
       HostStatus == VIRTIO_BLK_S_OK) {\r
     return EFI_SUCCESS;\r
   }\r
index e1e12039b3591b0ecfce21c63e849b89d7b8ae11..f5f412a32e9b8909a4d40e029c76bb177ae90b11 100644 (file)
@@ -470,7 +470,7 @@ VirtioScsiPassThru (
   // caller retry.\r
   //\r
   if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
-        &Indices) != EFI_SUCCESS) {\r
+        &Indices, NULL) != EFI_SUCCESS) {\r
     Packet->InTransferLength  = 0;\r
     Packet->OutTransferLength = 0;\r
     Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r