All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alexander Atanasov <alexander.atanasov@virtuozzo.com>
Cc: Jason Wang <jasowang@redhat.com>,
	kernel@openvz.org, Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	"Paul E. McKenney" <paulmck@kernel.org>,
	Marc Zyngier <maz@kernel.org>, Halil Pasic <pasic@linux.ibm.com>,
	Cornelia Huck <cohuck@redhat.com>,
	Vineeth Vijayan <vneethv@linux.ibm.com>,
	Peter Oberparleiter <oberpar@linux.ibm.com>,
	linux-s390@vger.kernel.org,
	Xuan Zhuo <xuanzhuo@linux.alibaba.com>,
	virtualization@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 1/1] virtio: Restore semantics of vq->broken in virtqueues
Date: Thu, 30 Jun 2022 11:43:52 -0400	[thread overview]
Message-ID: <20220630114142-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <1c72645a-f162-2649-bdb6-a28ba93bccd2@virtuozzo.com>

On Thu, Jun 30, 2022 at 01:08:53PM +0300, Alexander Atanasov wrote:
> Hello,
> 
> On 30/06/2022 12:46, Michael S. Tsirkin wrote:
> > On Thu, Jun 30, 2022 at 09:36:46AM +0000, Alexander Atanasov wrote:
> > > virtio: harden vring IRQ (8b4ec69d7e09) changed the use
> > > of vq->broken. As result vring_interrupt handles IRQs for
> > > broken drivers as IRQ_NONE and not IRQ_HANDLED and made impossible
> > > to initiallize vqs before the driver is ready, i.e. in probe method.
> > > Balloon driver does this and it can not load because it fails in
> > > vqs_init with -EIO.
> > > 
> > > So instead of changing the original intent ot the flag introduce
> > > a new flag vq->ready which servers the purpose to check of early IRQs
> > > and restore the behaviour of the vq->broken flag.
> > > 
> > > Signed-off-by: Alexander Atanasov <alexander.atanasov@virtuozzo.com>
> > 
> > Does
> > 
> > commit c346dae4f3fbce51bbd4f2ec5e8c6f9b91e93163
> > Author: Jason Wang <jasowang@redhat.com>
> > Date:   Wed Jun 22 09:29:40 2022 +0800
> > 
> >      virtio: disable notification hardening by default
> > 
> > 
> > solve the problem for you?
> 
> 
> No, it won't if CONFIG_VIRTIO_HARDEN_NOTIFICATION is enabled - balloon still
> won't be able to init vqs.

Yea I intend to make CONFIG_VIRTIO_HARDEN_NOTIFICATION 
depend on BROKEN for now.

> The problem is in virtqueue_add_split and virtqueue_add_packed - can not set
> driver_ok without queues.
> 
> The return value of the vring_interrupt gets different - and iirc IRQ_NONE
> for broken device can lead to interrupt storms - i am not sure if that is
> valid for virtio devices yet but for real harware most likely.

No, I think it's the reverse. With IRQ_HANDLED an interrupt
storm will keep overloading the CPU since driver tells
kernel all is well. With IRQ_NONE kernel will eventually
intervene and disable the irq.

