Re: [PATCH] virtio: acknowledge all features before access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




在 2022/1/15 上午4:09, Michael S. Tsirkin 写道:
The feature negotiation was designed in a way that
makes it possible for devices to know which config
fields will be accessed by drivers.

This is broken since commit 404123c2db79 ("virtio: allow drivers to
validate features") with fallout in at least block and net.
We have a partial work-around in commit 2f9a174f918e ("virtio: write
back F_VERSION_1 before validate") which at least lets devices
find out which format should config space have, but this
is a partial fix: guests should not access config space
without acknowledging features since otherwise we'll never
be able to change the config space format.

As a side effect, this also reduces the amount of hypervisor accesses -
we now only acknowledge features once unless we are clearing any
features when validating.

Cc: stable@xxxxxxxxxxxxxxx
Fixes: 404123c2db79 ("virtio: allow drivers to validate features")
Fixes: 2f9a174f918e ("virtio: write back F_VERSION_1 before validate")
Cc: "Halil Pasic" <pasic@xxxxxxxxxxxxx>
Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
---

Halil, I thought hard about our situation with transitional and
today I finally thought of something I am happy with.
Pls let me know what you think. Testing on big endian would
also be much appreciated!

  drivers/virtio/virtio.c | 31 +++++++++++++++++--------------
  1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index d891b0a354b0..2ed6e2451fd8 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -168,12 +168,10 @@ EXPORT_SYMBOL_GPL(virtio_add_status);
static int virtio_finalize_features(struct virtio_device *dev)
  {
-	int ret = dev->config->finalize_features(dev);
  	unsigned status;
+	int ret;
might_sleep();
-	if (ret)
-		return ret;
ret = arch_has_restricted_virtio_memory_access();
  	if (ret) {
@@ -244,17 +242,6 @@ static int virtio_dev_probe(struct device *_d)
  		driver_features_legacy = driver_features;
  	}
- /*
-	 * Some devices detect legacy solely via F_VERSION_1. Write
-	 * F_VERSION_1 to force LE config space accesses before FEATURES_OK for
-	 * these when needed.
-	 */
-	if (drv->validate && !virtio_legacy_is_little_endian()
-			  && device_features & BIT_ULL(VIRTIO_F_VERSION_1)) {
-		dev->features = BIT_ULL(VIRTIO_F_VERSION_1);
-		dev->config->finalize_features(dev);
-	}
-
  	if (device_features & (1ULL << VIRTIO_F_VERSION_1))
  		dev->features = driver_features & device_features;
  	else
@@ -265,10 +252,22 @@ static int virtio_dev_probe(struct device *_d)
  		if (device_features & (1ULL << i))
  			__virtio_set_bit(dev, i);
+ err = dev->config->finalize_features(dev);
+	if (err)
+		goto err;
+
  	if (drv->validate) {
+		u64 features = dev->features;
+
  		err = drv->validate(dev);
  		if (err)
  			goto err;
+
+		if (features != dev->features) {
+			err = dev->config->finalize_features(dev);
+			if (err)
+				goto err;
+		}
  	}
err = virtio_finalize_features(dev);
@@ -495,6 +494,10 @@ int virtio_device_restore(struct virtio_device *dev)
  	/* We have a driver! */
  	virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
+ ret = dev->config->finalize_features(dev);
+	if (ret)
+		goto err;


Is this part of code related?

Thanks


+
  	ret = virtio_finalize_features(dev);
  	if (ret)
  		goto err;




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux