On Mon, 20 May 2019 12:29:56 -0400 Eric Farman <far...@linux.ibm.com> wrote:
> On 5/7/19 11:47 AM, Cornelia Huck wrote: > > A vfio-ccw device may provide an async command subregion for > > issuing halt/clear subchannel requests. If it is present, use > > it for sending halt/clear request to the device; if not, fall > > back to emulation (as done today). > > > > Signed-off-by: Cornelia Huck <coh...@redhat.com> > > --- > > hw/s390x/css.c | 27 +++++++-- > > hw/vfio/ccw.c | 110 +++++++++++++++++++++++++++++++++++- > > include/hw/s390x/s390-ccw.h | 3 + > > 3 files changed, 134 insertions(+), 6 deletions(-) (...) > > +int vfio_ccw_handle_clear(SubchDev *sch) > > +{ > > + S390CCWDevice *cdev = sch->driver_data; > > + VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); > > + struct ccw_cmd_region *region = vcdev->async_cmd_region; > > + int ret; > > + > > + if (!vcdev->async_cmd_region) { > > + /* Async command region not available, fall back to emulation */ > > + return -ENOSYS; > > + } > > + > > + memset(region, 0, sizeof(*region)); > > + region->command = VFIO_CCW_ASYNC_CMD_CSCH; > > Considering the serialization you added on the kernel side, what happens > if another vcpu runs this code (or _halt) and clears the async region > before the kernel code gains control from the pwrite() call below? > Asked another way, there's nothing preventing us from issuing more than > one asynchronous command concurrently, so how do we make sure the > command gets to the kernel rather than "current command wins" ? Hm... good question. But unfortunately not one I can answer quickly, so I'll put off queuing this patch and just send a pull request without it. It's not like we're in a hurry :) > > That possibly worrisome question aside, this seems generally fine. Thanks for looking! > > + > > +again: > > + ret = pwrite(vcdev->vdev.fd, region, > > + vcdev->async_cmd_region_size, > > vcdev->async_cmd_region_offset); > > + if (ret != vcdev->async_cmd_region_size) { > > + if (errno == EAGAIN) { > > + goto again; > > + } > > + error_report("vfio-ccw: write cmd region failed with errno=%d", > > errno); > > + ret = -errno; > > + } else { > > + ret = region->ret_code; > > + } > > + switch (ret) { > > + case 0: > > + case -ENODEV: > > + case -EACCES: > > + return 0; > > + case -EFAULT: > > + default: > > + sch_gen_unit_exception(sch); > > + css_inject_io_interrupt(sch); > > + return 0; > > + }