All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Farman <farman@linux.ibm.com>
To: linux-s390@vger.kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org
Cc: Matthew Rosato <mjrosato@linux.ibm.com>,
	Halil Pasic <pasic@linux.ibm.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	Eric Farman <farman@linux.ibm.com>
Subject: [PATCH v2 6/7] s390/vfio_ccw: implement a channel program lock
Date: Mon, 20 Jul 2026 22:19:30 +0200	[thread overview]
Message-ID: <20260720201931.976660-7-farman@linux.ibm.com> (raw)
In-Reply-To: <20260720201931.976660-1-farman@linux.ibm.com>

The channel_program struct is manipulated without a serialization
mechanism to ensure consistent behavior. Take a broad stroke of
putting the entire structure behind a spin lock, which can be
acquired with or without the mutex guarding the I/O regions that
feed into the population of the channel program.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
---
 drivers/s390/cio/vfio_ccw_cp.c      | 13 ++++++++++++-
 drivers/s390/cio/vfio_ccw_cp.h      |  1 +
 drivers/s390/cio/vfio_ccw_drv.c     |  6 +++++-
 drivers/s390/cio/vfio_ccw_ops.c     |  8 +++++++-
 drivers/s390/cio/vfio_ccw_private.h |  2 ++
 5 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index c6f0264fb5d3..7bfb3a952817 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -790,7 +790,7 @@ int cp_init(struct channel_program *cp, union orb *orb)
  * @cp, which must have been returned by a previous call to cp_init().
  * Otherwise, undefined behavior occurs.
  */
-void cp_free(struct channel_program *cp)
+void cp_free_locked(struct channel_program *cp)
 {
 	struct vfio_device *vdev =
 		&container_of(cp, struct vfio_ccw_private, cp)->vdev;
@@ -810,6 +810,17 @@ void cp_free(struct channel_program *cp)
 	}
 }
 
+void cp_free(struct channel_program *cp)
+{
+	struct vfio_ccw_private *private =
+		container_of(cp, struct vfio_ccw_private, cp);
+	unsigned long flags;
+
+	spin_lock_irqsave(&private->cp_lock, flags);
+	cp_free_locked(cp);
+	spin_unlock_irqrestore(&private->cp_lock, flags);
+}
+
 /**
  * cp_prefetch() - translate a guest physical address channel program to
  *                 a real-device runnable channel program.
diff --git a/drivers/s390/cio/vfio_ccw_cp.h b/drivers/s390/cio/vfio_ccw_cp.h
index d547dbc969cc..edfb47a292ca 100644
--- a/drivers/s390/cio/vfio_ccw_cp.h
+++ b/drivers/s390/cio/vfio_ccw_cp.h
@@ -48,6 +48,7 @@ struct channel_program {
 };
 
 int cp_init(struct channel_program *cp, union orb *orb);
+void cp_free_locked(struct channel_program *cp);
 void cp_free(struct channel_program *cp);
 int cp_prefetch(struct channel_program *cp);
 union orb *cp_get_orb(struct channel_program *cp, struct subchannel *sch);
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 1a095085bc72..bfb68de6e52c 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -83,6 +83,7 @@ void vfio_ccw_sch_io_todo(struct work_struct *work)
 {
 	struct vfio_ccw_private *private;
 	struct irb *irb;
+	unsigned long flags;
 	bool is_final;
 	bool cp_is_finished = false;
 
@@ -91,13 +92,16 @@ void vfio_ccw_sch_io_todo(struct work_struct *work)
 
 	is_final = !(scsw_actl(&irb->scsw) &
 		     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
+	spin_lock_irqsave(&private->cp_lock, flags);
 	if (scsw_is_solicited(&irb->scsw)) {
 		cp_update_scsw(&private->cp, &irb->scsw);
 		if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING) {
-			cp_free(&private->cp);
+			cp_free_locked(&private->cp);
 			cp_is_finished = true;
 		}
 	}
+	spin_unlock_irqrestore(&private->cp_lock, flags);
+
 	mutex_lock(&private->io_mutex);
 	memcpy(private->io_region->irb_area, irb, sizeof(*irb));
 	mutex_unlock(&private->io_mutex);
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index e695cd985369..d2475b3158cf 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -36,10 +36,15 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
 {
 	struct vfio_ccw_private *private =
 		container_of(vdev, struct vfio_ccw_private, vdev);
+	unsigned long flags;
 
 	/* Drivers MUST unpin pages in response to an invalidation. */
-	if (!cp_iova_pinned(&private->cp, iova, length))
+	spin_lock_irqsave(&private->cp_lock, flags);
+	if (!cp_iova_pinned(&private->cp, iova, length)) {
+		spin_unlock_irqrestore(&private->cp_lock, flags);
 		return;
+	}
+	spin_unlock_irqrestore(&private->cp_lock, flags);
 
 	vfio_ccw_mdev_reset(private);
 }
@@ -54,6 +59,7 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
 	INIT_LIST_HEAD(&private->crw);
 	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
 	INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
+	spin_lock_init(&private->cp_lock);
 
 	private->cp.guest_cp = kzalloc_objs(struct ccw1, CCWCHAIN_LEN_MAX);
 	if (!private->cp.guest_cp)
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index 0501d4bbcdbd..061b594fde36 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -115,7 +115,9 @@ struct vfio_ccw_private {
 	struct ccw_crw_region	*crw_region;
 	int num_regions;
 
+	spinlock_t		cp_lock;
 	struct channel_program	cp;
+
 	struct irb		irb;
 	union scsw		scsw;
 	struct list_head	crw;
-- 
2.53.0


  parent reply	other threads:[~2026-07-20 20:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 20:19 [PATCH v2 0/7] s390/vfio_ccw fixes Eric Farman
2026-07-20 20:19 ` [PATCH v2 1/7] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-20 20:31   ` sashiko-bot
2026-07-20 21:48   ` Farhan Ali
2026-07-20 20:19 ` [PATCH v2 2/7] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-20 20:30   ` sashiko-bot
2026-07-20 20:53     ` Eric Farman
2026-07-20 20:19 ` [PATCH v2 3/7] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-20 20:38   ` sashiko-bot
2026-07-20 20:19 ` [PATCH v2 4/7] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-20 20:33   ` sashiko-bot
2026-07-20 20:19 ` [PATCH v2 5/7] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-20 20:40   ` sashiko-bot
2026-07-20 20:19 ` Eric Farman [this message]
2026-07-20 20:39   ` [PATCH v2 6/7] s390/vfio_ccw: implement a channel program lock sashiko-bot
2026-07-20 20:19 ` [PATCH v2 7/7] s390/vfio_ccw: implement a crw lock Eric Farman
2026-07-20 20:47   ` sashiko-bot

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=20260720201931.976660-7-farman@linux.ibm.com \
    --to=farman@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mjrosato@linux.ibm.com \
    --cc=pasic@linux.ibm.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.