From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433283174479.35936447759025; Fri, 1 Mar 2019 01:41:23 -0800 (PST) Received: from localhost ([127.0.0.1]:53527 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzefL-0002ub-3R for importer@patchew.org; Fri, 01 Mar 2019 04:41:15 -0500 Received: from eggs.gnu.org ([209.51.188.92]:37948) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzedW-0001ea-S9 for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzedU-0004As-VW for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36674) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzedS-00047G-NG; Fri, 01 Mar 2019 04:39:19 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F32AE6516E; Fri, 1 Mar 2019 09:39:14 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 889421001DFD; Fri, 1 Mar 2019 09:39:12 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:38:57 +0100 Message-Id: <20190301093902.27799-2-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 01 Mar 2019 09:39:15 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 1/6] vfio-ccw: make it safe to access channel programs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" When we get a solicited interrupt, the start function may have been cleared by a csch, but we still have a channel program structure allocated. Make it safe to call the cp accessors in any case, so we can call them unconditionally. While at it, also make sure that functions called from other parts of the code return gracefully if the channel program structure has not been initialized (even though that is a bug in the caller). Reviewed-by: Eric Farman Signed-off-by: Cornelia Huck Reviewed-by: Farhan Ali --- drivers/s390/cio/vfio_ccw_cp.c | 21 ++++++++++++++++++++- drivers/s390/cio/vfio_ccw_cp.h | 2 ++ drivers/s390/cio/vfio_ccw_fsm.c | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 384b3987eeb4..0e79799e9a71 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -362,6 +362,7 @@ static void cp_unpin_free(struct channel_program *cp) struct ccwchain *chain, *temp; int i; =20 + cp->initialized =3D false; list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) { for (i =3D 0; i < chain->ch_len; i++) { pfn_array_table_unpin_free(chain->ch_pat + i, @@ -732,6 +733,9 @@ int cp_init(struct channel_program *cp, struct device *= mdev, union orb *orb) */ cp->orb.cmd.c64 =3D 1; =20 + if (!ret) + cp->initialized =3D true; + return ret; } =20 @@ -746,7 +750,8 @@ int cp_init(struct channel_program *cp, struct device *= mdev, union orb *orb) */ void cp_free(struct channel_program *cp) { - cp_unpin_free(cp); + if (cp->initialized) + cp_unpin_free(cp); } =20 /** @@ -791,6 +796,10 @@ int cp_prefetch(struct channel_program *cp) struct ccwchain *chain; int len, idx, ret; =20 + /* this is an error in the caller */ + if (!cp->initialized) + return -EINVAL; + list_for_each_entry(chain, &cp->ccwchain_list, next) { len =3D chain->ch_len; for (idx =3D 0; idx < len; idx++) { @@ -826,6 +835,10 @@ union orb *cp_get_orb(struct channel_program *cp, u32 = intparm, u8 lpm) struct ccwchain *chain; struct ccw1 *cpa; =20 + /* this is an error in the caller */ + if (!cp->initialized) + return NULL; + orb =3D &cp->orb; =20 orb->cmd.intparm =3D intparm; @@ -862,6 +875,9 @@ void cp_update_scsw(struct channel_program *cp, union s= csw *scsw) u32 cpa =3D scsw->cmd.cpa; u32 ccw_head; =20 + if (!cp->initialized) + return; + /* * LATER: * For now, only update the cmd.cpa part. We may need to deal with @@ -898,6 +914,9 @@ bool cp_iova_pinned(struct channel_program *cp, u64 iov= a) struct ccwchain *chain; int i; =20 + if (!cp->initialized) + return false; + list_for_each_entry(chain, &cp->ccwchain_list, next) { for (i =3D 0; i < chain->ch_len; i++) if (pfn_array_table_iova_pinned(chain->ch_pat + i, diff --git a/drivers/s390/cio/vfio_ccw_cp.h b/drivers/s390/cio/vfio_ccw_cp.h index a4b74fb1aa57..3c20cd208da5 100644 --- a/drivers/s390/cio/vfio_ccw_cp.h +++ b/drivers/s390/cio/vfio_ccw_cp.h @@ -21,6 +21,7 @@ * @ccwchain_list: list head of ccwchains * @orb: orb for the currently processed ssch request * @mdev: the mediated device to perform page pinning/unpinning + * @initialized: whether this instance is actually initialized * * @ccwchain_list is the head of a ccwchain list, that contents the * translated result of the guest channel program that pointed out by @@ -30,6 +31,7 @@ struct channel_program { struct list_head ccwchain_list; union orb orb; struct device *mdev; + bool initialized; }; =20 extern int cp_init(struct channel_program *cp, struct device *mdev, diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fs= m.c index cab17865aafe..e7c9877c9f1e 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -31,6 +31,10 @@ static int fsm_io_helper(struct vfio_ccw_private *privat= e) private->state =3D VFIO_CCW_STATE_BUSY; =20 orb =3D cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm); + if (!orb) { + ret =3D -EIO; + goto out; + } =20 /* Issue "Start Subchannel" */ ccode =3D ssch(sch->schid, orb); @@ -64,6 +68,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private) default: ret =3D ccode; } +out: spin_unlock_irqrestore(sch->lock, flags); return ret; } --=20 2.17.2 From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433444161833.5298022211302; Fri, 1 Mar 2019 01:44:04 -0800 (PST) Received: from localhost ([127.0.0.1]:53559 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzei1-0005Kf-2w for importer@patchew.org; Fri, 01 Mar 2019 04:44:01 -0500 Received: from eggs.gnu.org ([209.51.188.92]:37971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzedY-0001fu-Nn for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzedW-0004C4-Tg for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57220) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzedV-0004AS-4w; Fri, 01 Mar 2019 04:39:22 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1A979A12CF; Fri, 1 Mar 2019 09:39:20 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 106385D9E1; Fri, 1 Mar 2019 09:39:16 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:38:58 +0100 Message-Id: <20190301093902.27799-3-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 01 Mar 2019 09:39:20 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 2/6] vfio-ccw: rework ssch state handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The flow for processing ssch requests can be improved by splitting the BUSY state: - CP_PROCESSING: We reject any user space requests while we are in the process of translating a channel program and submitting it to the hardware. Use -EAGAIN to signal user space that it should retry the request. - CP_PENDING: We have successfully submitted a request with ssch and are now expecting an interrupt. As we can't handle more than one channel program being processed, reject any further requests with -EBUSY. A final interrupt will move us out of this state; this also fixes a latent bug where a non-final interrupt might have freed up a channel program that still was in progress. By making this a separate state, we make it possible to issue a halt or a clear while we're still waiting for the final interrupt for the ssch (in a follow-on patch). It also makes a lot of sense not to preemptively filter out writes to the io_region if we're in an incorrect state: the state machine will handle this correctly. Reviewed-by: Eric Farman Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_drv.c | 8 ++++++-- drivers/s390/cio/vfio_ccw_fsm.c | 19 ++++++++++++++----- drivers/s390/cio/vfio_ccw_ops.c | 2 -- drivers/s390/cio/vfio_ccw_private.h | 3 ++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_dr= v.c index a10cec0e86eb..0b3b9de45c60 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -72,20 +72,24 @@ static void vfio_ccw_sch_io_todo(struct work_struct *wo= rk) { struct vfio_ccw_private *private; struct irb *irb; + bool is_final; =20 private =3D container_of(work, struct vfio_ccw_private, io_work); irb =3D &private->irb; =20 + is_final =3D !(scsw_actl(&irb->scsw) & + (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)); if (scsw_is_solicited(&irb->scsw)) { cp_update_scsw(&private->cp, &irb->scsw); - cp_free(&private->cp); + if (is_final) + cp_free(&private->cp); } memcpy(private->io_region->irb_area, irb, sizeof(*irb)); =20 if (private->io_trigger) eventfd_signal(private->io_trigger, 1); =20 - if (private->mdev) + if (private->mdev && is_final) private->state =3D VFIO_CCW_STATE_IDLE; } =20 diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fs= m.c index e7c9877c9f1e..b4a141fbd1a8 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -28,7 +28,6 @@ static int fsm_io_helper(struct vfio_ccw_private *private) sch =3D private->sch; =20 spin_lock_irqsave(sch->lock, flags); - private->state =3D VFIO_CCW_STATE_BUSY; =20 orb =3D cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm); if (!orb) { @@ -46,6 +45,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private) */ sch->schib.scsw.cmd.actl |=3D SCSW_ACTL_START_PEND; ret =3D 0; + private->state =3D VFIO_CCW_STATE_CP_PENDING; break; case 1: /* Status pending */ case 2: /* Busy */ @@ -107,6 +107,12 @@ static void fsm_io_busy(struct vfio_ccw_private *priva= te, private->io_region->ret_code =3D -EBUSY; } =20 +static void fsm_io_retry(struct vfio_ccw_private *private, + enum vfio_ccw_event event) +{ + private->io_region->ret_code =3D -EAGAIN; +} + static void fsm_disabled_irq(struct vfio_ccw_private *private, enum vfio_ccw_event event) { @@ -135,8 +141,7 @@ static void fsm_io_request(struct vfio_ccw_private *pri= vate, struct mdev_device *mdev =3D private->mdev; char *errstr =3D "request"; =20 - private->state =3D VFIO_CCW_STATE_BUSY; - + private->state =3D VFIO_CCW_STATE_CP_PROCESSING; memcpy(scsw, io_region->scsw_area, sizeof(*scsw)); =20 if (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) { @@ -181,7 +186,6 @@ static void fsm_io_request(struct vfio_ccw_private *pri= vate, } =20 err_out: - private->state =3D VFIO_CCW_STATE_IDLE; trace_vfio_ccw_io_fctl(scsw->cmd.fctl, get_schid(private), io_region->ret_code, errstr); } @@ -221,7 +225,12 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_= VFIO_CCW_EVENTS] =3D { [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_request, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, - [VFIO_CCW_STATE_BUSY] =3D { + [VFIO_CCW_STATE_CP_PROCESSING] =3D { + [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, + [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_retry, + [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, + }, + [VFIO_CCW_STATE_CP_PENDING] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_busy, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_op= s.c index f673e106c041..3fdcc6dfe0bf 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -193,8 +193,6 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *= mdev, return -EINVAL; =20 private =3D dev_get_drvdata(mdev_parent_dev(mdev)); - if (private->state !=3D VFIO_CCW_STATE_IDLE) - return -EACCES; =20 region =3D private->io_region; if (copy_from_user((void *)region + *ppos, buf, count)) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_cc= w_private.h index 08e9a7dc9176..50c52efb4fcb 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -63,7 +63,8 @@ enum vfio_ccw_state { VFIO_CCW_STATE_NOT_OPER, VFIO_CCW_STATE_STANDBY, VFIO_CCW_STATE_IDLE, - VFIO_CCW_STATE_BUSY, + VFIO_CCW_STATE_CP_PROCESSING, + VFIO_CCW_STATE_CP_PENDING, /* last element! */ NR_VFIO_CCW_STATES }; --=20 2.17.2 From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433292368169.32390276353522; Fri, 1 Mar 2019 01:41:32 -0800 (PST) Received: from localhost ([127.0.0.1]:53529 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzefV-00035S-2I for importer@patchew.org; Fri, 01 Mar 2019 04:41:25 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38013) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzedd-0001kC-EP for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzedc-0004Ex-F0 for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:29 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52742) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzeda-0004DC-K5; Fri, 01 Mar 2019 04:39:26 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CAD2BC074EEB; Fri, 1 Mar 2019 09:39:24 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2DD1618B5E; Fri, 1 Mar 2019 09:39:22 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:38:59 +0100 Message-Id: <20190301093902.27799-4-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 01 Mar 2019 09:39:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 3/6] vfio-ccw: protect the I/O region X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Introduce a mutex to disallow concurrent reads or writes to the I/O region. This makes sure that the data the kernel or user space see is always consistent. The same mutex will be used to protect the async region as well. Reviewed-by: Eric Farman Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_drv.c | 3 +++ drivers/s390/cio/vfio_ccw_ops.c | 28 +++++++++++++++++++--------- drivers/s390/cio/vfio_ccw_private.h | 2 ++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_dr= v.c index 0b3b9de45c60..5ea0da1dd954 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -84,7 +84,9 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work) if (is_final) cp_free(&private->cp); } + mutex_lock(&private->io_mutex); memcpy(private->io_region->irb_area, irb, sizeof(*irb)); + mutex_unlock(&private->io_mutex); =20 if (private->io_trigger) eventfd_signal(private->io_trigger, 1); @@ -129,6 +131,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) =20 private->sch =3D sch; dev_set_drvdata(&sch->dev, private); + mutex_init(&private->io_mutex); =20 spin_lock_irq(sch->lock); private->state =3D VFIO_CCW_STATE_NOT_OPER; diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_op= s.c index 3fdcc6dfe0bf..025c8a832bc8 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -169,16 +169,20 @@ static ssize_t vfio_ccw_mdev_read(struct mdev_device = *mdev, { struct vfio_ccw_private *private; struct ccw_io_region *region; + int ret; =20 if (*ppos + count > sizeof(*region)) return -EINVAL; =20 private =3D dev_get_drvdata(mdev_parent_dev(mdev)); + mutex_lock(&private->io_mutex); region =3D private->io_region; if (copy_to_user(buf, (void *)region + *ppos, count)) - return -EFAULT; - - return count; + ret =3D -EFAULT; + else + ret =3D count; + mutex_unlock(&private->io_mutex); + return ret; } =20 static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, @@ -188,23 +192,29 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device= *mdev, { struct vfio_ccw_private *private; struct ccw_io_region *region; + int ret; =20 if (*ppos + count > sizeof(*region)) return -EINVAL; =20 private =3D dev_get_drvdata(mdev_parent_dev(mdev)); + if (!mutex_trylock(&private->io_mutex)) + return -EAGAIN; =20 region =3D private->io_region; - if (copy_from_user((void *)region + *ppos, buf, count)) - return -EFAULT; + if (copy_from_user((void *)region + *ppos, buf, count)) { + ret =3D -EFAULT; + goto out_unlock; + } =20 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_IO_REQ); - if (region->ret_code !=3D 0) { + if (region->ret_code !=3D 0) private->state =3D VFIO_CCW_STATE_IDLE; - return region->ret_code; - } + ret =3D (region->ret_code !=3D 0) ? region->ret_code : count; =20 - return count; +out_unlock: + mutex_unlock(&private->io_mutex); + return ret; } =20 static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_cc= w_private.h index 50c52efb4fcb..32173cbd838d 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -28,6 +28,7 @@ * @mdev: pointer to the mediated device * @nb: notifier for vfio events * @io_region: MMIO region to input/output I/O arguments/results + * @io_mutex: protect against concurrent update of I/O regions * @cp: channel program for the current I/O operation * @irb: irb info received from interrupt * @scsw: scsw info @@ -42,6 +43,7 @@ struct vfio_ccw_private { struct mdev_device *mdev; struct notifier_block nb; struct ccw_io_region *io_region; + struct mutex io_mutex; =20 struct channel_program cp; struct irb irb; --=20 2.17.2 From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433636662180.81516568997029; Fri, 1 Mar 2019 01:47:16 -0800 (PST) Received: from localhost ([127.0.0.1]:53623 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzel3-0007wu-5y for importer@patchew.org; Fri, 01 Mar 2019 04:47:09 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38031) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzede-0001lD-Eq for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzedc-0004FK-WE for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:30 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44910) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzedc-0004Ec-N0; Fri, 01 Mar 2019 04:39:28 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 600E2C0AC910; Fri, 1 Mar 2019 09:39:27 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C1FF619C58; Fri, 1 Mar 2019 09:39:26 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:39:00 +0100 Message-Id: <20190301093902.27799-5-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 01 Mar 2019 09:39:27 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 4/6] vfio-ccw: add capabilities chain X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Allow to extend the regions used by vfio-ccw. The first user will be handling of halt and clear subchannel. Signed-off-by: Cornelia Huck Reviewed-by: Eric Farman Reviewed-by: Farhan Ali --- drivers/s390/cio/vfio_ccw_ops.c | 186 ++++++++++++++++++++++++---- drivers/s390/cio/vfio_ccw_private.h | 38 ++++++ include/uapi/linux/vfio.h | 2 + 3 files changed, 200 insertions(+), 26 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_op= s.c index 025c8a832bc8..3fd663320bbf 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -3,13 +3,16 @@ * Physical device callbacks for vfio_ccw * * Copyright IBM Corp. 2017 + * Copyright Red Hat, Inc. 2019 * * Author(s): Dong Jia Shi * Xiao Feng Ren + * Cornelia Huck */ =20 #include #include +#include =20 #include "vfio_ccw_private.h" =20 @@ -157,27 +160,33 @@ static void vfio_ccw_mdev_release(struct mdev_device = *mdev) { struct vfio_ccw_private *private =3D dev_get_drvdata(mdev_parent_dev(mdev)); + int i; =20 vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &private->nb); + + for (i =3D 0; i < private->num_regions; i++) + private->region[i].ops->release(private, &private->region[i]); + + private->num_regions =3D 0; + kfree(private->region); + private->region =3D NULL; } =20 -static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, - char __user *buf, - size_t count, - loff_t *ppos) +static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *priva= te, + char __user *buf, size_t count, + loff_t *ppos) { - struct vfio_ccw_private *private; + loff_t pos =3D *ppos & VFIO_CCW_OFFSET_MASK; struct ccw_io_region *region; int ret; =20 - if (*ppos + count > sizeof(*region)) + if (pos + count > sizeof(*region)) return -EINVAL; =20 - private =3D dev_get_drvdata(mdev_parent_dev(mdev)); mutex_lock(&private->io_mutex); region =3D private->io_region; - if (copy_to_user(buf, (void *)region + *ppos, count)) + if (copy_to_user(buf, (void *)region + pos, count)) ret =3D -EFAULT; else ret =3D count; @@ -185,24 +194,47 @@ static ssize_t vfio_ccw_mdev_read(struct mdev_device = *mdev, return ret; } =20 -static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, - const char __user *buf, - size_t count, - loff_t *ppos) +static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, + char __user *buf, + size_t count, + loff_t *ppos) { + unsigned int index =3D VFIO_CCW_OFFSET_TO_INDEX(*ppos); struct vfio_ccw_private *private; + + private =3D dev_get_drvdata(mdev_parent_dev(mdev)); + + if (index >=3D VFIO_CCW_NUM_REGIONS + private->num_regions) + return -EINVAL; + + switch (index) { + case VFIO_CCW_CONFIG_REGION_INDEX: + return vfio_ccw_mdev_read_io_region(private, buf, count, ppos); + default: + index -=3D VFIO_CCW_NUM_REGIONS; + return private->region[index].ops->read(private, buf, count, + ppos); + } + + return -EINVAL; +} + +static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *priv= ate, + const char __user *buf, + size_t count, loff_t *ppos) +{ + loff_t pos =3D *ppos & VFIO_CCW_OFFSET_MASK; struct ccw_io_region *region; int ret; =20 - if (*ppos + count > sizeof(*region)) + if (pos + count > sizeof(*region)) return -EINVAL; =20 - private =3D dev_get_drvdata(mdev_parent_dev(mdev)); if (!mutex_trylock(&private->io_mutex)) return -EAGAIN; =20 region =3D private->io_region; - if (copy_from_user((void *)region + *ppos, buf, count)) { + if (copy_from_user((void *)region + pos, buf, count)) { ret =3D -EFAULT; goto out_unlock; } @@ -217,19 +249,52 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device= *mdev, return ret; } =20 -static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info) +static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, + const char __user *buf, + size_t count, + loff_t *ppos) { + unsigned int index =3D VFIO_CCW_OFFSET_TO_INDEX(*ppos); + struct vfio_ccw_private *private; + + private =3D dev_get_drvdata(mdev_parent_dev(mdev)); + + if (index >=3D VFIO_CCW_NUM_REGIONS + private->num_regions) + return -EINVAL; + + switch (index) { + case VFIO_CCW_CONFIG_REGION_INDEX: + return vfio_ccw_mdev_write_io_region(private, buf, count, ppos); + default: + index -=3D VFIO_CCW_NUM_REGIONS; + return private->region[index].ops->write(private, buf, count, + ppos); + } + + return -EINVAL; +} + +static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, + struct mdev_device *mdev) +{ + struct vfio_ccw_private *private; + + private =3D dev_get_drvdata(mdev_parent_dev(mdev)); info->flags =3D VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; - info->num_regions =3D VFIO_CCW_NUM_REGIONS; + info->num_regions =3D VFIO_CCW_NUM_REGIONS + private->num_regions; info->num_irqs =3D VFIO_CCW_NUM_IRQS; =20 return 0; } =20 static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, - u16 *cap_type_id, - void **cap_type) + struct mdev_device *mdev, + unsigned long arg) { + struct vfio_ccw_private *private; + int i; + + private =3D dev_get_drvdata(mdev_parent_dev(mdev)); switch (info->index) { case VFIO_CCW_CONFIG_REGION_INDEX: info->offset =3D 0; @@ -237,9 +302,55 @@ static int vfio_ccw_mdev_get_region_info(struct vfio_r= egion_info *info, info->flags =3D VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; return 0; - default: - return -EINVAL; + default: /* all other regions are handled via capability chain */ + { + struct vfio_info_cap caps =3D { .buf =3D NULL, .size =3D 0 }; + struct vfio_region_info_cap_type cap_type =3D { + .header.id =3D VFIO_REGION_INFO_CAP_TYPE, + .header.version =3D 1 }; + int ret; + + if (info->index >=3D + VFIO_CCW_NUM_REGIONS + private->num_regions) + return -EINVAL; + + info->index =3D array_index_nospec(info->index, + VFIO_CCW_NUM_REGIONS + + private->num_regions); + + i =3D info->index - VFIO_CCW_NUM_REGIONS; + + info->offset =3D VFIO_CCW_INDEX_TO_OFFSET(info->index); + info->size =3D private->region[i].size; + info->flags =3D private->region[i].flags; + + cap_type.type =3D private->region[i].type; + cap_type.subtype =3D private->region[i].subtype; + + ret =3D vfio_info_add_capability(&caps, &cap_type.header, + sizeof(cap_type)); + if (ret) + return ret; + + info->flags |=3D VFIO_REGION_INFO_FLAG_CAPS; + if (info->argsz < sizeof(*info) + caps.size) { + info->argsz =3D sizeof(*info) + caps.size; + info->cap_offset =3D 0; + } else { + vfio_info_cap_shift(&caps, sizeof(*info)); + if (copy_to_user((void __user *)arg + sizeof(*info), + caps.buf, caps.size)) { + kfree(caps.buf); + return -EFAULT; + } + info->cap_offset =3D sizeof(*info); + } + + kfree(caps.buf); + + } } + return 0; } =20 static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info) @@ -316,6 +427,32 @@ static int vfio_ccw_mdev_set_irqs(struct mdev_device *= mdev, } } =20 +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, + unsigned int subtype, + const struct vfio_ccw_regops *ops, + size_t size, u32 flags, void *data) +{ + struct vfio_ccw_region *region; + + region =3D krealloc(private->region, + (private->num_regions + 1) * sizeof(*region), + GFP_KERNEL); + if (!region) + return -ENOMEM; + + private->region =3D region; + private->region[private->num_regions].type =3D VFIO_REGION_TYPE_CCW; + private->region[private->num_regions].subtype =3D subtype; + private->region[private->num_regions].ops =3D ops; + private->region[private->num_regions].size =3D size; + private->region[private->num_regions].flags =3D flags; + private->region[private->num_regions].data =3D data; + + private->num_regions++; + + return 0; +} + static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, unsigned int cmd, unsigned long arg) @@ -336,7 +473,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *= mdev, if (info.argsz < minsz) return -EINVAL; =20 - ret =3D vfio_ccw_mdev_get_device_info(&info); + ret =3D vfio_ccw_mdev_get_device_info(&info, mdev); if (ret) return ret; =20 @@ -345,8 +482,6 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *= mdev, case VFIO_DEVICE_GET_REGION_INFO: { struct vfio_region_info info; - u16 cap_type_id =3D 0; - void *cap_type =3D NULL; =20 minsz =3D offsetofend(struct vfio_region_info, offset); =20 @@ -356,8 +491,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *= mdev, if (info.argsz < minsz) return -EINVAL; =20 - ret =3D vfio_ccw_mdev_get_region_info(&info, &cap_type_id, - &cap_type); + ret =3D vfio_ccw_mdev_get_region_info(&info, mdev, arg); if (ret) return ret; =20 diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_cc= w_private.h index 32173cbd838d..d888a2573470 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -3,9 +3,11 @@ * Private stuff for vfio_ccw driver * * Copyright IBM Corp. 2017 + * Copyright Red Hat, Inc. 2019 * * Author(s): Dong Jia Shi * Xiao Feng Ren + * Cornelia Huck */ =20 #ifndef _VFIO_CCW_PRIVATE_H_ @@ -19,6 +21,38 @@ #include "css.h" #include "vfio_ccw_cp.h" =20 +#define VFIO_CCW_OFFSET_SHIFT 10 +#define VFIO_CCW_OFFSET_TO_INDEX(off) (off >> VFIO_CCW_OFFSET_SHIFT) +#define VFIO_CCW_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_CCW_OFFSET_S= HIFT) +#define VFIO_CCW_OFFSET_MASK (((u64)(1) << VFIO_CCW_OFFSET_SHIFT) - 1) + +/* capability chain handling similar to vfio-pci */ +struct vfio_ccw_private; +struct vfio_ccw_region; + +struct vfio_ccw_regops { + ssize_t (*read)(struct vfio_ccw_private *private, char __user *buf, + size_t count, loff_t *ppos); + ssize_t (*write)(struct vfio_ccw_private *private, + const char __user *buf, size_t count, loff_t *ppos); + void (*release)(struct vfio_ccw_private *private, + struct vfio_ccw_region *region); +}; + +struct vfio_ccw_region { + u32 type; + u32 subtype; + const struct vfio_ccw_regops *ops; + void *data; + size_t size; + u32 flags; +}; + +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, + unsigned int subtype, + const struct vfio_ccw_regops *ops, + size_t size, u32 flags, void *data); + /** * struct vfio_ccw_private * @sch: pointer to the subchannel @@ -29,6 +63,8 @@ * @nb: notifier for vfio events * @io_region: MMIO region to input/output I/O arguments/results * @io_mutex: protect against concurrent update of I/O regions + * @region: additional regions for other subchannel operations + * @num_regions: number of additional regions * @cp: channel program for the current I/O operation * @irb: irb info received from interrupt * @scsw: scsw info @@ -44,6 +80,8 @@ struct vfio_ccw_private { struct notifier_block nb; struct ccw_io_region *io_region; struct mutex io_mutex; + struct vfio_ccw_region *region; + int num_regions; =20 struct channel_program cp; struct irb irb; diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 02bb7ad6e986..56e2413d3e00 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -353,6 +353,8 @@ struct vfio_region_gfx_edid { #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2 }; =20 +#define VFIO_REGION_TYPE_CCW (2) + /* * 10de vendor sub-type * --=20 2.17.2 From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433296813765.4224430679028; Fri, 1 Mar 2019 01:41:36 -0800 (PST) Received: from localhost ([127.0.0.1]:53531 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzefZ-0003AD-Li for importer@patchew.org; Fri, 01 Mar 2019 04:41:29 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38049) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzedf-0001mH-HU for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzede-0004Gn-Qo for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:31 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57308) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzede-0004Fz-KA; Fri, 01 Mar 2019 04:39:30 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD51A8F2F1; Fri, 1 Mar 2019 09:39:29 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 68F2D1001E63; Fri, 1 Mar 2019 09:39:29 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:39:01 +0100 Message-Id: <20190301093902.27799-6-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 01 Mar 2019 09:39:29 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 5/6] s390/cio: export hsch to modules X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The vfio-ccw code will need this, and it matches treatment of ssch and csch. Reviewed-by: Pierre Morel Reviewed-by: Halil Pasic Signed-off-by: Cornelia Huck --- drivers/s390/cio/ioasm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 14d328338ce2..08eb10283b18 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -233,6 +233,7 @@ int hsch(struct subchannel_id schid) =20 return ccode; } +EXPORT_SYMBOL(hsch); =20 static inline int __xsch(struct subchannel_id schid) { --=20 2.17.2 From nobody Thu May 16 08:47:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551433445145600.4357365657438; Fri, 1 Mar 2019 01:44:05 -0800 (PST) Received: from localhost ([127.0.0.1]:53562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzei1-0005L6-T5 for importer@patchew.org; Fri, 01 Mar 2019 04:44:01 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38091) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzedq-0001wO-9K for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzedi-0004J4-Ue for qemu-devel@nongnu.org; Fri, 01 Mar 2019 04:39:40 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45006) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gzedi-0004Hu-CU; Fri, 01 Mar 2019 04:39:34 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A801BC0AD43E; Fri, 1 Mar 2019 09:39:32 +0000 (UTC) Received: from localhost (ovpn-117-66.ams2.redhat.com [10.36.117.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DFC4919C58; Fri, 1 Mar 2019 09:39:31 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Fri, 1 Mar 2019 10:39:02 +0100 Message-Id: <20190301093902.27799-7-cohuck@redhat.com> In-Reply-To: <20190301093902.27799-1-cohuck@redhat.com> References: <20190301093902.27799-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 01 Mar 2019 09:39:32 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 6/6] vfio-ccw: add handling for async channel instructions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a region to the vfio-ccw device that can be used to submit asynchronous I/O instructions. ssch continues to be handled by the existing I/O region; the new region handles hsch and csch. Interrupt status continues to be reported through the same channels as for ssch. Signed-off-by: Cornelia Huck Acked-by: Eric Farman Reviewed-by: Farhan Ali --- drivers/s390/cio/Makefile | 3 +- drivers/s390/cio/vfio_ccw_async.c | 88 ++++++++++++++++++++ drivers/s390/cio/vfio_ccw_drv.c | 46 ++++++++--- drivers/s390/cio/vfio_ccw_fsm.c | 119 +++++++++++++++++++++++++++- drivers/s390/cio/vfio_ccw_ops.c | 13 ++- drivers/s390/cio/vfio_ccw_private.h | 5 ++ include/uapi/linux/vfio.h | 2 + include/uapi/linux/vfio_ccw.h | 12 +++ 8 files changed, 270 insertions(+), 18 deletions(-) create mode 100644 drivers/s390/cio/vfio_ccw_async.c diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index f230516abb96..f6a8db04177c 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -20,5 +20,6 @@ obj-$(CONFIG_CCWGROUP) +=3D ccwgroup.o qdio-objs :=3D qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o obj-$(CONFIG_QDIO) +=3D qdio.o =20 -vfio_ccw-objs +=3D vfio_ccw_drv.o vfio_ccw_cp.o vfio_ccw_ops.o vfio_ccw_fs= m.o +vfio_ccw-objs +=3D vfio_ccw_drv.o vfio_ccw_cp.o vfio_ccw_ops.o vfio_ccw_fs= m.o \ + vfio_ccw_async.o obj-$(CONFIG_VFIO_CCW) +=3D vfio_ccw.o diff --git a/drivers/s390/cio/vfio_ccw_async.c b/drivers/s390/cio/vfio_ccw_= async.c new file mode 100644 index 000000000000..8c1d2357ef5b --- /dev/null +++ b/drivers/s390/cio/vfio_ccw_async.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Async I/O region for vfio_ccw + * + * Copyright Red Hat, Inc. 2019 + * + * Author(s): Cornelia Huck + */ + +#include +#include + +#include "vfio_ccw_private.h" + +static ssize_t vfio_ccw_async_region_read(struct vfio_ccw_private *private, + char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned int i =3D VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS; + loff_t pos =3D *ppos & VFIO_CCW_OFFSET_MASK; + struct ccw_cmd_region *region; + int ret; + + if (pos + count > sizeof(*region)) + return -EINVAL; + + mutex_lock(&private->io_mutex); + region =3D private->region[i].data; + if (copy_to_user(buf, (void *)region + pos, count)) + ret =3D -EFAULT; + else + ret =3D count; + mutex_unlock(&private->io_mutex); + return ret; +} + +static ssize_t vfio_ccw_async_region_write(struct vfio_ccw_private *privat= e, + const char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned int i =3D VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS; + loff_t pos =3D *ppos & VFIO_CCW_OFFSET_MASK; + struct ccw_cmd_region *region; + int ret; + + if (pos + count > sizeof(*region)) + return -EINVAL; + + if (!mutex_trylock(&private->io_mutex)) + return -EAGAIN; + + region =3D private->region[i].data; + if (copy_from_user((void *)region + pos, buf, count)) { + ret =3D -EFAULT; + goto out_unlock; + } + + vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_ASYNC_REQ); + + ret =3D region->ret_code ? region->ret_code : count; + +out_unlock: + mutex_unlock(&private->io_mutex); + return ret; +} + +static void vfio_ccw_async_region_release(struct vfio_ccw_private *private, + struct vfio_ccw_region *region) +{ + +} + +const struct vfio_ccw_regops vfio_ccw_async_region_ops =3D { + .read =3D vfio_ccw_async_region_read, + .write =3D vfio_ccw_async_region_write, + .release =3D vfio_ccw_async_region_release, +}; + +int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private) +{ + return vfio_ccw_register_dev_region(private, + VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD, + &vfio_ccw_async_region_ops, + sizeof(struct ccw_cmd_region), + VFIO_REGION_INFO_FLAG_READ | + VFIO_REGION_INFO_FLAG_WRITE, + private->cmd_region); +} diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_dr= v.c index 5ea0da1dd954..c39d01943a6a 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -3,9 +3,11 @@ * VFIO based Physical Subchannel device driver * * Copyright IBM Corp. 2017 + * Copyright Red Hat, Inc. 2019 * * Author(s): Dong Jia Shi * Xiao Feng Ren + * Cornelia Huck */ =20 #include @@ -23,6 +25,7 @@ =20 struct workqueue_struct *vfio_ccw_work_q; static struct kmem_cache *vfio_ccw_io_region; +static struct kmem_cache *vfio_ccw_cmd_region; =20 /* * Helpers @@ -110,7 +113,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) { struct pmcw *pmcw =3D &sch->schib.pmcw; struct vfio_ccw_private *private; - int ret; + int ret =3D -ENOMEM; =20 if (pmcw->qf) { dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n", @@ -124,10 +127,13 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) =20 private->io_region =3D kmem_cache_zalloc(vfio_ccw_io_region, GFP_KERNEL | GFP_DMA); - if (!private->io_region) { - kfree(private); - return -ENOMEM; - } + if (!private->io_region) + goto out_free; + + private->cmd_region =3D kmem_cache_zalloc(vfio_ccw_cmd_region, + GFP_KERNEL | GFP_DMA); + if (!private->cmd_region) + goto out_free; =20 private->sch =3D sch; dev_set_drvdata(&sch->dev, private); @@ -155,7 +161,10 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) cio_disable_subchannel(sch); out_free: dev_set_drvdata(&sch->dev, NULL); - kmem_cache_free(vfio_ccw_io_region, private->io_region); + if (private->cmd_region) + kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); + if (private->io_region) + kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private); return ret; } @@ -170,6 +179,7 @@ static int vfio_ccw_sch_remove(struct subchannel *sch) =20 dev_set_drvdata(&sch->dev, NULL); =20 + kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private); =20 @@ -244,7 +254,7 @@ static struct css_driver vfio_ccw_sch_driver =3D { =20 static int __init vfio_ccw_sch_init(void) { - int ret; + int ret =3D -ENOMEM; =20 vfio_ccw_work_q =3D create_singlethread_workqueue("vfio-ccw"); if (!vfio_ccw_work_q) @@ -254,20 +264,30 @@ static int __init vfio_ccw_sch_init(void) sizeof(struct ccw_io_region), 0, SLAB_ACCOUNT, 0, sizeof(struct ccw_io_region), NULL); - if (!vfio_ccw_io_region) { - destroy_workqueue(vfio_ccw_work_q); - return -ENOMEM; - } + if (!vfio_ccw_io_region) + goto out_err; + + vfio_ccw_cmd_region =3D kmem_cache_create_usercopy("vfio_ccw_cmd_region", + sizeof(struct ccw_cmd_region), 0, + SLAB_ACCOUNT, 0, + sizeof(struct ccw_cmd_region), NULL); + if (!vfio_ccw_cmd_region) + goto out_err; =20 isc_register(VFIO_CCW_ISC); ret =3D css_driver_register(&vfio_ccw_sch_driver); if (ret) { isc_unregister(VFIO_CCW_ISC); - kmem_cache_destroy(vfio_ccw_io_region); - destroy_workqueue(vfio_ccw_work_q); + goto out_err; } =20 return ret; + +out_err: + kmem_cache_destroy(vfio_ccw_cmd_region); + kmem_cache_destroy(vfio_ccw_io_region); + destroy_workqueue(vfio_ccw_work_q); + return ret; } =20 static void __exit vfio_ccw_sch_exit(void) diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fs= m.c index b4a141fbd1a8..49d9d3da0282 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -3,8 +3,10 @@ * Finite state machine for vfio-ccw device handling * * Copyright IBM Corp. 2017 + * Copyright Red Hat, Inc. 2019 * * Author(s): Dong Jia Shi + * Cornelia Huck */ =20 #include @@ -73,6 +75,75 @@ static int fsm_io_helper(struct vfio_ccw_private *privat= e) return ret; } =20 +static int fsm_do_halt(struct vfio_ccw_private *private) +{ + struct subchannel *sch; + unsigned long flags; + int ccode; + int ret; + + sch =3D private->sch; + + spin_lock_irqsave(sch->lock, flags); + + /* Issue "Halt Subchannel" */ + ccode =3D hsch(sch->schid); + + switch (ccode) { + case 0: + /* + * Initialize device status information + */ + sch->schib.scsw.cmd.actl |=3D SCSW_ACTL_HALT_PEND; + ret =3D 0; + break; + case 1: /* Status pending */ + case 2: /* Busy */ + ret =3D -EBUSY; + break; + case 3: /* Device not operational */ + ret =3D -ENODEV; + break; + default: + ret =3D ccode; + } + spin_unlock_irqrestore(sch->lock, flags); + return ret; +} + +static int fsm_do_clear(struct vfio_ccw_private *private) +{ + struct subchannel *sch; + unsigned long flags; + int ccode; + int ret; + + sch =3D private->sch; + + spin_lock_irqsave(sch->lock, flags); + + /* Issue "Clear Subchannel" */ + ccode =3D csch(sch->schid); + + switch (ccode) { + case 0: + /* + * Initialize device status information + */ + sch->schib.scsw.cmd.actl =3D SCSW_ACTL_CLEAR_PEND; + /* TODO: check what else we might need to clear */ + ret =3D 0; + break; + case 3: /* Device not operational */ + ret =3D -ENODEV; + break; + default: + ret =3D ccode; + } + spin_unlock_irqrestore(sch->lock, flags); + return ret; +} + static void fsm_notoper(struct vfio_ccw_private *private, enum vfio_ccw_event event) { @@ -113,6 +184,24 @@ static void fsm_io_retry(struct vfio_ccw_private *priv= ate, private->io_region->ret_code =3D -EAGAIN; } =20 +static void fsm_async_error(struct vfio_ccw_private *private, + enum vfio_ccw_event event) +{ + struct ccw_cmd_region *cmd_region =3D private->cmd_region; + + pr_err("vfio-ccw: FSM: %s request from state:%d\n", + cmd_region->command =3D=3D VFIO_CCW_ASYNC_CMD_HSCH ? "halt" : + cmd_region->command =3D=3D VFIO_CCW_ASYNC_CMD_CSCH ? "clear" : + "", private->state); + cmd_region->ret_code =3D -EIO; +} + +static void fsm_async_retry(struct vfio_ccw_private *private, + enum vfio_ccw_event event) +{ + private->cmd_region->ret_code =3D -EAGAIN; +} + static void fsm_disabled_irq(struct vfio_ccw_private *private, enum vfio_ccw_event event) { @@ -176,11 +265,11 @@ static void fsm_io_request(struct vfio_ccw_private *p= rivate, } return; } else if (scsw->cmd.fctl & SCSW_FCTL_HALT_FUNC) { - /* XXX: Handle halt. */ + /* halt is handled via the async cmd region */ io_region->ret_code =3D -EOPNOTSUPP; goto err_out; } else if (scsw->cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { - /* XXX: Handle clear. */ + /* clear is handled via the async cmd region */ io_region->ret_code =3D -EOPNOTSUPP; goto err_out; } @@ -190,6 +279,27 @@ static void fsm_io_request(struct vfio_ccw_private *pr= ivate, io_region->ret_code, errstr); } =20 +/* + * Deal with an async request from userspace. + */ +static void fsm_async_request(struct vfio_ccw_private *private, + enum vfio_ccw_event event) +{ + struct ccw_cmd_region *cmd_region =3D private->cmd_region; + + switch (cmd_region->command) { + case VFIO_CCW_ASYNC_CMD_HSCH: + cmd_region->ret_code =3D fsm_do_halt(private); + break; + case VFIO_CCW_ASYNC_CMD_CSCH: + cmd_region->ret_code =3D fsm_do_clear(private); + break; + default: + /* should not happen? */ + cmd_region->ret_code =3D -EINVAL; + } +} + /* * Got an interrupt for a normal io (state busy). */ @@ -213,26 +323,31 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR= _VFIO_CCW_EVENTS] =3D { [VFIO_CCW_STATE_NOT_OPER] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_nop, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_error, + [VFIO_CCW_EVENT_ASYNC_REQ] =3D fsm_async_error, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_disabled_irq, }, [VFIO_CCW_STATE_STANDBY] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_error, + [VFIO_CCW_EVENT_ASYNC_REQ] =3D fsm_async_error, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, [VFIO_CCW_STATE_IDLE] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_request, + [VFIO_CCW_EVENT_ASYNC_REQ] =3D fsm_async_request, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, [VFIO_CCW_STATE_CP_PROCESSING] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_retry, + [VFIO_CCW_EVENT_ASYNC_REQ] =3D fsm_async_retry, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, [VFIO_CCW_STATE_CP_PENDING] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_busy, + [VFIO_CCW_EVENT_ASYNC_REQ] =3D fsm_async_request, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, }; diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_op= s.c index 3fd663320bbf..ec2f796c70fe 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -149,11 +149,20 @@ static int vfio_ccw_mdev_open(struct mdev_device *mde= v) struct vfio_ccw_private *private =3D dev_get_drvdata(mdev_parent_dev(mdev)); unsigned long events =3D VFIO_IOMMU_NOTIFY_DMA_UNMAP; + int ret; =20 private->nb.notifier_call =3D vfio_ccw_mdev_notifier; =20 - return vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, - &events, &private->nb); + ret =3D vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, + &events, &private->nb); + if (ret) + return ret; + + ret =3D vfio_ccw_register_async_dev_regions(private); + if (ret) + vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, + &private->nb); + return ret; } =20 static void vfio_ccw_mdev_release(struct mdev_device *mdev) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_cc= w_private.h index d888a2573470..f1092c3dc1b1 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -53,6 +53,8 @@ int vfio_ccw_register_dev_region(struct vfio_ccw_private = *private, const struct vfio_ccw_regops *ops, size_t size, u32 flags, void *data); =20 +int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private); + /** * struct vfio_ccw_private * @sch: pointer to the subchannel @@ -64,6 +66,7 @@ int vfio_ccw_register_dev_region(struct vfio_ccw_private = *private, * @io_region: MMIO region to input/output I/O arguments/results * @io_mutex: protect against concurrent update of I/O regions * @region: additional regions for other subchannel operations + * @cmd_region: MMIO region for asynchronous I/O commands other than START * @num_regions: number of additional regions * @cp: channel program for the current I/O operation * @irb: irb info received from interrupt @@ -81,6 +84,7 @@ struct vfio_ccw_private { struct ccw_io_region *io_region; struct mutex io_mutex; struct vfio_ccw_region *region; + struct ccw_cmd_region *cmd_region; int num_regions; =20 struct channel_program cp; @@ -116,6 +120,7 @@ enum vfio_ccw_event { VFIO_CCW_EVENT_NOT_OPER, VFIO_CCW_EVENT_IO_REQ, VFIO_CCW_EVENT_INTERRUPT, + VFIO_CCW_EVENT_ASYNC_REQ, /* last element! */ NR_VFIO_CCW_EVENTS }; diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 56e2413d3e00..8f10748dac79 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -354,6 +354,8 @@ struct vfio_region_gfx_edid { }; =20 #define VFIO_REGION_TYPE_CCW (2) +/* ccw sub-types */ +#define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1) =20 /* * 10de vendor sub-type diff --git a/include/uapi/linux/vfio_ccw.h b/include/uapi/linux/vfio_ccw.h index 2ec5f367ff78..cbecbf0cd54f 100644 --- a/include/uapi/linux/vfio_ccw.h +++ b/include/uapi/linux/vfio_ccw.h @@ -12,6 +12,7 @@ =20 #include =20 +/* used for START SUBCHANNEL, always present */ struct ccw_io_region { #define ORB_AREA_SIZE 12 __u8 orb_area[ORB_AREA_SIZE]; @@ -22,4 +23,15 @@ struct ccw_io_region { __u32 ret_code; } __packed; =20 +/* + * used for processing commands that trigger asynchronous actions + * Note: this is controlled by a capability + */ +#define VFIO_CCW_ASYNC_CMD_HSCH (1 << 0) +#define VFIO_CCW_ASYNC_CMD_CSCH (1 << 1) +struct ccw_cmd_region { + __u32 command; + __u32 ret_code; +} __packed; + #endif --=20 2.17.2