Lines Matching +full:04 +full:- +full:s390x +full:- +full:all +full:- +full:linux

7  * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
8 * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
9 * Pierre Morel <pmorel@linux.vnet.ibm.com>
13 * your option) any later version. See the COPYING file in the top-level
19 #include <linux/vfio.h>
20 #include <linux/vfio_ccw.h>
24 #include "hw/vfio/vfio-device.h"
26 #include "hw/s390x/s390-ccw.h"
27 #include "hw/s390x/vfio-ccw.h"
28 #include "hw/qdev-properties.h"
29 #include "hw/s390x/ccw-device.h"
30 #include "system/address-spaces.h"
31 #include "qemu/error-report.h"
32 #include "qemu/main-loop.h"
58 vdev->needs_reset = false; in vfio_ccw_compute_needs_reset()
71 VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); in vfio_ccw_handle_request()
72 struct ccw_io_region *region = vcdev->io_region; in vfio_ccw_handle_request()
75 if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH) && vcdev->force_orb_pfch) { in vfio_ccw_handle_request()
76 sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH; in vfio_ccw_handle_request()
77 warn_report_once("vfio-ccw (devno %x.%x.%04x): PFCH flag forced", in vfio_ccw_handle_request()
78 sch->cssid, sch->ssid, sch->devno); in vfio_ccw_handle_request()
81 QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB)); in vfio_ccw_handle_request()
82 QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW)); in vfio_ccw_handle_request()
83 QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB)); in vfio_ccw_handle_request()
87 memcpy(region->orb_area, &sch->orb, sizeof(ORB)); in vfio_ccw_handle_request()
88 memcpy(region->scsw_area, &sch->curr_status.scsw, sizeof(SCSW)); in vfio_ccw_handle_request()
91 ret = pwrite(vcdev->vdev.fd, region, in vfio_ccw_handle_request()
92 vcdev->io_region_size, vcdev->io_region_offset); in vfio_ccw_handle_request()
93 if (ret != vcdev->io_region_size) { in vfio_ccw_handle_request()
97 error_report("vfio-ccw: write I/O region failed with errno=%d", errno); in vfio_ccw_handle_request()
98 ret = errno ? -errno : -EFAULT; in vfio_ccw_handle_request()
105 case -EBUSY: in vfio_ccw_handle_request()
107 case -ENODEV: in vfio_ccw_handle_request()
108 case -EACCES: in vfio_ccw_handle_request()
110 case -EFAULT: in vfio_ccw_handle_request()
120 VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); in vfio_ccw_handle_store()
121 SCHIB *schib = &sch->curr_status; in vfio_ccw_handle_store()
122 struct ccw_schib_region *region = vcdev->schib_region; in vfio_ccw_handle_store()
132 ret = pread(vcdev->vdev.fd, region, vcdev->schib_region_size, in vfio_ccw_handle_store()
133 vcdev->schib_region_offset); in vfio_ccw_handle_store()
135 if (ret == -1) { in vfio_ccw_handle_store()
141 error_report("vfio-ccw: store region read failed with errno=%d", errno); in vfio_ccw_handle_store()
146 * Selectively copy path-related bits of the SCHIB, in vfio_ccw_handle_store()
149 s = (SCHIB *)region->schib_area; in vfio_ccw_handle_store()
150 schib->pmcw.pnom = s->pmcw.pnom; in vfio_ccw_handle_store()
151 schib->pmcw.lpum = s->pmcw.lpum; in vfio_ccw_handle_store()
152 schib->pmcw.pam = s->pmcw.pam; in vfio_ccw_handle_store()
153 schib->pmcw.pom = s->pmcw.pom; in vfio_ccw_handle_store()
155 if (s->scsw.flags & SCSW_FLAGS_MASK_PNO) { in vfio_ccw_handle_store()
156 schib->scsw.flags |= SCSW_FLAGS_MASK_PNO; in vfio_ccw_handle_store()
164 VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); in vfio_ccw_handle_clear()
165 struct ccw_cmd_region *region = vcdev->async_cmd_region; in vfio_ccw_handle_clear()
168 if (!vcdev->async_cmd_region) { in vfio_ccw_handle_clear()
170 return -ENOSYS; in vfio_ccw_handle_clear()
174 region->command = VFIO_CCW_ASYNC_CMD_CSCH; in vfio_ccw_handle_clear()
177 ret = pwrite(vcdev->vdev.fd, region, in vfio_ccw_handle_clear()
178 vcdev->async_cmd_region_size, vcdev->async_cmd_region_offset); in vfio_ccw_handle_clear()
179 if (ret != vcdev->async_cmd_region_size) { in vfio_ccw_handle_clear()
183 error_report("vfio-ccw: write cmd region failed with errno=%d", errno); in vfio_ccw_handle_clear()
184 ret = errno ? -errno : -EFAULT; in vfio_ccw_handle_clear()
190 case -ENODEV: in vfio_ccw_handle_clear()
191 case -EACCES: in vfio_ccw_handle_clear()
193 case -EFAULT: in vfio_ccw_handle_clear()
203 VFIOCCWDevice *vcdev = VFIO_CCW(sch->driver_data); in vfio_ccw_handle_halt()
204 struct ccw_cmd_region *region = vcdev->async_cmd_region; in vfio_ccw_handle_halt()
207 if (!vcdev->async_cmd_region) { in vfio_ccw_handle_halt()
209 return -ENOSYS; in vfio_ccw_handle_halt()
213 region->command = VFIO_CCW_ASYNC_CMD_HSCH; in vfio_ccw_handle_halt()
216 ret = pwrite(vcdev->vdev.fd, region, in vfio_ccw_handle_halt()
217 vcdev->async_cmd_region_size, vcdev->async_cmd_region_offset); in vfio_ccw_handle_halt()
218 if (ret != vcdev->async_cmd_region_size) { in vfio_ccw_handle_halt()
222 error_report("vfio-ccw: write cmd region failed with errno=%d", errno); in vfio_ccw_handle_halt()
223 ret = errno ? -errno : -EFAULT; in vfio_ccw_handle_halt()
229 case -EBUSY: in vfio_ccw_handle_halt()
230 case -ENODEV: in vfio_ccw_handle_halt()
231 case -EACCES: in vfio_ccw_handle_halt()
233 case -EFAULT: in vfio_ccw_handle_halt()
245 ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); in vfio_ccw_reset()
250 struct ccw_crw_region *region = vcdev->crw_region; in vfio_ccw_crw_read()
257 size = pread(vcdev->vdev.fd, region, vcdev->crw_region_size, in vfio_ccw_crw_read()
258 vcdev->crw_region_offset); in vfio_ccw_crw_read()
260 if (size == -1) { in vfio_ccw_crw_read()
261 error_report("vfio-ccw: Read crw region failed with errno=%d", in vfio_ccw_crw_read()
266 if (region->crw == 0) { in vfio_ccw_crw_read()
271 memcpy(&crw, &region->crw, sizeof(CRW)); in vfio_ccw_crw_read()
282 if (!event_notifier_test_and_clear(&vcdev->req_notifier)) { in vfio_ccw_req_notifier_handler()
288 warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); in vfio_ccw_req_notifier_handler()
296 while (event_notifier_test_and_clear(&vcdev->crw_notifier)) { in vfio_ccw_crw_notifier_handler()
304 struct ccw_io_region *region = vcdev->io_region; in vfio_ccw_io_notifier_handler()
306 SubchDev *sch = ccw_dev->sch; in vfio_ccw_io_notifier_handler()
307 SCHIB *schib = &sch->curr_status; in vfio_ccw_io_notifier_handler()
313 if (!event_notifier_test_and_clear(&vcdev->io_notifier)) { in vfio_ccw_io_notifier_handler()
317 size = pread(vcdev->vdev.fd, region, vcdev->io_region_size, in vfio_ccw_io_notifier_handler()
318 vcdev->io_region_offset); in vfio_ccw_io_notifier_handler()
319 if (size == -1) { in vfio_ccw_io_notifier_handler()
323 schib->scsw.flags |= SCSW_FLAGS_MASK_CC; in vfio_ccw_io_notifier_handler()
324 schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL; in vfio_ccw_io_notifier_handler()
325 schib->scsw.ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND); in vfio_ccw_io_notifier_handler()
329 schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND; in vfio_ccw_io_notifier_handler()
330 schib->scsw.cstat = SCSW_CSTAT_DATA_CHECK; in vfio_ccw_io_notifier_handler()
331 schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL; in vfio_ccw_io_notifier_handler()
332 schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY | in vfio_ccw_io_notifier_handler()
337 schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND; in vfio_ccw_io_notifier_handler()
338 schib->scsw.cstat = SCSW_CSTAT_PROG_CHECK; in vfio_ccw_io_notifier_handler()
339 schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL; in vfio_ccw_io_notifier_handler()
340 schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY | in vfio_ccw_io_notifier_handler()
344 } else if (size != vcdev->io_region_size) { in vfio_ccw_io_notifier_handler()
345 /* Information transfer error, generate channel-control check. */ in vfio_ccw_io_notifier_handler()
346 schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND; in vfio_ccw_io_notifier_handler()
347 schib->scsw.cstat = SCSW_CSTAT_CHN_CTRL_CHK; in vfio_ccw_io_notifier_handler()
348 schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL; in vfio_ccw_io_notifier_handler()
349 schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY | in vfio_ccw_io_notifier_handler()
354 memcpy(&irb, region->irb_area, sizeof(IRB)); in vfio_ccw_io_notifier_handler()
357 s = schib->scsw; in vfio_ccw_io_notifier_handler()
359 schib->scsw = s; in vfio_ccw_io_notifier_handler()
362 sch->esw = esw; in vfio_ccw_io_notifier_handler()
365 if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) && in vfio_ccw_io_notifier_handler()
366 (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) { in vfio_ccw_io_notifier_handler()
367 memcpy(sch->sense_data, irb.ecw, sizeof(irb.ecw)); in vfio_ccw_io_notifier_handler()
378 VFIODevice *vdev = &vcdev->vdev; in vfio_ccw_register_irq_notifier()
387 notifier = &vcdev->io_notifier; in vfio_ccw_register_irq_notifier()
391 notifier = &vcdev->crw_notifier; in vfio_ccw_register_irq_notifier()
395 notifier = &vcdev->req_notifier; in vfio_ccw_register_irq_notifier()
403 if (vdev->num_irqs < irq + 1) { in vfio_ccw_register_irq_notifier()
405 irq, vdev->num_irqs); in vfio_ccw_register_irq_notifier()
412 error_setg_errno(errp, -ret, "vfio: Error getting irq info"); in vfio_ccw_register_irq_notifier()
448 notifier = &vcdev->io_notifier; in vfio_ccw_unregister_irq_notifier()
451 notifier = &vcdev->crw_notifier; in vfio_ccw_unregister_irq_notifier()
454 notifier = &vcdev->req_notifier; in vfio_ccw_unregister_irq_notifier()
461 if (!vfio_device_irq_set_signaling(&vcdev->vdev, irq, 0, in vfio_ccw_unregister_irq_notifier()
462 VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) { in vfio_ccw_unregister_irq_notifier()
463 warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); in vfio_ccw_unregister_irq_notifier()
473 VFIODevice *vdev = &vcdev->vdev; in vfio_ccw_get_region()
478 if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) { in vfio_ccw_get_region()
479 error_setg(errp, "vfio: Um, this isn't a vfio-ccw device"); in vfio_ccw_get_region()
487 if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) { in vfio_ccw_get_region()
489 vdev->num_regions, VFIO_CCW_CONFIG_REGION_INDEX + 1); in vfio_ccw_get_region()
495 error_setg_errno(errp, -ret, "vfio: Error getting config info"); in vfio_ccw_get_region()
499 vcdev->io_region_size = info->size; in vfio_ccw_get_region()
500 if (sizeof(*vcdev->io_region) != vcdev->io_region_size) { in vfio_ccw_get_region()
505 vcdev->io_region_offset = info->offset; in vfio_ccw_get_region()
506 vcdev->io_region = g_malloc0(info->size); in vfio_ccw_get_region()
512 vcdev->async_cmd_region_size = info->size; in vfio_ccw_get_region()
513 if (sizeof(*vcdev->async_cmd_region) != vcdev->async_cmd_region_size) { in vfio_ccw_get_region()
517 vcdev->async_cmd_region_offset = info->offset; in vfio_ccw_get_region()
518 vcdev->async_cmd_region = g_malloc0(info->size); in vfio_ccw_get_region()
524 vcdev->schib_region_size = info->size; in vfio_ccw_get_region()
525 if (sizeof(*vcdev->schib_region) != vcdev->schib_region_size) { in vfio_ccw_get_region()
529 vcdev->schib_region_offset = info->offset; in vfio_ccw_get_region()
530 vcdev->schib_region = g_malloc(info->size); in vfio_ccw_get_region()
537 vcdev->crw_region_size = info->size; in vfio_ccw_get_region()
538 if (sizeof(*vcdev->crw_region) != vcdev->crw_region_size) { in vfio_ccw_get_region()
542 vcdev->crw_region_offset = info->offset; in vfio_ccw_get_region()
543 vcdev->crw_region = g_malloc(info->size); in vfio_ccw_get_region()
549 g_free(vcdev->crw_region); in vfio_ccw_get_region()
550 g_free(vcdev->schib_region); in vfio_ccw_get_region()
551 g_free(vcdev->async_cmd_region); in vfio_ccw_get_region()
552 g_free(vcdev->io_region); in vfio_ccw_get_region()
558 g_free(vcdev->crw_region); in vfio_ccw_put_region()
559 g_free(vcdev->schib_region); in vfio_ccw_put_region()
560 g_free(vcdev->async_cmd_region); in vfio_ccw_put_region()
561 g_free(vcdev->io_region); in vfio_ccw_put_region()
569 VFIODevice *vbasedev = &vcdev->vdev; in vfio_ccw_realize()
573 if (cdc->realize) { in vfio_ccw_realize()
574 if (!cdc->realize(cdev, vcdev->vdev.sysfsdev, errp)) { in vfio_ccw_realize()
583 if (!vfio_device_attach(cdev->mdevid, vbasedev, in vfio_ccw_realize()
596 if (vcdev->crw_region) { in vfio_ccw_realize()
622 g_free(vbasedev->name); in vfio_ccw_realize()
624 if (cdc->unrealize) { in vfio_ccw_realize()
625 cdc->unrealize(cdev); in vfio_ccw_realize()
639 vfio_device_detach(&vcdev->vdev); in vfio_ccw_unrealize()
640 g_free(vcdev->vdev.name); in vfio_ccw_unrealize()
642 if (cdc->unrealize) { in vfio_ccw_unrealize()
643 cdc->unrealize(cdev); in vfio_ccw_unrealize()
649 DEFINE_PROP_BOOL("force-orb-pfch", VFIOCCWDevice, force_orb_pfch, false),
658 .name = "vfio-ccw",
665 VFIODevice *vbasedev = &vcdev->vdev; in vfio_ccw_instance_init()
668 vbasedev->mdev = true; in vfio_ccw_instance_init()
671 * All vfio-ccw devices are believed to operate in a way compatible with in vfio_ccw_instance_init()
685 vfio_device_set_fd(&VFIO_CCW(obj)->vdev, str, errp); in vfio_ccw_set_fd()
698 dc->vmsd = &vfio_ccw_vmstate; in vfio_ccw_class_init()
699 dc->desc = "VFIO-based subchannel assignment"; in vfio_ccw_class_init()
700 set_bit(DEVICE_CATEGORY_MISC, dc->categories); in vfio_ccw_class_init()
701 dc->realize = vfio_ccw_realize; in vfio_ccw_class_init()
702 dc->unrealize = vfio_ccw_unrealize; in vfio_ccw_class_init()
705 cdc->handle_request = vfio_ccw_handle_request; in vfio_ccw_class_init()
706 cdc->handle_halt = vfio_ccw_handle_halt; in vfio_ccw_class_init()
707 cdc->handle_clear = vfio_ccw_handle_clear; in vfio_ccw_class_init()
708 cdc->handle_store = vfio_ccw_handle_store; in vfio_ccw_class_init()
714 "force-orb-pfch", in vfio_ccw_class_init()