X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FVirtioRngDxe%2FVirtioRng.c;h=3c733ea4db6666b8a7e29dfd5be42cd1ee3e7bfb;hb=231fdbb2107a2b359042626263317d8e494165dd;hp=0abca488e6cdd6614d4443c90c5c80d570bbe554;hpb=53a4c6047f3ce2ece7bb8db5b9815a1c9227dddb;p=mirror_edk2.git diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c index 0abca488e6..3c733ea4db 100644 --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c @@ -140,6 +140,8 @@ VirtioRngGetRNG ( UINT32 Len; UINT32 BufferSize; EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS DeviceAddress; + VOID *Mapping; if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) { return EFI_INVALID_PARAMETER; @@ -159,6 +161,21 @@ VirtioRngGetRNG ( } Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This); + // + // Map Buffer's system phyiscal address to device address + // + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterWrite, + (VOID *)Buffer, + RNGValueLength, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto FreeBuffer; + } // // The Virtio RNG device may return less data than we asked it to, and can @@ -170,7 +187,7 @@ VirtioRngGetRNG ( VirtioPrepare (&Dev->Ring, &Indices); VirtioAppendDesc (&Dev->Ring, - (UINTN)Buffer + Index, + DeviceAddress + Index, BufferSize, VRING_DESC_F_WRITE, &Indices); @@ -178,17 +195,35 @@ VirtioRngGetRNG ( if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) != EFI_SUCCESS) { Status = EFI_DEVICE_ERROR; - goto FreeBuffer; + goto UnmapBuffer; } ASSERT (Len > 0); ASSERT (Len <= BufferSize); } + // + // Unmap the device buffer before accessing it. + // + Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto FreeBuffer; + } + for (Index = 0; Index < RNGValueLength; Index++) { RNGValue[Index] = Buffer[Index]; } Status = EFI_SUCCESS; +UnmapBuffer: + // + // If we are reached here due to the error then unmap the buffer otherwise + // the buffer is already unmapped after VirtioFlush(). + // + if (EFI_ERROR (Status)) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping); + } + FreeBuffer: FreePool ((VOID *)Buffer); return Status; @@ -205,6 +240,7 @@ VirtioRngInit ( EFI_STATUS Status; UINT16 QueueSize; UINT64 Features; + UINT64 RingBaseShift; // // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. @@ -243,7 +279,7 @@ VirtioRngInit ( goto Failed; } - Features &= VIRTIO_F_VERSION_1; + Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM; // // In virtio-1.0, feature negotiation is expected to complete before queue @@ -281,36 +317,53 @@ VirtioRngInit ( goto Failed; } + // + // If anything fails from here on, we must release the ring resources. + // + Status = VirtioRingMap ( + Dev->VirtIo, + &Dev->Ring, + &RingBaseShift, + &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. + // size. If anything fails from here on, we must unmap the ring resources. // Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); if (EFI_ERROR (Status)) { - goto ReleaseQueue; + goto UnmapQueue; } Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { - goto ReleaseQueue; + goto UnmapQueue; } // // step 4c -- Report GPFN (guest-physical frame number) of queue. // - Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0); + Status = Dev->VirtIo->SetQueueAddress ( + Dev->VirtIo, + &Dev->Ring, + RingBaseShift + ); if (EFI_ERROR (Status)) { - goto ReleaseQueue; + goto UnmapQueue; } // // step 5 -- Report understood features and guest-tuneables. // if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) { - Features &= ~(UINT64)VIRTIO_F_VERSION_1; + Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM); Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); if (EFI_ERROR (Status)) { - goto ReleaseQueue; + goto UnmapQueue; } } @@ -320,7 +373,7 @@ VirtioRngInit ( NextDevStat |= VSTAT_DRIVER_OK; Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { - goto ReleaseQueue; + goto UnmapQueue; } // @@ -331,6 +384,9 @@ VirtioRngInit ( return EFI_SUCCESS; +UnmapQueue: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap); + ReleaseQueue: VirtioRingUninit (Dev->VirtIo, &Dev->Ring); @@ -359,6 +415,9 @@ VirtioRngUninit ( // the old comms area. // Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); + + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap); + VirtioRingUninit (Dev->VirtIo, &Dev->Ring); } @@ -376,6 +435,7 @@ VirtioRngExitBoot ( { VIRTIO_RNG_DEV *Dev; + DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context)); // // Reset the device. This causes the hypervisor to forget about the virtio // ring.