> Either way if
> you have a mix of  drivers working differently depending on return of the
> handler  it would get really messy.
> 
> RR's original intent was to flag a driver as bad why reuse it like that  ?
> 
> 
> > >   drivers/virtio/virtio_ring.c  | 20 ++++++++++++++------
> > >   include/linux/virtio.h        |  2 +-
> > >   include/linux/virtio_config.h | 10 +++++-----
> > >   3 files changed, 20 insertions(+), 12 deletions(-)
> > > 
> > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > Cc: Peter Zijlstra <peterz@infradead.org>
> > > Cc: "Paul E. McKenney" <paulmck@kernel.org>
> > > Cc: Marc Zyngier <maz@kernel.org>
> > > Cc: Halil Pasic <pasic@linux.ibm.com>
> > > Cc: Cornelia Huck <cohuck@redhat.com>
> > > Cc: Vineeth Vijayan <vneethv@linux.ibm.com>
> > > Cc: Peter Oberparleiter <oberpar@linux.ibm.com>
> > > Cc: linux-s390@vger.kernel.org
> > > Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > 
> > > 
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index 13a7348cedff..dca3cc774584 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -100,6 +100,9 @@ struct vring_virtqueue {
> > >   	/* Other side has made a mess, don't try any more. */
> > >   	bool broken;
> > > +	/* the queue is ready to handle interrupts  */
> > > +	bool ready;
> > > +
> > >   	/* Host supports indirect buffers */
> > >   	bool indirect;
> > > @@ -1688,7 +1691,8 @@ static struct virtqueue *vring_create_virtqueue_packed(
> > >   	vq->we_own_ring = true;
> > >   	vq->notify = notify;
> > >   	vq->weak_barriers = weak_barriers;
> > > -	vq->broken = true;
> > > +	vq->broken = false;
> > > +	vq->ready = false;
> > >   	vq->last_used_idx = 0;
> > >   	vq->event_triggered = false;
> > >   	vq->num_added = 0;
> > > @@ -2134,7 +2138,10 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
> > >   		return IRQ_NONE;
> > >   	}
> > > -	if (unlikely(vq->broken)) {
> > > +	if (unlikely(vq->broken))
> > > +		return IRQ_HANDLED;
> > > +
> > > +	if (unlikely(!vq->ready)) {
> > >   		dev_warn_once(&vq->vq.vdev->dev,
> > >   			      "virtio vring IRQ raised before DRIVER_OK");
> > >   		return IRQ_NONE;
> > > @@ -2180,7 +2187,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > >   	vq->we_own_ring = false;
> > >   	vq->notify = notify;
> > >   	vq->weak_barriers = weak_barriers;
> > > -	vq->broken = true;
> > > +	vq->broken = false;
> > > +	vq->ready = false;
> > >   	vq->last_used_idx = 0;
> > >   	vq->event_triggered = false;
> > >   	vq->num_added = 0;
> > > @@ -2405,7 +2413,7 @@ EXPORT_SYMBOL_GPL(virtio_break_device);
> > >    * (probing and restoring). This function should only be called by the
> > >    * core, not directly by the driver.
> > >    */
> > > -void __virtio_unbreak_device(struct virtio_device *dev)
> > > +void __virtio_device_ready(struct virtio_device *dev)
> > >   {
> > >   	struct virtqueue *_vq;
> > > @@ -2414,11 +2422,11 @@ void __virtio_unbreak_device(struct virtio_device *dev)
> > >   		struct vring_virtqueue *vq = to_vvq(_vq);
> > >   		/* Pairs with READ_ONCE() in virtqueue_is_broken(). */
> > > -		WRITE_ONCE(vq->broken, false);
> > > +		WRITE_ONCE(vq->ready, true);
> > >   	}
> > >   	spin_unlock(&dev->vqs_list_lock);
> > >   }
> > > -EXPORT_SYMBOL_GPL(__virtio_unbreak_device);
> > > +EXPORT_SYMBOL_GPL(__virtio_device_ready);
> > >   dma_addr_t virtqueue_get_desc_addr(struct virtqueue *_vq)
> > >   {
> > > diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> > > index d8fdf170637c..538c5959949a 100644
> > > --- a/include/linux/virtio.h
> > > +++ b/include/linux/virtio.h
> > > @@ -131,7 +131,7 @@ void unregister_virtio_device(struct virtio_device *dev);
> > >   bool is_virtio_device(struct device *dev);
> > >   void virtio_break_device(struct virtio_device *dev);
> > > -void __virtio_unbreak_device(struct virtio_device *dev);
> > > +void __virtio_device_ready(struct virtio_device *dev);
> > >   void virtio_config_changed(struct virtio_device *dev);
> > >   #ifdef CONFIG_PM_SLEEP
> > > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > > index 49c7c32815f1..35cf1b26e05a 100644
> > > --- a/include/linux/virtio_config.h
> > > +++ b/include/linux/virtio_config.h
> > > @@ -259,21 +259,21 @@ void virtio_device_ready(struct virtio_device *dev)
> > >   	/*
> > >   	 * The virtio_synchronize_cbs() makes sure vring_interrupt()
> > > -	 * will see the driver specific setup if it sees vq->broken
> > > +	 * will see the driver specific setup if it sees vq->ready
> > >   	 * as false (even if the notifications come before DRIVER_OK).
> > >   	 */
> > >   	virtio_synchronize_cbs(dev);
> > > -	__virtio_unbreak_device(dev);
> > > +	__virtio_device_ready(dev);
> > >   	/*
> > > -	 * The transport should ensure the visibility of vq->broken
> > > +	 * The transport should ensure the visibility of vq->ready
> > >   	 * before setting DRIVER_OK. See the comments for the transport
> > >   	 * specific set_status() method.
> > >   	 *
> > >   	 * A well behaved device will only notify a virtqueue after
> > >   	 * DRIVER_OK, this means the device should "see" the coherenct
> > > -	 * memory write that set vq->broken as false which is done by
> > > +	 * memory write that set vq->ready as true which is done by
> > >   	 * the driver when it sees DRIVER_OK, then the following
> > > -	 * driver's vring_interrupt() will see vq->broken as false so
> > > +	 * driver's vring_interrupt() will see vq->true as true so
> > >   	 * we won't lose any notification.
> > >   	 */
> > >   	dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
> > > -- 
> > > 2.25.1
> 
> -- 
> Regards,
> Alexander Atanasov


WARNING: multiple messages have this Message-ID (diff)
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alexander Atanasov <alexander.atanasov@virtuozzo.com>
Cc: linux-s390@vger.kernel.org,
	"Paul E. McKenney" <paulmck@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Marc Zyngier <maz@kernel.org>, Cornelia Huck <cohuck@redhat.com>,
	Peter Oberparleiter <oberpar@linux.ibm.com>,
	virtualization@lists.linux-foundation.org,
	Halil Pasic <pasic@linux.ibm.com>,
	kernel@openvz.org, Vineeth Vijayan <vneethv@linux.ibm.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 1/1] virtio: Restore semantics of vq->broken in virtqueues
Date: Thu, 30 Jun 2022 11:43:52 -0400	[thread overview]
Message-ID: <20220630114142-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <1c72645a-f162-2649-bdb6-a28ba93bccd2@virtuozzo.com>

On Thu, Jun 30, 2022 at 01:08:53PM +0300, Alexander Atanasov wrote:
> Hello,
> 
> On 30/06/2022 12:46, Michael S. Tsirkin wrote:
> > On Thu, Jun 30, 2022 at 09:36:46AM +0000, Alexander Atanasov wrote:
> > > virtio: harden vring IRQ (8b4ec69d7e09) changed the use
> > > of vq->broken. As result vring_interrupt handles IRQs for
> > > broken drivers as IRQ_NONE and not IRQ_HANDLED and made impossible
> > > to initiallize vqs before the driver is ready, i.e. in probe method.
> > > Balloon driver does this and it can not load because it fails in
> > > vqs_init with -EIO.
> > > 
> > > So instead of changing the original intent ot the flag introduce
> > > a new flag vq->ready which servers the purpose to check of early IRQs
> > > and restore the behaviour of the vq->broken flag.
> > > 
> > > Signed-off-by: Alexander Atanasov <alexander.atanasov@virtuozzo.com>
> > 
> > Does
> > 
> > commit c346dae4f3fbce51bbd4f2ec5e8c6f9b91e93163
> > Author: Jason Wang <jasowang@redhat.com>
> > Date:   Wed Jun 22 09:29:40 2022 +0800
> > 
> >      virtio: disable notification hardening by default
> > 
> > 
> > solve the problem for you?
> 
> 
> No, it won't if CONFIG_VIRTIO_HARDEN_NOTIFICATION is enabled - balloon still
> won't be able to init vqs.

Yea I intend to make CONFIG_VIRTIO_HARDEN_NOTIFICATION 
depend on BROKEN for now.

> The problem is in virtqueue_add_split and virtqueue_add_packed - can not set
> driver_ok without queues.
> 
> The return value of the vring_interrupt gets different - and iirc IRQ_NONE
> for broken device can lead to interrupt storms - i am not sure if that is
> valid for virtio devices yet but for real harware most likely.

No, I think it's the reverse. With IRQ_HANDLED an interrupt
storm will keep overloading the CPU since driver tells
kernel all is well. With IRQ_NONE kernel will eventually
intervene and disable the irq.

> Either way if
> you have a mix of  drivers working differently depending on return of the
> handler  it would get really messy.
> 
> RR's original intent was to flag a driver as bad why reuse it like that  ?
> 
> 
> > >   drivers/virtio/virtio_ring.c  | 20 ++++++++++++++------
> > >   include/linux/virtio.h        |  2 +-
> > >   include/linux/virtio_config.h | 10 +++++-----
> > >   3 files changed, 20 insertions(+), 12 deletions(-)
> > > 
> > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > Cc: Peter Zijlstra <peterz@infradead.org>
> > > Cc: "Paul E. McKenney" <paulmck@kernel.org>
> > > Cc: Marc Zyngier <maz@kernel.org>
> > > Cc: Halil Pasic <pasic@linux.ibm.com>
> > > Cc: Cornelia Huck <cohuck@redhat.com>
> > > Cc: Vineeth Vijayan <vneethv@linux.ibm.com>
> > > Cc: Peter Oberparleiter <oberpar@linux.ibm.com>
> > > Cc: linux-s390@vger.kernel.org
> > > Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > 
> > > 
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index 13a7348cedff..dca3cc774584 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -100,6 +100,9 @@ struct vring_virtqueue {
> > >   	/* Other side has made a mess, don't try any more. */
> > >   	bool broken;
> > > +	/* the queue is ready to handle interrupts  */
> > > +	bool ready;
> > > +
> > >   	/* Host supports indirect buffers */
> > >   	bool indirect;
> > > @@ -1688,7 +1691,8 @@ static struct virtqueue *vring_create_virtqueue_packed(
> > >   	vq->we_own_ring = true;
> > >   	vq->notify = notify;
> > >   	vq->weak_barriers = weak_barriers;
> > > -	vq->broken = true;
> > > +	vq->broken = false;
> > > +	vq->ready = false;
> > >   	vq->last_used_idx = 0;
> > >   	vq->event_triggered = false;
> > >   	vq->num_added = 0;
> > > @@ -2134,7 +2138,10 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
> > >   		return IRQ_NONE;
> > >   	}
> > > -	if (unlikely(vq->broken)) {
> > > +	if (unlikely(vq->broken))
> > > +		return IRQ_HANDLED;
> > > +
> > > +	if (unlikely(!vq->ready)) {
> > >   		dev_warn_once(&vq->vq.vdev->dev,
> > >   			      "virtio vring IRQ raised before DRIVER_OK");
> > >   		return IRQ_NONE;
> > > @@ -2180,7 +2187,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > >   	vq->we_own_ring = false;
> > >   	vq->notify = notify;
> > >   	vq->weak_barriers = weak_barriers;
> > > -	vq->broken = true;
> > > +	vq->broken = false;
> > > +	vq->ready = false;
> > >   	vq->last_used_idx = 0;
> > >   	vq->event_triggered = false;
> > >   	vq->num_added = 0;
> > > @@ -2405,7 +2413,7 @@ EXPORT_SYMBOL_GPL(virtio_break_device);
> > >    * (probing and restoring). This function should only be called by the
> > >    * core, not directly by the driver.
> > >    */
> > > -void __virtio_unbreak_device(struct virtio_device *dev)
> > > +void __virtio_device_ready(struct virtio_device *dev)
> > >   {
> > >   	struct virtqueue *_vq;
> > > @@ -2414,11 +2422,11 @@ void __virtio_unbreak_device(struct virtio_device *dev)
> > >   		struct vring_virtqueue *vq = to_vvq(_vq);
> > >   		/* Pairs with READ_ONCE() in virtqueue_is_broken(). */
> > > -		WRITE_ONCE(vq->broken, false);
> > > +		WRITE_ONCE(vq->ready, true);
> > >   	}
> > >   	spin_unlock(&dev->vqs_list_lock);
> > >   }
> > > -EXPORT_SYMBOL_GPL(__virtio_unbreak_device);
> > > +EXPORT_SYMBOL_GPL(__virtio_device_ready);
> > >   dma_addr_t virtqueue_get_desc_addr(struct virtqueue *_vq)
> > >   {
> > > diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> > > index d8fdf170637c..538c5959949a 100644
> > > --- a/include/linux/virtio.h
> > > +++ b/include/linux/virtio.h
> > > @@ -131,7 +131,7 @@ void unregister_virtio_device(struct virtio_device *dev);
> > >   bool is_virtio_device(struct device *dev);
> > >   void virtio_break_device(struct virtio_device *dev);
> > > -void __virtio_unbreak_device(struct virtio_device *dev);
> > > +void __virtio_device_ready(struct virtio_device *dev);
> > >   void virtio_config_changed(struct virtio_device *dev);
> > >   #ifdef CONFIG_PM_SLEEP
> > > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > > index 49c7c32815f1..35cf1b26e05a 100644
> > > --- a/include/linux/virtio_config.h
> > > +++ b/include/linux/virtio_config.h
> > > @@ -259,21 +259,21 @@ void virtio_device_ready(struct virtio_device *dev)
> > >   	/*
> > >   	 * The virtio_synchronize_cbs() makes sure vring_interrupt()
> > > -	 * will see the driver specific setup if it sees vq->broken
> > > +	 * will see the driver specific setup if it sees vq->ready
> > >   	 * as false (even if the notifications come before DRIVER_OK).
> > >   	 */
> > >   	virtio_synchronize_cbs(dev);
> > > -	__virtio_unbreak_device(dev);
> > > +	__virtio_device_ready(dev);
> > >   	/*
> > > -	 * The transport should ensure the visibility of vq->broken
> > > +	 * The transport should ensure the visibility of vq->ready
> > >   	 * before setting DRIVER_OK. See the comments for the transport
> > >   	 * specific set_status() method.
> > >   	 *
> > >   	 * A well behaved device will only notify a virtqueue after
> > >   	 * DRIVER_OK, this means the device should "see" the coherenct
> > > -	 * memory write that set vq->broken as false which is done by
> > > +	 * memory write that set vq->ready as true which is done by
> > >   	 * the driver when it sees DRIVER_OK, then the following
> > > -	 * driver's vring_interrupt() will see vq->broken as false so
> > > +	 * driver's vring_interrupt() will see vq->true as true so
> > >   	 * we won't lose any notification.
> > >   	 */
> > >   	dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
> > > -- 
> > > 2.25.1
> 
> -- 
> Regards,
> Alexander Atanasov

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

  reply	other threads:[~2022-06-30 15:44 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-30  9:36 [PATCH v1 1/1] virtio: Restore semantics of vq->broken in virtqueues Alexander Atanasov
2022-06-30  9:46 ` Michael S. Tsirkin
2022-06-30  9:46   ` Michael S. Tsirkin
2022-06-30 10:08   ` Alexander Atanasov
2022-06-30 15:43     ` Michael S. Tsirkin [this message]
2022-06-30 15:43       ` Michael S. Tsirkin
2022-07-01  1:12       ` Jason Wang
2022-07-01  1:12         ` Jason Wang
2022-07-01  6:14         ` Michael S. Tsirkin
2022-07-01  6:14           ` Michael S. Tsirkin
2022-07-01  1:07     ` Jason Wang
2022-07-01  1:07       ` Jason Wang
2022-07-04  7:44       ` [PATCH v2 " Alexander Atanasov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220630114142-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=alexander.atanasov@virtuozzo.com \
    --cc=cohuck@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=kernel@openvz.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=oberpar@linux.ibm.com \
    --cc=pasic@linux.ibm.com \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=vneethv@linux.ibm.com \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.