From nobody Sun May 5 00:42:31 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1513135134051716.0999794969309; Tue, 12 Dec 2017 19:18:54 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 791322214E33A; Tue, 12 Dec 2017 19:14:13 -0800 (PST) Received: from huawei.com (unknown [45.249.212.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 29F46220EE136 for ; Tue, 12 Dec 2017 19:14:10 -0800 (PST) Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id A215E21FA52CC; Wed, 13 Dec 2017 11:18:45 +0800 (CST) Received: from HGHY1z004218071.china.huawei.com (10.177.29.32) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.361.1; Wed, 13 Dec 2017 11:18:39 +0800 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=45.249.212.35; helo=huawei.com; envelope-from=zhengxiang9@huawei.com; receiver=edk2-devel@lists.01.org From: Zheng Xiang To: Date: Wed, 13 Dec 2017 11:16:32 +0800 Message-ID: <20171213031632.11856-1-zhengxiang9@huawei.com> X-Mailer: git-send-email 2.15.1.windows.2 MIME-Version: 1.0 X-Originating-IP: [10.177.29.32] X-CFilter-Loop: Reflected Subject: [edk2] [PATCH] OvmfPkg/VirtioScsiDxe: Allocate all required vrings at VirtioScsiInit X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jordan Justen , Laszlo Ersek , Ard Biesheuvel Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" VirtioScsiInit() allocate only one request queue which causes the address of the other vrings to be 0. In AARCH64 virtual machines, the address of system memory starts at 0x40000000 and the address of rom starts at 0. This causes an error when QEMU translates the guest physical memory of vhost-scsi vrings to host virtual memory. So this patch fixes this issue by allocating all the required Vrings. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Laszlo Ersek Cc: Shannon Zhao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Zheng Xiang --- When using qemu with vhost-scsi on ARM64, it will fail with below error: qemu-kvm: Error start vhost dev qemu-kvm: unable to start vhost-scsi: Cannot allocate memory --- OvmfPkg/Include/IndustryStandard/VirtioScsi.h | 1 + OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 192 ++++++++++++++++------= ---- OvmfPkg/VirtioScsiDxe/VirtioScsi.h | 7 +- 3 files changed, 122 insertions(+), 78 deletions(-) diff --git a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h b/OvmfPkg/Includ= e/IndustryStandard/VirtioScsi.h index 0c9b520..9f4e6be 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioScsi.h @@ -81,6 +81,7 @@ typedef struct { // selector of first virtio queue usable for request transfer // #define VIRTIO_SCSI_REQUEST_QUEUE 2 +#define VIRTIO_SCSI_QUEUE_MAX 1024 =20 // // host response codes diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/Vir= tioScsi.c index 1a68f06..b9e72c8 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -590,19 +590,19 @@ VirtioScsiPassThru ( goto FreeResponseBuffer; } =20 - VirtioPrepare (&Dev->Ring, &Indices); + VirtioPrepare (&Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], &Indices); =20 // // ensured by VirtioScsiInit() -- this predicate, in combination with the // lock-step progress, ensures we don't have to track free descriptors. // - ASSERT (Dev->Ring.QueueSize >=3D 4); + ASSERT (Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE].QueueSize >=3D 4); =20 // // enqueue Request // VirtioAppendDesc ( - &Dev->Ring, + &Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], RequestDeviceAddress, sizeof Request, VRING_DESC_F_NEXT, @@ -614,7 +614,7 @@ VirtioScsiPassThru ( // if (Packet->OutTransferLength > 0) { VirtioAppendDesc ( - &Dev->Ring, + &Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], OutDataDeviceAddress, Packet->OutTransferLength, VRING_DESC_F_NEXT, @@ -626,7 +626,7 @@ VirtioScsiPassThru ( // enqueue Response, to be written by the host // VirtioAppendDesc ( - &Dev->Ring, + &Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], ResponseDeviceAddress, sizeof *Response, VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? VRING_DESC_F_NEXT= : 0), @@ -638,7 +638,7 @@ VirtioScsiPassThru ( // if (Packet->InTransferLength > 0) { VirtioAppendDesc ( - &Dev->Ring, + &Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], InDataDeviceAddress, Packet->InTransferLength, VRING_DESC_F_WRITE, @@ -650,7 +650,8 @@ VirtioScsiPassThru ( // EFI_NOT_READY would save us the effort, but it would also suggest tha= t the // caller retry. // - if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring, + if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, + &Dev->Ring[VIRTIO_SCSI_REQUEST_QUEUE], &Indices, NULL) !=3D EFI_SUCCESS) { Status =3D ReportHostAdapterError (Packet); goto UnmapResponseBuffer; @@ -912,6 +913,88 @@ VirtioScsiGetNextTarget ( return EFI_NOT_FOUND; } =20 +STATIC +EFI_STATUS +EFIAPI +VirtioScsiInitRing ( + IN OUT VSCSI_DEV *Dev, + IN UINT16 Selector, + OUT VRING *Ring, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT16 QueueSize; + UINT64 RingBaseShift; + VOID *MapInfo; + + // + // step 4b -- allocate request virtqueue + // + Status =3D Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector); + if (EFI_ERROR (Status)) { + return Status; + } + Status =3D Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); + if (EFI_ERROR (Status)) { + return Status; + } + // + // VirtioScsiPassThru() uses at most four descriptors + // + if (QueueSize < 4) { + Status =3D EFI_UNSUPPORTED; + return Status; + } + + Status =3D VirtioRingInit (Dev->VirtIo, QueueSize, Ring); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If anything fails from here on, we must release the ring resources + // + Status =3D VirtioRingMap (Dev->VirtIo, Ring, &RingBaseShift, &MapInfo); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must unmap the ring resource= s. + // + Status =3D Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status =3D Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + // + // step 4c -- Report GPFN (guest-physical frame number) of queue. + // + Status =3D Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, RingBaseShif= t); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + *Mapping =3D MapInfo; + + return EFI_SUCCESS; + +UnmapQueue: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, MapInfo); + +ReleaseQueue: + VirtioRingUninit (Dev->VirtIo, Ring); + + return Status; +} + =20 STATIC EFI_STATUS @@ -922,11 +1005,10 @@ VirtioScsiInit ( { UINT8 NextDevStat; EFI_STATUS Status; - UINT64 RingBaseShift; UINT64 Features; UINT16 MaxChannel; // for validation only - UINT32 NumQueues; // for validation only - UINT16 QueueSize; + UINT16 Count; + UINT16 Index; =20 // // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. @@ -978,11 +1060,11 @@ VirtioScsiInit ( goto Failed; } =20 - Status =3D VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues); + Status =3D VIRTIO_CFG_READ (Dev, NumQueues, &Dev->NumQueues); if (EFI_ERROR (Status)) { goto Failed; } - if (NumQueues < 1) { + if (Dev->NumQueues < 1 || Dev->NumQueues > VIRTIO_SCSI_QUEUE_MAX - 2) { Status =3D EFI_UNSUPPORTED; goto Failed; } @@ -1031,66 +1113,18 @@ VirtioScsiInit ( } =20 // - // step 4b -- allocate request virtqueue - // - Status =3D Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QU= EUE); - if (EFI_ERROR (Status)) { - goto Failed; - } - Status =3D Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); - if (EFI_ERROR (Status)) { - goto Failed; - } - // - // VirtioScsiPassThru() uses at most four descriptors - // - if (QueueSize < 4) { - Status =3D EFI_UNSUPPORTED; - goto Failed; - } - - Status =3D VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring); - if (EFI_ERROR (Status)) { - goto Failed; - } - - // - // If anything fails from here on, we must release the ring resources + // step 4b, 4c -- allocate and report virtqueues // - Status =3D VirtioRingMap ( - Dev->VirtIo, - &Dev->Ring, - &RingBaseShift, - &Dev->RingMap + for (Count =3D 0; Count < Dev->NumQueues + 2; Count++) { + Status =3D VirtioScsiInitRing ( + Dev, + Count, + &Dev->Ring[Count], + &Dev->RingMap[Count] ); - if (EFI_ERROR (Status)) { - goto ReleaseQueue; - } - - // - // Additional steps for MMIO: align the queue appropriately, and set the - // size. If anything fails from here on, we must unmap the ring resource= s. - // - Status =3D Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); - if (EFI_ERROR (Status)) { - goto UnmapQueue; - } - - Status =3D Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); - if (EFI_ERROR (Status)) { - goto UnmapQueue; - } - - // - // step 4c -- Report GPFN (guest-physical frame number) of queue. - // - Status =3D Dev->VirtIo->SetQueueAddress ( - Dev->VirtIo, - &Dev->Ring, - RingBaseShift - ); - if (EFI_ERROR (Status)) { - goto UnmapQueue; + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } } =20 // @@ -1160,10 +1194,10 @@ VirtioScsiInit ( return EFI_SUCCESS; =20 UnmapQueue: - Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap); - -ReleaseQueue: - VirtioRingUninit (Dev->VirtIo, &Dev->Ring); + for (Index =3D Count - 1; Index >=3D 0; Index--) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap[Index]); + VirtioRingUninit (Dev->VirtIo, &Dev->Ring[Index]); + } =20 Failed: // @@ -1177,6 +1211,7 @@ Failed: Dev->MaxTarget =3D 0; Dev->MaxLun =3D 0; Dev->MaxSectors =3D 0; + Dev->NumQueues =3D 0; =20 return Status; // reached only via Failed above } @@ -1189,6 +1224,7 @@ VirtioScsiUninit ( IN OUT VSCSI_DEV *Dev ) { + INT16 Index; // // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. = When // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away f= rom @@ -1201,8 +1237,12 @@ VirtioScsiUninit ( Dev->MaxLun =3D 0; Dev->MaxSectors =3D 0; =20 - Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap); - VirtioRingUninit (Dev->VirtIo, &Dev->Ring); + for (Index =3D 0; Index < Dev->NumQueues + 2; Index++) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap[Index]); + VirtioRingUninit (Dev->VirtIo, &Dev->Ring[Index]); + } + + Dev->NumQueues =3D 0; =20 SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00); SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00); diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/Vir= tioScsi.h index 05a6bf5..40ee6ba 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h @@ -57,10 +57,13 @@ typedef struct { UINT16 MaxTarget; // VirtioScsiInit 1 UINT32 MaxLun; // VirtioScsiInit 1 UINT32 MaxSectors; // VirtioScsiInit 1 - VRING Ring; // VirtioRingInit 2 + UINT32 NumQueues; // VirtioScsiInit 1 + VRING Ring[VIRTIO_SCSI_QUEUE_MAX]; + // VirtioScsiInitRing 2 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1 - VOID *RingMap; // VirtioRingMap 2 + VOID *RingMap[VIRTIO_SCSI_QUEUE_MAX]; + // VirtioRingMap 3 } VSCSI_DEV; =20 #define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \ --=20 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel