mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 08:34:07 +02:00
Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers
When device is behind the IOMMU, driver is require to pass the device address of virtio request, response and any memory referenced by those request/response to the bus master. The patch uses IOMMU-like member functions from VIRTIO_DEVICE_PROTOCOL to map request and response buffers system physical address to the device address. - If the buffer need to be accessed by both the processor and a bus master then map with BusMasterCommonBuffer. - If the buffer need to be accessed for a write operation by a bus master then map with BusMasterWrite. - If the buffer need to be accessed for a read operation by a bus master then map with BusMasterRead. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
1916513047
commit
3540f2cef5
@ -232,7 +232,8 @@ VerifyReadWriteRequest (
|
|||||||
|
|
||||||
@retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
|
@retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
|
||||||
unable to parse host response, or host response
|
unable to parse host response, or host response
|
||||||
is not VIRTIO_BLK_S_OK.
|
is not VIRTIO_BLK_S_OK or failed to map Buffer
|
||||||
|
for a bus master operation.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -249,8 +250,16 @@ SynchronousRequest (
|
|||||||
{
|
{
|
||||||
UINT32 BlockSize;
|
UINT32 BlockSize;
|
||||||
volatile VIRTIO_BLK_REQ Request;
|
volatile VIRTIO_BLK_REQ Request;
|
||||||
volatile UINT8 HostStatus;
|
volatile UINT8 *HostStatus;
|
||||||
|
VOID *HostStatusBuffer;
|
||||||
DESC_INDICES Indices;
|
DESC_INDICES Indices;
|
||||||
|
VOID *RequestMapping;
|
||||||
|
VOID *StatusMapping;
|
||||||
|
VOID *BufferMapping;
|
||||||
|
EFI_PHYSICAL_ADDRESS BufferDeviceAddress;
|
||||||
|
EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress;
|
||||||
|
EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
BlockSize = Dev->BlockIoMedia.BlockSize;
|
BlockSize = Dev->BlockIoMedia.BlockSize;
|
||||||
|
|
||||||
@ -275,12 +284,82 @@ SynchronousRequest (
|
|||||||
Request.IoPrio = 0;
|
Request.IoPrio = 0;
|
||||||
Request.Sector = MultU64x32(Lba, BlockSize / 512);
|
Request.Sector = MultU64x32(Lba, BlockSize / 512);
|
||||||
|
|
||||||
VirtioPrepare (&Dev->Ring, &Indices);
|
//
|
||||||
|
// Host status is bi-directional (we preset with a value and expect the
|
||||||
|
// device to update it). Allocate a host status buffer which can be mapped
|
||||||
|
// to access equally by both processor and the device.
|
||||||
|
//
|
||||||
|
Status = Dev->VirtIo->AllocateSharedPages (
|
||||||
|
Dev->VirtIo,
|
||||||
|
EFI_SIZE_TO_PAGES (sizeof *HostStatus),
|
||||||
|
&HostStatusBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostStatus = HostStatusBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Map virtio-blk request header (must be done after request header is
|
||||||
|
// populated)
|
||||||
|
//
|
||||||
|
Status = VirtioMapAllBytesInSharedBuffer (
|
||||||
|
Dev->VirtIo,
|
||||||
|
VirtioOperationBusMasterRead,
|
||||||
|
(VOID *) &Request,
|
||||||
|
sizeof Request,
|
||||||
|
&RequestDeviceAddress,
|
||||||
|
&RequestMapping
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_DEVICE_ERROR;
|
||||||
|
goto FreeHostStatusBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Map data buffer
|
||||||
|
//
|
||||||
|
if (BufferSize > 0) {
|
||||||
|
Status = VirtioMapAllBytesInSharedBuffer (
|
||||||
|
Dev->VirtIo,
|
||||||
|
(RequestIsWrite ?
|
||||||
|
VirtioOperationBusMasterRead :
|
||||||
|
VirtioOperationBusMasterWrite),
|
||||||
|
(VOID *) Buffer,
|
||||||
|
BufferSize,
|
||||||
|
&BufferDeviceAddress,
|
||||||
|
&BufferMapping
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_DEVICE_ERROR;
|
||||||
|
goto UnmapRequestBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// preset a host status for ourselves that we do not accept as success
|
// preset a host status for ourselves that we do not accept as success
|
||||||
//
|
//
|
||||||
HostStatus = VIRTIO_BLK_S_IOERR;
|
*HostStatus = VIRTIO_BLK_S_IOERR;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
|
||||||
|
// both processor and device can access it.
|
||||||
|
//
|
||||||
|
Status = VirtioMapAllBytesInSharedBuffer (
|
||||||
|
Dev->VirtIo,
|
||||||
|
VirtioOperationBusMasterCommonBuffer,
|
||||||
|
HostStatusBuffer,
|
||||||
|
sizeof *HostStatus,
|
||||||
|
&HostStatusDeviceAddress,
|
||||||
|
&StatusMapping
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_DEVICE_ERROR;
|
||||||
|
goto UnmapDataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtioPrepare (&Dev->Ring, &Indices);
|
||||||
|
|
||||||
//
|
//
|
||||||
// ensured by VirtioBlkInit() -- this predicate, in combination with the
|
// ensured by VirtioBlkInit() -- this predicate, in combination with the
|
||||||
@ -291,8 +370,13 @@ SynchronousRequest (
|
|||||||
//
|
//
|
||||||
// virtio-blk header in first desc
|
// virtio-blk header in first desc
|
||||||
//
|
//
|
||||||
VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
|
VirtioAppendDesc (
|
||||||
VRING_DESC_F_NEXT, &Indices);
|
&Dev->Ring,
|
||||||
|
RequestDeviceAddress,
|
||||||
|
sizeof Request,
|
||||||
|
VRING_DESC_F_NEXT,
|
||||||
|
&Indices
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// data buffer for read/write in second desc
|
// data buffer for read/write in second desc
|
||||||
@ -311,27 +395,55 @@ SynchronousRequest (
|
|||||||
//
|
//
|
||||||
// VRING_DESC_F_WRITE is interpreted from the host's point of view.
|
// VRING_DESC_F_WRITE is interpreted from the host's point of view.
|
||||||
//
|
//
|
||||||
VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
|
VirtioAppendDesc (
|
||||||
|
&Dev->Ring,
|
||||||
|
BufferDeviceAddress,
|
||||||
|
(UINT32) BufferSize,
|
||||||
VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
|
VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
|
||||||
&Indices);
|
&Indices
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// host status in last (second or third) desc
|
// host status in last (second or third) desc
|
||||||
//
|
//
|
||||||
VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
|
VirtioAppendDesc (
|
||||||
VRING_DESC_F_WRITE, &Indices);
|
&Dev->Ring,
|
||||||
|
HostStatusDeviceAddress,
|
||||||
|
sizeof *HostStatus,
|
||||||
|
VRING_DESC_F_WRITE,
|
||||||
|
&Indices
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
|
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
|
||||||
//
|
//
|
||||||
if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
|
if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
|
||||||
NULL) == EFI_SUCCESS &&
|
NULL) == EFI_SUCCESS &&
|
||||||
HostStatus == VIRTIO_BLK_S_OK) {
|
*HostStatus == VIRTIO_BLK_S_OK) {
|
||||||
return EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
} else {
|
||||||
|
Status = EFI_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_DEVICE_ERROR;
|
Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);
|
||||||
|
|
||||||
|
UnmapDataBuffer:
|
||||||
|
if (BufferSize > 0) {
|
||||||
|
Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmapRequestBuffer:
|
||||||
|
Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
|
||||||
|
|
||||||
|
FreeHostStatusBuffer:
|
||||||
|
Dev->VirtIo->FreeSharedPages (
|
||||||
|
Dev->VirtIo,
|
||||||
|
EFI_SIZE_TO_PAGES (sizeof *HostStatus),
|
||||||
|
HostStatusBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user