On 08/10/17 02:25, Laszlo Ersek wrote: > On 08/07/17 13:58, Brijesh Singh wrote: >> The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() >> to map system memory to device address and programs the vring descriptors >> with device addresses. >> >> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> >> Cc: Jordan Justen <jordan.l.jus...@intel.com> >> Cc: Tom Lendacky <thomas.lenda...@amd.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> >> --- >> OvmfPkg/VirtioRngDxe/VirtioRng.h | 1 + >> OvmfPkg/VirtioRngDxe/VirtioRng.c | 47 +++++++++++++++++--- >> 2 files changed, 43 insertions(+), 5 deletions(-) > > I'm skipping all the other device driver conversion patches for now (v1 > 8-13), because I think that this is the simplest driver, and we already > have enough changes queued from this review. > > I suggest that for v2, you please update and test all of the drivers (so > that we can be sure that my requests are feasible), but move this driver > patch in front of the others. > > I'll say a number of generalities: > > * Please never roll-back earlier actions directly within an > error-catching "if" -- instead, insert a new error handling label at > the appropriate place, and jump to it with "goto". Sooner or later > we'll grow yet more actions, and then we'll have to convert those "if" > bodies to goto's anyway. > > * NULL for RingMap is a valid value () -- see also point (8) in my v1 > 03/14 feedback -- and device driver logic should not depend on it. > Instead, use additional (precise) labels -- such as "UnmapQueue" and > "UnmapBuffer" -- and matching goto statements. > > If a VirtIo->MapSharedBuffer() implementation gives you RingMap=NULL > (on success), then VirtIo->UnmapSharedBuffer() will also take > RingMap=NULL -- you simply don't have to be aware of the value. > > * In most cases, the fact that you have a live exit-boot-services > callback implies that your device is "live" as well. So no need for > additional checks before unmapping the queue. (There are exceptions of > course, such as virtio-net -- IIRC the SimpleNetworkProtocol has an > internal state flag that affects this question.) > > For example, in the virtio-rng case, the exit-boot-services > notification function is installed in VirtioRngDriverBindingStart() > *after* the call to VirtioRngInit(). In addition, it is uninstalled -- > its associated event is closed -- in VirtioRngDriverBindingStop(), > *before* the call to VirtioRngUninit(). So whenever the notification > function can run, the device is guaranteed to be live.
Something else: please don't forget about the VIRTIO_F_IOMMU_PLATFORM flag -- pls see point (5.3) in <841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com">http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com>. After this conversion is complete, we can claim that our virtio device drivers are "IOMMU aware", whenever we negotiate VIRTIO_F_VERSION_1. (It's a different question what IOMMU drivers we have.) Thanks, Laszlo >> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.h >> b/OvmfPkg/VirtioRngDxe/VirtioRng.h >> index 998f9fae48c2..b372d84c1ebc 100644 >> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.h >> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.h >> @@ -38,6 +38,7 @@ typedef struct { >> EFI_EVENT ExitBoot; // DriverBindingStart 0 >> VRING Ring; // VirtioRingInit 2 >> EFI_RNG_PROTOCOL Rng; // VirtioRngInit 1 >> + VOID *RingMap; // VirtioRngInit 1 >> } VIRTIO_RNG_DEV; >> >> #define VIRTIO_ENTROPY_SOURCE_FROM_RNG(RngPointer) \ >> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c >> b/OvmfPkg/VirtioRngDxe/VirtioRng.c >> index e20602ac7225..5ff54867616a 100644 >> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c >> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c >> @@ -140,11 +140,15 @@ VirtioRngGetRNG ( >> UINT32 Len; >> UINT32 BufferSize; >> EFI_STATUS Status; >> + UINTN NumPages; >> + EFI_PHYSICAL_ADDRESS DeviceAddress; >> + VOID *Mapping; >> >> if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) { >> return EFI_INVALID_PARAMETER; >> } >> >> + Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This); >> // >> // We only support the raw algorithm, so reject requests for anything else >> // >> @@ -153,12 +157,18 @@ VirtioRngGetRNG ( >> return EFI_UNSUPPORTED; >> } >> >> - Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength); >> - if (Buffer == NULL) { >> + NumPages = EFI_SIZE_TO_PAGES (RNGValueLength); >> + Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages, (VOID >> *)&Buffer); >> + if (EFI_ERROR (Status)) { >> return EFI_DEVICE_ERROR; >> } >> >> - Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This); >> + Status = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *)Buffer, >> + RNGValueLength, &DeviceAddress, &Mapping); >> + if (EFI_ERROR (Status)) { >> + VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer); >> + return EFI_DEVICE_ERROR; >> + } >> >> // >> // The Virtio RNG device may return less data than we asked it to, and can >> @@ -170,7 +180,7 @@ VirtioRngGetRNG ( >> >> VirtioPrepare (&Dev->Ring, &Indices); >> VirtioAppendDesc (&Dev->Ring, >> - (UINTN)Buffer + Index, >> + (UINTN)DeviceAddress + Index, >> BufferSize, >> VRING_DESC_F_WRITE, >> &Indices); >> @@ -178,19 +188,22 @@ VirtioRngGetRNG ( >> if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) != >> EFI_SUCCESS) { >> Status = EFI_DEVICE_ERROR; >> + VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping); >> goto FreeBuffer; >> } >> ASSERT (Len > 0); >> ASSERT (Len <= BufferSize); >> } >> >> + VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping); >> + >> for (Index = 0; Index < RNGValueLength; Index++) { >> RNGValue[Index] = Buffer[Index]; >> } >> Status = EFI_SUCCESS; >> >> FreeBuffer: >> - FreePool ((VOID *)Buffer); >> + VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer); >> return Status; >> } >> >> @@ -281,6 +294,11 @@ VirtioRngInit ( >> goto Failed; >> } >> >> + Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &Dev->RingMap); >> + 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 release the ring >> resources. >> @@ -332,6 +350,11 @@ VirtioRngInit ( >> return EFI_SUCCESS; >> >> ReleaseQueue: >> + if (Dev->RingMap != NULL) { >> + VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap); >> + Dev->RingMap = NULL; >> + } >> + >> VirtioRingUninit (Dev->VirtIo, &Dev->Ring); >> >> Failed: >> @@ -359,6 +382,11 @@ VirtioRngUninit ( >> // the old comms area. >> // >> Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); >> + >> + if (Dev->RingMap != NULL) { >> + VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap); >> + } >> + >> VirtioRingUninit (Dev->VirtIo, &Dev->Ring); >> } >> >> @@ -385,6 +413,15 @@ VirtioRngExitBoot ( >> // >> Dev = Context; >> Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); >> + >> + // >> + // If Ring mapping exist then umap it so that hypervisor will not able to >> + // get readable data after device reset. >> + // >> + if (Dev->RingMap != NULL) { >> + VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap); >> + Dev->RingMap = NULL; >> + } >> } >> >> >> > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel