diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h index 448dd2b578..3bebd9f2f4 100644 --- a/OvmfPkg/Include/Library/VirtioLib.h +++ b/OvmfPkg/Include/Library/VirtioLib.h @@ -140,8 +140,8 @@ VirtioRingUninit ( // request. // typedef struct { - UINT16 HeadIdx; - UINT16 NextAvailIdx; + UINT16 HeadDescIdx; + UINT16 NextDescIdx; } DESC_INDICES; @@ -169,9 +169,8 @@ VirtioPrepare ( Append a contiguous buffer for transmission / reception via the virtio ring. - This function implements the following sections from virtio-0.9.5: + This function implements the following section from virtio-0.9.5: - 2.4.1.1 Placing Buffers into the Descriptor Table - - 2.4.1.2 Updating the Available Ring Free space is taken as granted, since the individual drivers support only synchronous requests and host side status is processed in lock-step with @@ -199,13 +198,9 @@ VirtioPrepare ( In *Indices: - @param [in] HeadIdx The index identifying the head buffer (first - buffer appended) belonging to this same - request. - - @param [in out] NextAvailIdx On input, the index identifying the next - descriptor available to carry the buffer. On - output, incremented by one, modulo 2^16. + @param [in out] NextDescIdx On input, the index identifying the next + descriptor to carry the buffer. On output, + incremented by one, modulo 2^16. **/ VOID @@ -221,8 +216,8 @@ VirtioAppendDesc ( /** - Notify the host about appended descriptors and wait until it processes the - last one (ie. all of them). + Notify the host about the descriptor chain just built, and wait until the + host processes it. @param[in] PciIo The target virtio PCI device to notify. @@ -230,8 +225,10 @@ VirtioAppendDesc ( @param[in out] Ring The virtio ring with descriptors to submit. - @param[in] Indices The function waits until the host processes - descriptors up to Indices->NextAvailIdx. + In *Indices: + + @param[in] HeadDescIdx Identifies the head descriptor of the descriptor + chain. @return Error code from VirtioWrite() if it fails. diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c index 8398c9db4c..db619eee15 100644 --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c @@ -306,8 +306,11 @@ VirtioPrepare ( // // Prepare for virtio-0.9.5, 2.4.1 Supplying Buffers to the Device. // - Indices->HeadIdx = *Ring->Avail.Idx; - Indices->NextAvailIdx = Indices->HeadIdx; + // Since we support only one in-flight descriptor chain, we can always build + // that chain starting at entry #0 of the descriptor table. + // + Indices->HeadDescIdx = 0; + Indices->NextDescIdx = Indices->HeadDescIdx; } @@ -315,9 +318,8 @@ VirtioPrepare ( Append a contiguous buffer for transmission / reception via the virtio ring. - This function implements the following sections from virtio-0.9.5: + This function implements the following section from virtio-0.9.5: - 2.4.1.1 Placing Buffers into the Descriptor Table - - 2.4.1.2 Updating the Available Ring Free space is taken as granted, since the individual drivers support only synchronous requests and host side status is processed in lock-step with @@ -345,13 +347,9 @@ VirtioPrepare ( In *Indices: - @param [in] HeadIdx The index identifying the head buffer (first - buffer appended) belonging to this same - request. - - @param [in out] NextAvailIdx On input, the index identifying the next - descriptor available to carry the buffer. On - output, incremented by one, modulo 2^16. + @param [in out] NextDescIdx On input, the index identifying the next + descriptor to carry the buffer. On output, + incremented by one, modulo 2^16. **/ VOID @@ -366,20 +364,18 @@ VirtioAppendDesc ( { volatile VRING_DESC *Desc; - Desc = &Ring->Desc[Indices->NextAvailIdx % Ring->QueueSize]; + Desc = &Ring->Desc[Indices->NextDescIdx++ % Ring->QueueSize]; Desc->Addr = BufferPhysAddr; Desc->Len = BufferSize; Desc->Flags = Flags; - Ring->Avail.Ring[Indices->NextAvailIdx++ % Ring->QueueSize] = - Indices->HeadIdx % Ring->QueueSize; - Desc->Next = Indices->NextAvailIdx % Ring->QueueSize; + Desc->Next = Indices->NextDescIdx % Ring->QueueSize; } /** - Notify the host about appended descriptors and wait until it processes the - last one (ie. all of them). + Notify the host about the descriptor chain just built, and wait until the + host processes it. @param[in] PciIo The target virtio PCI device to notify. @@ -387,8 +383,10 @@ VirtioAppendDesc ( @param[in out] Ring The virtio ring with descriptors to submit. - @param[in] Indices The function waits until the host processes - descriptors up to Indices->NextAvailIdx. + In *Indices: + + @param[in] HeadDescIdx Identifies the head descriptor of the descriptor + chain. @return Error code from VirtioWrite() if it fails. @@ -405,14 +403,26 @@ VirtioFlush ( IN DESC_INDICES *Indices ) { + UINT16 NextAvailIdx; EFI_STATUS Status; UINTN PollPeriodUsecs; + // + // virtio-0.9.5, 2.4.1.2 Updating the Available Ring + // + // It is not exactly clear from the wording of the virtio-0.9.5 + // specification, but each entry in the Available Ring references only the + // head descriptor of any given descriptor chain. + // + NextAvailIdx = *Ring->Avail.Idx; + Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] = + Indices->HeadDescIdx % Ring->QueueSize; + // // virtio-0.9.5, 2.4.1.3 Updating the Index Field // MemoryFence(); - *Ring->Avail.Idx = Indices->NextAvailIdx; + *Ring->Avail.Idx = NextAvailIdx; // // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are @@ -439,7 +449,7 @@ VirtioFlush ( // PollPeriodUsecs = 1; MemoryFence(); - while (*Ring->Used.Idx != Indices->NextAvailIdx) { + while (*Ring->Used.Idx != NextAvailIdx) { gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay if (PollPeriodUsecs < 1024) {