| From 86991b6e7ea6c613b7692f65106076943449b6b7 Mon Sep 17 00:00:00 2001 |
| From: Juergen Gross <jgross@suse.com> |
| Date: Mon, 7 Sep 2020 15:47:28 +0200 |
| Subject: xen/scsiback: use lateeoi irq binding |
| |
| From: Juergen Gross <jgross@suse.com> |
| |
| commit 86991b6e7ea6c613b7692f65106076943449b6b7 upstream. |
| |
| In order to reduce the chance for the system becoming unresponsive due |
| to event storms triggered by a misbehaving scsifront use the lateeoi |
| irq binding for scsiback and unmask the event channel only just before |
| leaving the event handling function. |
| |
| In case of a ring protocol error don't issue an EOI in order to avoid |
| the possibility to use that for producing an event storm. This at once |
| will result in no further call of scsiback_irq_fn(), so the ring_error |
| struct member can be dropped and scsiback_do_cmd_fn() can signal the |
| protocol error via a negative return value. |
| |
| This is part of XSA-332. |
| |
| Cc: stable@vger.kernel.org |
| Reported-by: Julien Grall <julien@xen.org> |
| Signed-off-by: Juergen Gross <jgross@suse.com> |
| Reviewed-by: Jan Beulich <jbeulich@suse.com> |
| Reviewed-by: Wei Liu <wl@xen.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/xen/xen-scsiback.c | 23 +++++++++++++---------- |
| 1 file changed, 13 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/xen/xen-scsiback.c |
| +++ b/drivers/xen/xen-scsiback.c |
| @@ -91,7 +91,6 @@ struct vscsibk_info { |
| unsigned int irq; |
| |
| struct vscsiif_back_ring ring; |
| - int ring_error; |
| |
| spinlock_t ring_lock; |
| atomic_t nr_unreplied_reqs; |
| @@ -722,7 +721,8 @@ static struct vscsibk_pend *prepare_pend |
| return pending_req; |
| } |
| |
| -static int scsiback_do_cmd_fn(struct vscsibk_info *info) |
| +static int scsiback_do_cmd_fn(struct vscsibk_info *info, |
| + unsigned int *eoi_flags) |
| { |
| struct vscsiif_back_ring *ring = &info->ring; |
| struct vscsiif_request ring_req; |
| @@ -739,11 +739,12 @@ static int scsiback_do_cmd_fn(struct vsc |
| rc = ring->rsp_prod_pvt; |
| pr_warn("Dom%d provided bogus ring requests (%#x - %#x = %u). Halting ring processing\n", |
| info->domid, rp, rc, rp - rc); |
| - info->ring_error = 1; |
| - return 0; |
| + return -EINVAL; |
| } |
| |
| while ((rc != rp)) { |
| + *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS; |
| + |
| if (RING_REQUEST_CONS_OVERFLOW(ring, rc)) |
| break; |
| |
| @@ -802,13 +803,16 @@ static int scsiback_do_cmd_fn(struct vsc |
| static irqreturn_t scsiback_irq_fn(int irq, void *dev_id) |
| { |
| struct vscsibk_info *info = dev_id; |
| + int rc; |
| + unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS; |
| |
| - if (info->ring_error) |
| - return IRQ_HANDLED; |
| - |
| - while (scsiback_do_cmd_fn(info)) |
| + while ((rc = scsiback_do_cmd_fn(info, &eoi_flags)) > 0) |
| cond_resched(); |
| |
| + /* In case of a ring error we keep the event channel masked. */ |
| + if (!rc) |
| + xen_irq_lateeoi(irq, eoi_flags); |
| + |
| return IRQ_HANDLED; |
| } |
| |
| @@ -829,7 +833,7 @@ static int scsiback_init_sring(struct vs |
| sring = (struct vscsiif_sring *)area; |
| BACK_RING_INIT(&info->ring, sring, PAGE_SIZE); |
| |
| - err = bind_interdomain_evtchn_to_irq(info->domid, evtchn); |
| + err = bind_interdomain_evtchn_to_irq_lateeoi(info->domid, evtchn); |
| if (err < 0) |
| goto unmap_page; |
| |
| @@ -1253,7 +1257,6 @@ static int scsiback_probe(struct xenbus_ |
| |
| info->domid = dev->otherend_id; |
| spin_lock_init(&info->ring_lock); |
| - info->ring_error = 0; |
| atomic_set(&info->nr_unreplied_reqs, 0); |
| init_waitqueue_head(&info->waiting_to_free); |
| info->dev = dev; |