From 263559b87232826552c9e42c1652d9f9488c9870 Mon Sep 17 00:00:00 2001 From: jljusten Date: Fri, 12 Oct 2012 18:53:58 +0000 Subject: OvmfPkg: extract VirtioLib from VirtioBlkDxe Introduce a new library called VirtioLib, for now only collecting the following reusable functions with as little changes as possible: - VirtioWrite() - VirtioRead() - VirtioRingInit() - VirtioRingUninit() - AppendDesc() Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek Reviewed-by: Jordan Justen git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13842 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/Include/Library/VirtioLib.h | 187 ++++++++++++++++++ OvmfPkg/Library/VirtioLib/VirtioLib.c | 335 ++++++++++++++++++++++++++++++++ OvmfPkg/Library/VirtioLib/VirtioLib.inf | 34 ++++ OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 320 +----------------------------- OvmfPkg/VirtioBlkDxe/VirtioBlk.inf | 1 + 8 files changed, 561 insertions(+), 319 deletions(-) create mode 100644 OvmfPkg/Include/Library/VirtioLib.h create mode 100644 OvmfPkg/Library/VirtioLib/VirtioLib.c create mode 100644 OvmfPkg/Library/VirtioLib/VirtioLib.inf diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h new file mode 100644 index 0000000000..95657a7111 --- /dev/null +++ b/OvmfPkg/Include/Library/VirtioLib.h @@ -0,0 +1,187 @@ +/** @file + + Declarations of utility functions used by virtio device drivers. + + Copyright (C) 2012, 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 + 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. + +**/ + +#ifndef _VIRTIO_LIB_H_ +#define _VIRTIO_LIB_H_ + +#include +#include + +/** + + Write a word into Region 0 of the device specified by PciIo. + + Region 0 must be an iomem region. This is an internal function for the + driver-specific VIRTIO_CFG_WRITE() macros. + + @param[in] PciIo Target PCI device. + + @param[in] FieldOffset Destination offset. + + @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }. + + @param[in] Value Little endian value to write, converted to UINT64. + The least significant FieldSize bytes will be used. + + + @return Status code returned by PciIo->Io.Write(). + +**/ +EFIAPI +EFI_STATUS +VirtioWrite ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value + ); + + +/** + + Read a word from Region 0 of the device specified by PciIo. + + Region 0 must be an iomem region. This is an internal function for the + driver-specific VIRTIO_CFG_READ() macros. + + @param[in] PciIo Source PCI device. + + @param[in] FieldOffset Source offset. + + @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }. + + @param[in] BufferSize Number of bytes available in the target buffer. Must + equal FieldSize. + + @param[out] Buffer Target buffer. + + + @return Status code returned by PciIo->Io.Read(). + +**/ +EFIAPI +EFI_STATUS +VirtioRead ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + + +/** + + 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 + ); + + +/** + + 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 + ); + + +/** + + Append a contiguous buffer for transmission / reception via the virtio ring. + + This function implements the following sections 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 + request submission. It is the calling driver's responsibility to verify the + ring size in advance. + + @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] 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. + +**/ +VOID +EFIAPI +AppendDesc ( + IN OUT VRING *Ring, + IN UINTN BufferPhysAddr, + IN UINT32 BufferSize, + IN UINT16 Flags, + IN UINT16 HeadIdx, + IN OUT UINT16 *NextAvailIdx + ); + +#endif // _VIRTIO_LIB_H_ diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c new file mode 100644 index 0000000000..580824261c --- /dev/null +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c @@ -0,0 +1,335 @@ +/** @file + + Utility functions used by virtio device drivers. + + Copyright (C) 2012, 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 + 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 +#include +#include +#include + +#include + + +/** + + Write a word into Region 0 of the device specified by PciIo. + + Region 0 must be an iomem region. This is an internal function for the + driver-specific VIRTIO_CFG_WRITE() macros. + + @param[in] PciIo Target PCI device. + + @param[in] FieldOffset Destination offset. + + @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }. + + @param[in] Value Little endian value to write, converted to UINT64. + The least significant FieldSize bytes will be used. + + + @return Status code returned by PciIo->Io.Write(). + +**/ +EFIAPI +EFI_STATUS +VirtioWrite ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value + ) +{ + UINTN Count; + EFI_PCI_IO_PROTOCOL_WIDTH Width; + + Count = 1; + switch (FieldSize) { + case 1: + Width = EfiPciIoWidthUint8; + break; + + case 2: + Width = EfiPciIoWidthUint16; + break; + + case 8: + Count = 2; + // fall through + + case 4: + Width = EfiPciIoWidthUint32; + break; + + default: + ASSERT (FALSE); + } + + return PciIo->Io.Write ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + &Value + ); +} + + +/** + + Read a word from Region 0 of the device specified by PciIo. + + Region 0 must be an iomem region. This is an internal function for the + driver-specific VIRTIO_CFG_READ() macros. + + @param[in] PciIo Source PCI device. + + @param[in] FieldOffset Source offset. + + @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }. + + @param[in] BufferSize Number of bytes available in the target buffer. Must + equal FieldSize. + + @param[out] Buffer Target buffer. + + + @return Status code returned by PciIo->Io.Read(). + +**/ +EFIAPI +EFI_STATUS +VirtioRead ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + UINTN Count; + EFI_PCI_IO_PROTOCOL_WIDTH Width; + + ASSERT (FieldSize == BufferSize); + + Count = 1; + switch (FieldSize) { + case 1: + Width = EfiPciIoWidthUint8; + break; + + case 2: + Width = EfiPciIoWidthUint16; + break; + + case 8: + Count = 2; + // fall through + + case 4: + Width = EfiPciIoWidthUint32; + break; + + default: + ASSERT (FALSE); + } + + return PciIo->Io.Read ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + Buffer + ); +} + + +/** + + 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); +} + + +/** + + Append a contiguous buffer for transmission / reception via the virtio ring. + + This function implements the following sections 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 + request submission. It is the calling driver's responsibility to verify the + ring size in advance. + + @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] 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. + +**/ +VOID +EFIAPI +AppendDesc ( + IN OUT VRING *Ring, + IN UINTN BufferPhysAddr, + IN UINT32 BufferSize, + IN UINT16 Flags, + IN UINT16 HeadIdx, + IN OUT UINT16 *NextAvailIdx + ) +{ + volatile VRING_DESC *Desc; + + Desc = &Ring->Desc[*NextAvailIdx % Ring->QueueSize]; + Desc->Addr = BufferPhysAddr; + Desc->Len = BufferSize; + Desc->Flags = Flags; + Ring->Avail.Ring[(*NextAvailIdx)++ % Ring->QueueSize] = + HeadIdx % Ring->QueueSize; + Desc->Next = *NextAvailIdx % Ring->QueueSize; +} diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.inf b/OvmfPkg/Library/VirtioLib/VirtioLib.inf new file mode 100644 index 0000000000..cfd93a2c2c --- /dev/null +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.inf @@ -0,0 +1,34 @@ +## @file +# Library of virtio utility functions. +# +# Copyright (C) 2012, 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 +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VirtioLib + FILE_GUID = 90CED1D9-18F2-47CC-BF24-41EC29406637 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = VirtioLib + +[Sources] + VirtioLib.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 16037b3772..d0c632979d 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -97,6 +97,7 @@ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index f73f079d07..b442314680 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -102,6 +102,7 @@ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 97d4ec8a93..11f90a4818 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -102,6 +102,7 @@ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index ead98272a5..eeeb4bef6e 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -29,146 +29,10 @@ #include #include #include +#include #include "VirtioBlk.h" -/** - - Write a word into Region 0 of the device specified by PciIo. - - Region 0 must be an iomem region. This is an internal function for the - VIRTIO_CFG_WRITE() macro below. - - @param[in] PciIo Target PCI device. - - @param[in] FieldOffset Destination offset. - - @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }. - - @param[in] Value Little endian value to write, converted to UINT64. - The least significant FieldSize bytes will be used. - - - @return Status code returned by PciIo->Io.Write(). - -**/ -STATIC -EFIAPI -EFI_STATUS -VirtioWrite ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINT64 Value - ) -{ - UINTN Count; - EFI_PCI_IO_PROTOCOL_WIDTH Width; - - Count = 1; - switch (FieldSize) { - case 1: - Width = EfiPciIoWidthUint8; - break; - - case 2: - Width = EfiPciIoWidthUint16; - break; - - case 8: - Count = 2; - // fall through - - case 4: - Width = EfiPciIoWidthUint32; - break; - - default: - ASSERT (FALSE); - } - - return PciIo->Io.Write ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - &Value - ); -} - - -/** - - Read a word from Region 0 of the device specified by PciIo. - - Region 0 must be an iomem region. This is an internal function for the - VIRTIO_CFG_READ() macro below. - - @param[in] PciIo Source PCI device. - - @param[in] FieldOffset Source offset. - - @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }. - - @param[in] BufferSize Number of bytes available in the target buffer. Must - equal FieldSize. - - @param[out] Buffer Target buffer. - - - @return Status code returned by PciIo->Io.Read(). - -**/ -STATIC -EFIAPI -EFI_STATUS -VirtioRead ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - UINTN Count; - EFI_PCI_IO_PROTOCOL_WIDTH Width; - - ASSERT (FieldSize == BufferSize); - - Count = 1; - switch (FieldSize) { - case 1: - Width = EfiPciIoWidthUint8; - break; - - case 2: - Width = EfiPciIoWidthUint16; - break; - - case 8: - Count = 2; - // fall through - - case 4: - Width = EfiPciIoWidthUint32; - break; - - default: - ASSERT (FALSE); - } - - return PciIo->Io.Read ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - Buffer - ); -} - - /** Convenience macros to read and write region 0 IO space elements of the @@ -314,66 +178,6 @@ VerifyReadWriteRequest ( } -/** - - Append a contiguous buffer for transmission / reception via the virtio ring. - - This function implements the following sections 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 this driver supports only synchronous - requests and host side status is processed in lock-step with request - submission. VirtioBlkInit() verifies the ring size in advance. - - @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] 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. - -**/ - -STATIC -VOID -EFIAPI -AppendDesc ( - IN OUT VRING *Ring, - IN UINTN BufferPhysAddr, - IN UINT32 BufferSize, - IN UINT16 Flags, - IN UINT16 HeadIdx, - IN OUT UINT16 *NextAvailIdx - ) -{ - volatile VRING_DESC *Desc; - - Desc = &Ring->Desc[*NextAvailIdx % Ring->QueueSize]; - Desc->Addr = BufferPhysAddr; - Desc->Len = BufferSize; - Desc->Flags = Flags; - Ring->Avail.Ring[(*NextAvailIdx)++ % Ring->QueueSize] = - HeadIdx % Ring->QueueSize; - Desc->Next = *NextAvailIdx % Ring->QueueSize; -} /** @@ -825,128 +629,6 @@ VirtioBlkDriverBindingSupported ( } -/** - - 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. - -**/ - -STATIC -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. - -**/ - - -STATIC -VOID -EFIAPI -VirtioRingUninit ( - IN OUT VRING *Ring - ) -{ - FreePages (Ring->Base, Ring->NumPages); - SetMem (Ring, sizeof *Ring, 0x00); -} - - /** Set up all BlockIo and virtio-blk aspects of this driver for the specified diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf index 730903d55e..6dffc3a22a 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf @@ -35,6 +35,7 @@ UefiBootServicesTableLib UefiDriverEntryPoint UefiLib + VirtioLib [Protocols] gEfiBlockIoProtocolGuid ## BY_START -- cgit v1.2.3