251 lines
6.6 KiB
Diff
251 lines
6.6 KiB
Diff
From 734457162d02f6b4d66b8eb82da0717765fceebe Mon Sep 17 00:00:00 2001
|
|
From: Adttil <2429917001@qq.com>
|
|
Date: Fri, 29 Nov 2024 09:04:13 +0800
|
|
Subject: [PATCH 3/3] VirtioBlk: split large IO according to segment_size_max
|
|
|
|
When the VirtioBlk device is initialized, the value of SegmentSizeMax
|
|
is obtained based on the feature capability. Then delivere the requests
|
|
based on the value of SegmentSizeMax.
|
|
|
|
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
|
|
---
|
|
MdePkg/Include/Protocol/BlockIo.h | 10 ++
|
|
OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 148 +++++++++++++++++++++---------
|
|
2 files changed, 117 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/MdePkg/Include/Protocol/BlockIo.h b/MdePkg/Include/Protocol/BlockIo.h
|
|
index ac9adf7a..ac5e1c2a 100644
|
|
--- a/MdePkg/Include/Protocol/BlockIo.h
|
|
+++ b/MdePkg/Include/Protocol/BlockIo.h
|
|
@@ -197,6 +197,16 @@ typedef struct {
|
|
/// granularity as a number of logical blocks.
|
|
///
|
|
UINT32 OptimalTransferLengthGranularity;
|
|
+
|
|
+ ///
|
|
+ /// Maximum size of any single segment
|
|
+ ///
|
|
+ UINT32 MaxSegmentSize;
|
|
+
|
|
+ ///
|
|
+ /// Maximum number of segments in a request
|
|
+ ///
|
|
+ UINT32 MaxSegments;
|
|
} EFI_BLOCK_IO_MEDIA;
|
|
|
|
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
|
|
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
|
|
index eed56994..6d7c7aef 100644
|
|
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
|
|
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
|
|
@@ -31,6 +31,8 @@
|
|
#define MAX_RETRY_TIMES 1000
|
|
#define DEVICE_WAIT_INTVL 1000
|
|
|
|
+#define DEFAULT_MAX_SEGMENTS 32
|
|
+
|
|
/**
|
|
|
|
Convenience macros to read and write region 0 IO space elements of the
|
|
@@ -460,6 +462,68 @@ FreeHostStatusBuffer:
|
|
return Status;
|
|
}
|
|
|
|
+STATIC
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+VirtioBlkReadWriteBlocks (
|
|
+ IN EFI_BLOCK_IO_PROTOCOL *This,
|
|
+ IN UINT32 MediaId,
|
|
+ IN EFI_LBA Lba,
|
|
+ IN UINTN BufferSize,
|
|
+ IN OUT VOID *Buffer,
|
|
+ IN BOOLEAN RequestIsWrite
|
|
+ )
|
|
+{
|
|
+ VBLK_DEV *Dev;
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 SizeMax;
|
|
+
|
|
+ if (BufferSize == 0) {
|
|
+ return EFI_SUCCESS;
|
|
+ }
|
|
+
|
|
+ Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
|
|
+ Status = VerifyReadWriteRequest (
|
|
+ &Dev->BlockIoMedia,
|
|
+ Lba,
|
|
+ BufferSize,
|
|
+ RequestIsWrite
|
|
+ );
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ SizeMax = Dev->BlockIoMedia.MaxSegmentSize;
|
|
+ while (BufferSize >= SizeMax) {
|
|
+ Status = SynchronousRequest (
|
|
+ Dev,
|
|
+ Lba,
|
|
+ SizeMax,
|
|
+ Buffer,
|
|
+ RequestIsWrite
|
|
+ );
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ Lba += SizeMax / Dev->BlockIoMedia.BlockSize;
|
|
+ BufferSize -= SizeMax;
|
|
+ Buffer = (CHAR8 *)Buffer + SizeMax;
|
|
+ }
|
|
+
|
|
+ if (BufferSize == 0) {
|
|
+ return EFI_SUCCESS;
|
|
+ }
|
|
+
|
|
+ return SynchronousRequest (
|
|
+ Dev,
|
|
+ Lba,
|
|
+ BufferSize,
|
|
+ Buffer,
|
|
+ RequestIsWrite
|
|
+ );
|
|
+}
|
|
+
|
|
/**
|
|
|
|
ReadBlocks() operation for virtio-blk.
|
|
@@ -487,30 +551,13 @@ VirtioBlkReadBlocks (
|
|
OUT VOID *Buffer
|
|
)
|
|
{
|
|
- VBLK_DEV *Dev;
|
|
- EFI_STATUS Status;
|
|
-
|
|
- if (BufferSize == 0) {
|
|
- return EFI_SUCCESS;
|
|
- }
|
|
-
|
|
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
|
|
- Status = VerifyReadWriteRequest (
|
|
- &Dev->BlockIoMedia,
|
|
- Lba,
|
|
- BufferSize,
|
|
- FALSE // RequestIsWrite
|
|
- );
|
|
- if (EFI_ERROR (Status)) {
|
|
- return Status;
|
|
- }
|
|
-
|
|
- return SynchronousRequest (
|
|
- Dev,
|
|
+ return VirtioBlkReadWriteBlocks(
|
|
+ This,
|
|
+ MediaId,
|
|
Lba,
|
|
BufferSize,
|
|
Buffer,
|
|
- FALSE // RequestIsWrite
|
|
+ FALSE // RequestIsRead
|
|
);
|
|
}
|
|
|
|
@@ -541,26 +588,9 @@ VirtioBlkWriteBlocks (
|
|
IN VOID *Buffer
|
|
)
|
|
{
|
|
- VBLK_DEV *Dev;
|
|
- EFI_STATUS Status;
|
|
-
|
|
- if (BufferSize == 0) {
|
|
- return EFI_SUCCESS;
|
|
- }
|
|
-
|
|
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
|
|
- Status = VerifyReadWriteRequest (
|
|
- &Dev->BlockIoMedia,
|
|
- Lba,
|
|
- BufferSize,
|
|
- TRUE // RequestIsWrite
|
|
- );
|
|
- if (EFI_ERROR (Status)) {
|
|
- return Status;
|
|
- }
|
|
-
|
|
- return SynchronousRequest (
|
|
- Dev,
|
|
+ return VirtioBlkReadWriteBlocks(
|
|
+ This,
|
|
+ MediaId,
|
|
Lba,
|
|
BufferSize,
|
|
Buffer,
|
|
@@ -716,6 +746,8 @@ VirtioBlkInit (
|
|
UINT8 NextDevStat;
|
|
EFI_STATUS Status;
|
|
|
|
+ UINT32 MaxSegmentSize;
|
|
+ UINT32 MaxSegments;
|
|
UINT64 Features;
|
|
UINT64 NumSectors;
|
|
UINT32 BlockSize;
|
|
@@ -814,6 +846,36 @@ VirtioBlkInit (
|
|
BlockSize = 512;
|
|
}
|
|
|
|
+ if (Features & VIRTIO_BLK_F_SIZE_MAX) {
|
|
+ Status = VIRTIO_CFG_READ (Dev, SizeMax, &MaxSegmentSize);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ goto Failed;
|
|
+ }
|
|
+ if (MaxSegmentSize == 0) {
|
|
+ //
|
|
+ // We need at least one 4KB page.
|
|
+ //
|
|
+ MaxSegmentSize = SIZE_4KB;
|
|
+ }
|
|
+ } else {
|
|
+ MaxSegmentSize = SIZE_512KB;
|
|
+ }
|
|
+
|
|
+ if (Features & VIRTIO_BLK_F_SEG_MAX) {
|
|
+ Status = VIRTIO_CFG_READ (Dev, SegMax, &MaxSegments);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ goto Failed;
|
|
+ }
|
|
+ if (MaxSegments == 0) {
|
|
+ //
|
|
+ // We need at least one SG element, whatever they say.
|
|
+ //
|
|
+ MaxSegments = 1;
|
|
+ }
|
|
+ } else {
|
|
+ MaxSegments = DEFAULT_MAX_SEGMENTS;
|
|
+ }
|
|
+
|
|
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
|
|
Status = VIRTIO_CFG_READ (
|
|
Dev,
|
|
@@ -955,6 +1017,8 @@ VirtioBlkInit (
|
|
Dev->BlockIoMedia.ReadOnly = (BOOLEAN)((Features & VIRTIO_BLK_F_RO) != 0);
|
|
Dev->BlockIoMedia.WriteCaching = (BOOLEAN)((Features & VIRTIO_BLK_F_FLUSH) != 0);
|
|
Dev->BlockIoMedia.BlockSize = BlockSize;
|
|
+ Dev->BlockIoMedia.MaxSegments = MaxSegments;
|
|
+ Dev->BlockIoMedia.MaxSegmentSize = MaxSegmentSize;
|
|
Dev->BlockIoMedia.IoAlign = 0;
|
|
Dev->BlockIoMedia.LastBlock = DivU64x32 (
|
|
NumSectors,
|
|
@@ -968,6 +1032,8 @@ VirtioBlkInit (
|
|
Dev->BlockIoMedia.BlockSize,
|
|
Dev->BlockIoMedia.LastBlock + 1
|
|
));
|
|
+ DEBUG ((DEBUG_INFO, "%a: MaxSegments=0x%x[B] MaxSegmentSize=0x%x[B]\n",
|
|
+ __FUNCTION__, Dev->BlockIoMedia.MaxSegments, Dev->BlockIoMedia.MaxSegmentSize));
|
|
|
|
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
|
|
Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
|
|
--
|
|
2.43.0
|
|
|