summaryrefslogtreecommitdiff
path: root/OvmfPkg/Library/VirtioLib/VirtioLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/Library/VirtioLib/VirtioLib.c')
-rw-r--r--OvmfPkg/Library/VirtioLib/VirtioLib.c319
1 files changed, 0 insertions, 319 deletions
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
deleted file mode 100644
index 54cf225c98..0000000000
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/** @file
-
- Utility functions used by virtio device drivers.
-
- Copyright (C) 2012, Red Hat, Inc.
- Portion of Copyright (C) 2013, ARM Ltd.
-
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License which accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-
-#include <Library/VirtioLib.h>
-
-
-/**
-
- Configure a virtio ring.
-
- This function sets up internal storage (the guest-host communication area)
- and lays out several "navigation" (ie. no-ownership) pointers to parts of
- that storage.
-
- Relevant sections from the virtio-0.9.5 spec:
- - 1.1 Virtqueues,
- - 2.3 Virtqueue Configuration.
-
- @param[in] The number of descriptors to allocate for the
- virtio ring, as requested by the host.
-
- @param[out] Ring The virtio ring to set up.
-
- @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
- pages for the requested QueueSize. Fields of
- Ring have indeterminate value.
-
- @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
- (and nothing else) is responsible for
- deallocation.
-
-**/
-EFI_STATUS
-EFIAPI
-VirtioRingInit (
- IN UINT16 QueueSize,
- OUT VRING *Ring
- )
-{
- UINTN RingSize;
- volatile UINT8 *RingPagesPtr;
-
- RingSize = ALIGN_VALUE (
- sizeof *Ring->Desc * QueueSize +
- sizeof *Ring->Avail.Flags +
- sizeof *Ring->Avail.Idx +
- sizeof *Ring->Avail.Ring * QueueSize +
- sizeof *Ring->Avail.UsedEvent,
- EFI_PAGE_SIZE);
-
- RingSize += ALIGN_VALUE (
- sizeof *Ring->Used.Flags +
- sizeof *Ring->Used.Idx +
- sizeof *Ring->Used.UsedElem * QueueSize +
- sizeof *Ring->Used.AvailEvent,
- EFI_PAGE_SIZE);
-
- Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
- Ring->Base = AllocatePages (Ring->NumPages);
- if (Ring->Base == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- SetMem (Ring->Base, RingSize, 0x00);
- RingPagesPtr = Ring->Base;
-
- Ring->Desc = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Desc * QueueSize;
-
- Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Flags;
-
- Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Idx;
-
- Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;
-
- Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Avail.UsedEvent;
-
- RingPagesPtr = (volatile UINT8 *) Ring->Base +
- ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,
- EFI_PAGE_SIZE);
-
- Ring->Used.Flags = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.Flags;
-
- Ring->Used.Idx = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.Idx;
-
- Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;
-
- Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;
- RingPagesPtr += sizeof *Ring->Used.AvailEvent;
-
- Ring->QueueSize = QueueSize;
- return EFI_SUCCESS;
-}
-
-
-/**
-
- Tear down the internal resources of a configured virtio ring.
-
- The caller is responsible to stop the host from using this ring before
- invoking this function: the VSTAT_DRIVER_OK bit must be clear in
- VhdrDeviceStatus.
-
- @param[out] Ring The virtio ring to clean up.
-
-**/
-VOID
-EFIAPI
-VirtioRingUninit (
- IN OUT VRING *Ring
- )
-{
- FreePages (Ring->Base, Ring->NumPages);
- SetMem (Ring, sizeof *Ring, 0x00);
-}
-
-
-/**
-
- Turn off interrupt notifications from the host, and prepare for appending
- multiple descriptors to the virtio ring.
-
- The calling driver must be in VSTAT_DRIVER_OK state.
-
- @param[in,out] Ring The virtio ring we intend to append descriptors to.
-
- @param[out] Indices The DESC_INDICES structure to initialize.
-
-**/
-VOID
-EFIAPI
-VirtioPrepare (
- IN OUT VRING *Ring,
- OUT DESC_INDICES *Indices
- )
-{
- //
- // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.
- // We're going to poll the answer, the host should not send an interrupt.
- //
- *Ring->Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;
-
- //
- // Prepare for virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.
- //
- // 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;
-}
-
-
-/**
-
- Append a contiguous buffer for transmission / reception via the virtio ring.
-
- This function implements the following section from virtio-0.9.5:
- - 2.4.1.1 Placing Buffers into the Descriptor Table
-
- Free space is taken as granted, since the individual drivers support only
- synchronous requests and host side status is processed in lock-step with
- request submission. It is the calling driver's responsibility to verify the
- ring size in advance.
-
- The caller is responsible for initializing *Indices with VirtioPrepare()
- first.
-
- @param[in,out] Ring The virtio ring to append the buffer to, as a
- descriptor.
-
- @param[in] BufferPhysAddr (Guest pseudo-physical) start address of the
- transmit / receive buffer.
-
- @param[in] BufferSize Number of bytes to transmit or receive.
-
- @param[in] Flags A bitmask of VRING_DESC_F_* flags. The caller
- computes this mask dependent on further buffers to
- append and transfer direction.
- VRING_DESC_F_INDIRECT is unsupported. The
- VRING_DESC.Next field is always set, but the host
- only interprets it dependent on VRING_DESC_F_NEXT.
-
- @param[in,out] Indices Indices->HeadDescIdx is not accessed.
- On input, Indices->NextDescIdx identifies the next
- descriptor to carry the buffer. On output,
- Indices->NextDescIdx is incremented by one, modulo
- 2^16.
-
-**/
-VOID
-EFIAPI
-VirtioAppendDesc (
- IN OUT VRING *Ring,
- IN UINTN BufferPhysAddr,
- IN UINT32 BufferSize,
- IN UINT16 Flags,
- IN OUT DESC_INDICES *Indices
- )
-{
- volatile VRING_DESC *Desc;
-
- Desc = &Ring->Desc[Indices->NextDescIdx++ % Ring->QueueSize];
- Desc->Addr = BufferPhysAddr;
- Desc->Len = BufferSize;
- Desc->Flags = Flags;
- Desc->Next = Indices->NextDescIdx % Ring->QueueSize;
-}
-
-
-/**
-
- Notify the host about the descriptor chain just built, and wait until the
- host processes it.
-
- @param[in] VirtIo The target virtio device to notify.
-
- @param[in] VirtQueueId Identifies the queue for the target device.
-
- @param[in,out] Ring The virtio ring with descriptors to submit.
-
- @param[in] Indices Indices->NextDescIdx is not accessed.
- Indices->HeadDescIdx identifies the head descriptor
- of the descriptor chain.
-
-
- @return Error code from VirtIo->SetQueueNotify() if it fails.
-
- @retval EFI_SUCCESS Otherwise, the host processed all descriptors.
-
-**/
-EFI_STATUS
-EFIAPI
-VirtioFlush (
- IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
- IN UINT16 VirtQueueId,
- IN OUT VRING *Ring,
- 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 = NextAvailIdx;
-
- //
- // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are
- // OK.
- //
- MemoryFence();
- Status = VirtIo->SetQueueNotify (VirtIo, VirtQueueId);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
- // Wait until the host processes and acknowledges our descriptor chain. The
- // condition we use for polling is greatly simplified and relies on the
- // synchronous, lock-step progress.
- //
- // Keep slowing down until we reach a poll period of slightly above 1 ms.
- //
- PollPeriodUsecs = 1;
- MemoryFence();
- while (*Ring->Used.Idx != NextAvailIdx) {
- gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay
-
- if (PollPeriodUsecs < 1024) {
- PollPeriodUsecs *= 2;
- }
- MemoryFence();
- }
-
- MemoryFence();
- return EFI_SUCCESS;
-}