From cbad8e4cccf61c91932e7f091f9144448871c968 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Sat, 12 Mar 2016 14:41:26 +0100 Subject: [PATCH] OvmfPkg: VirtioBlkDxe: adapt feature negotiation to virtio-1.0 Relative to virtio-0.9.5, virtio-1.0 reverses the order of queue discovery and feature negotiation. In virtio-1.0, feature negotiation has to complete first, and the device can also reject a self-inconsistent feature request through the new VSTAT_FEATURES_OK status bit. (For example if the driver requests a higher level feature but clears a prerequisite feature.) Furthermore, we retain the VIRTIO_F_VERSION_1 feature bit if the VIRTIO_DEVICE_PROTOCOL provider has high enough revision. Cc: Ard Biesheuvel Cc: Jordan Justen Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek Tested-by: Ard Biesheuvel Reviewed-by: Jordan Justen --- OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 8257effac2..f1c3f87e20 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -692,6 +692,20 @@ VirtioBlkInit ( } } + Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO | + VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1; + + // + // In virtio-1.0, feature negotiation is expected to complete before queue + // discovery, and the device can also reject the selected set of features. + // + if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) { + Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + // // step 4b -- allocate virtqueue // @@ -739,11 +753,12 @@ VirtioBlkInit ( // // step 5 -- Report understood features. // - Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO | - VIRTIO_BLK_F_FLUSH; - Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); - if (EFI_ERROR (Status)) { - goto ReleaseQueue; + if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) { + Features &= ~(UINT64)VIRTIO_F_VERSION_1; + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } } //