Lines Matching +full:- +full:- +full:enable +full:- +full:trace +full:- +full:backend

2  * vfio based device assignment support - platform devices
11 * the COPYING file in the top-level directory.
23 #include "hw/vfio/vfio-platform.h"
26 #include "qemu/error-report.h"
28 #include "qemu/main-loop.h"
32 #include "system/address-spaces.h"
35 #include "trace.h"
37 #include "hw/platform-bus.h"
38 #include "hw/qdev-properties.h"
40 #include "hw/vfio/vfio-region.h"
48 return intp->flags & VFIO_IRQ_INFO_AUTOMASKED; in vfio_irq_is_automasked()
52 * vfio_init_intp - allocate, initialize the IRQ struct pointer
68 intp->vdev = vdev; in vfio_init_intp()
69 intp->pin = info.index; in vfio_init_intp()
70 intp->flags = info.flags; in vfio_init_intp()
71 intp->state = VFIO_IRQ_INACTIVE; in vfio_init_intp()
72 intp->kvm_accel = false; in vfio_init_intp()
74 sysbus_init_irq(sbdev, &intp->qemuirq); in vfio_init_intp()
77 intp->interrupt = g_new0(EventNotifier, 1); in vfio_init_intp()
78 ret = event_notifier_init(intp->interrupt, 0); in vfio_init_intp()
80 g_free(intp->interrupt); in vfio_init_intp()
82 error_setg_errno(errp, -ret, in vfio_init_intp()
88 intp->unmask = g_new0(EventNotifier, 1); in vfio_init_intp()
89 ret = event_notifier_init(intp->unmask, 0); in vfio_init_intp()
91 g_free(intp->interrupt); in vfio_init_intp()
92 g_free(intp->unmask); in vfio_init_intp()
94 error_setg_errno(errp, -ret, in vfio_init_intp()
100 QLIST_INSERT_HEAD(&vdev->intp_list, intp, next); in vfio_init_intp()
105 * vfio_set_trigger_eventfd - set VFIO eventfd handling
110 * Setup VFIO signaling and attach an optional user-side handler
116 VFIODevice *vbasedev = &intp->vdev->vbasedev; in vfio_set_trigger_eventfd()
117 int32_t fd = event_notifier_get_fd(intp->interrupt); in vfio_set_trigger_eventfd()
122 if (!vfio_device_irq_set_signaling(vbasedev, intp->pin, 0, in vfio_set_trigger_eventfd()
124 error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name); in vfio_set_trigger_eventfd()
126 return -EINVAL; in vfio_set_trigger_eventfd()
133 * Functions only used when eventfds are handled on user-side
138 * vfio_mmap_set_enabled - enable/disable the fast path mode
151 for (i = 0; i < vdev->vbasedev.num_regions; i++) { in vfio_mmap_set_enabled()
152 vfio_region_mmaps_set_enabled(vdev->regions[i], enabled); in vfio_mmap_set_enabled()
157 * vfio_intp_mmap_enable - timer function, restores the fast path
164 * if the IRQ is still active, the timer is re-programmed.
171 QEMU_LOCK_GUARD(&vdev->intp_mutex); in vfio_intp_mmap_enable()
172 QLIST_FOREACH(tmp, &vdev->intp_list, next) { in vfio_intp_mmap_enable()
173 if (tmp->state == VFIO_IRQ_ACTIVE) { in vfio_intp_mmap_enable()
174 trace_vfio_platform_intp_mmap_enable(tmp->pin); in vfio_intp_mmap_enable()
175 /* re-program the timer to check active status later */ in vfio_intp_mmap_enable()
176 timer_mod(vdev->mmap_timer, in vfio_intp_mmap_enable()
178 vdev->mmap_timeout); in vfio_intp_mmap_enable()
186 * vfio_intp_inject_pending_lockheld - Injects a pending IRQ
196 trace_vfio_platform_intp_inject_pending_lockheld(intp->pin, in vfio_intp_inject_pending_lockheld()
197 event_notifier_get_fd(intp->interrupt)); in vfio_intp_inject_pending_lockheld()
199 intp->state = VFIO_IRQ_ACTIVE; in vfio_intp_inject_pending_lockheld()
202 qemu_set_irq(intp->qemuirq, 1); in vfio_intp_inject_pending_lockheld()
206 * vfio_intp_interrupt - The user-side eventfd handler
217 VFIOPlatformDevice *vdev = intp->vdev; in vfio_intp_interrupt()
220 QEMU_LOCK_GUARD(&vdev->intp_mutex); in vfio_intp_interrupt()
221 if (intp->state == VFIO_IRQ_INACTIVE) { in vfio_intp_interrupt()
222 QLIST_FOREACH(tmp, &vdev->intp_list, next) { in vfio_intp_interrupt()
223 if (tmp->state == VFIO_IRQ_ACTIVE || in vfio_intp_interrupt()
224 tmp->state == VFIO_IRQ_PENDING) { in vfio_intp_interrupt()
235 intp->state = VFIO_IRQ_PENDING; in vfio_intp_interrupt()
236 trace_vfio_intp_interrupt_set_pending(intp->pin); in vfio_intp_interrupt()
237 QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue, in vfio_intp_interrupt()
239 event_notifier_test_and_clear(intp->interrupt); in vfio_intp_interrupt()
243 trace_vfio_platform_intp_interrupt(intp->pin, in vfio_intp_interrupt()
244 event_notifier_get_fd(intp->interrupt)); in vfio_intp_interrupt()
246 ret = event_notifier_test_and_clear(intp->interrupt); in vfio_intp_interrupt()
249 event_notifier_get_fd(intp->interrupt), ret); in vfio_intp_interrupt()
252 intp->state = VFIO_IRQ_ACTIVE; in vfio_intp_interrupt()
258 qemu_set_irq(intp->qemuirq, 1); in vfio_intp_interrupt()
264 if (vdev->mmap_timeout) { in vfio_intp_interrupt()
265 timer_mod(vdev->mmap_timer, in vfio_intp_interrupt()
267 vdev->mmap_timeout); in vfio_intp_interrupt()
272 * vfio_platform_eoi - IRQ completion routine
275 * De-asserts the active virtual IRQ and unmasks the physical IRQ
276 * (effective for level sensitive IRQ auto-masked by the VFIO driver).
292 QEMU_LOCK_GUARD(&vdev->intp_mutex); in vfio_platform_eoi()
293 QLIST_FOREACH(intp, &vdev->intp_list, next) { in vfio_platform_eoi()
294 if (intp->state == VFIO_IRQ_ACTIVE) { in vfio_platform_eoi()
295 trace_vfio_platform_eoi(intp->pin, in vfio_platform_eoi()
296 event_notifier_get_fd(intp->interrupt)); in vfio_platform_eoi()
297 intp->state = VFIO_IRQ_INACTIVE; in vfio_platform_eoi()
300 qemu_set_irq(intp->qemuirq, 0); in vfio_platform_eoi()
303 /* unmasks the physical level-sensitive IRQ */ in vfio_platform_eoi()
304 vfio_device_irq_unmask(vbasedev, intp->pin); in vfio_platform_eoi()
312 if (!QSIMPLEQ_EMPTY(&vdev->pending_intp_queue)) { in vfio_platform_eoi()
313 intp = QSIMPLEQ_FIRST(&vdev->pending_intp_queue); in vfio_platform_eoi()
315 QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext); in vfio_platform_eoi()
320 * vfio_start_eventfd_injection - starts the virtual IRQ injection using
321 * user-side handled eventfds
331 QLIST_FOREACH(intp, &vdev->intp_list, next) { in vfio_start_eventfd_injection()
332 if (intp->qemuirq == irq) { in vfio_start_eventfd_injection()
348 * vfio_set_resample_eventfd - sets the resamplefd for an IRQ
351 * intp->unmask eventfd is triggered
355 int32_t fd = event_notifier_get_fd(intp->unmask); in vfio_set_resample_eventfd()
356 VFIODevice *vbasedev = &intp->vdev->vbasedev; in vfio_set_resample_eventfd()
360 if (!vfio_device_irq_set_signaling(vbasedev, intp->pin, 0, in vfio_set_resample_eventfd()
362 error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name); in vfio_set_resample_eventfd()
363 return -EINVAL; in vfio_set_resample_eventfd()
369 * vfio_start_irqfd_injection - starts the virtual IRQ injection using
383 !vdev->irqfd_allowed) { in vfio_start_irqfd_injection()
387 QLIST_FOREACH(intp, &vdev->intp_list, next) { in vfio_start_irqfd_injection()
388 if (intp->qemuirq == irq) { in vfio_start_irqfd_injection()
394 if (kvm_irqchip_add_irqfd_notifier(kvm_state, intp->interrupt, in vfio_start_irqfd_injection()
395 intp->unmask, irq) < 0) { in vfio_start_irqfd_injection()
406 trace_vfio_platform_start_level_irqfd_injection(intp->pin, in vfio_start_irqfd_injection()
407 event_notifier_get_fd(intp->interrupt), in vfio_start_irqfd_injection()
408 event_notifier_get_fd(intp->unmask)); in vfio_start_irqfd_injection()
410 trace_vfio_platform_start_edge_irqfd_injection(intp->pin, in vfio_start_irqfd_injection()
411 event_notifier_get_fd(intp->interrupt)); in vfio_start_irqfd_injection()
414 intp->kvm_accel = true; in vfio_start_irqfd_injection()
418 kvm_irqchip_remove_irqfd_notifier(kvm_state, intp->interrupt, irq); in vfio_start_irqfd_injection()
428 vbasedev->needs_reset = true; in vfio_platform_compute_needs_reset()
434 return -1; in vfio_platform_hot_reset_multi()
438 * vfio_populate_device - Allocate and populate MMIO region
447 int i, ret = -1; in vfio_populate_device()
451 if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) { in vfio_populate_device()
456 vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions); in vfio_populate_device()
458 for (i = 0; i < vbasedev->num_regions; i++) { in vfio_populate_device()
459 char *name = g_strdup_printf("VFIO %s region %d\n", vbasedev->name, i); in vfio_populate_device()
461 vdev->regions[i] = g_new0(VFIORegion, 1); in vfio_populate_device()
463 vdev->regions[i], i, name); in vfio_populate_device()
466 error_setg_errno(errp, -ret, "failed to get region %d info", i); in vfio_populate_device()
471 vdev->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, in vfio_populate_device()
474 QSIMPLEQ_INIT(&vdev->pending_intp_queue); in vfio_populate_device()
476 for (i = 0; i < vbasedev->num_irqs; i++) { in vfio_populate_device()
482 error_setg_errno(errp, -ret, "failed to get device irq info"); in vfio_populate_device()
496 timer_del(vdev->mmap_timer); in vfio_populate_device()
497 QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) { in vfio_populate_device()
502 for (i = 0; i < vbasedev->num_regions; i++) { in vfio_populate_device()
503 if (vdev->regions[i]) { in vfio_populate_device()
504 vfio_region_finalize(vdev->regions[i]); in vfio_populate_device()
506 g_free(vdev->regions[i]); in vfio_populate_device()
508 g_free(vdev->regions); in vfio_populate_device()
520 * vfio_base_device_init - perform preliminary VFIO setup
532 if (vbasedev->fd < 0 && vbasedev->sysfsdev) { in vfio_base_device_init()
534 vbasedev->name = g_path_get_basename(vbasedev->sysfsdev); in vfio_base_device_init()
535 } else if (vbasedev->fd < 0) { in vfio_base_device_init()
536 if (!vbasedev->name || strchr(vbasedev->name, '/')) { in vfio_base_device_init()
541 vbasedev->sysfsdev = g_strdup_printf("/sys/bus/platform/devices/%s", in vfio_base_device_init()
542 vbasedev->name); in vfio_base_device_init()
549 if (!vfio_device_attach(vbasedev->name, vbasedev, in vfio_base_device_init()
563 * vfio_platform_realize - the device realize function
575 VFIODevice *vbasedev = &vdev->vbasedev; in vfio_platform_realize()
578 warn_report("-device vfio-platform is deprecated"); in vfio_platform_realize()
579 qemu_mutex_init(&vdev->intp_mutex); in vfio_platform_realize()
581 trace_vfio_platform_realize(vbasedev->sysfsdev ? in vfio_platform_realize()
582 vbasedev->sysfsdev : vbasedev->name, in vfio_platform_realize()
583 vdev->compat); in vfio_platform_realize()
589 if (!vdev->compat) { in vfio_platform_realize()
595 path = g_strdup_printf("%s/of_node/compatible", vbasedev->sysfsdev); in vfio_platform_realize()
597 error_setg(errp, "%s", gerr->message); in vfio_platform_realize()
603 vdev->compat = contents; in vfio_platform_realize()
604 for (vdev->num_compat = 0; length; vdev->num_compat++) { in vfio_platform_realize()
607 length -= skip; in vfio_platform_realize()
611 for (i = 0; i < vbasedev->num_regions; i++) { in vfio_platform_realize()
612 if (vfio_region_mmap(vdev->regions[i])) { in vfio_platform_realize()
614 memory_region_name(vdev->regions[i]->mem)); in vfio_platform_realize()
616 sysbus_init_mmio(sbdev, vdev->regions[i]->mem); in vfio_platform_realize()
621 if (vdev->vbasedev.name) { in vfio_platform_realize()
622 error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name); in vfio_platform_realize()
629 .name = "vfio-platform",
636 DEFINE_PROP_BOOL("x-no-mmap", VFIOPlatformDevice, vbasedev.no_mmap, false),
637 DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
639 DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
649 VFIODevice *vbasedev = &vdev->vbasedev; in vfio_platform_instance_init()
658 vfio_device_set_fd(&VFIO_PLATFORM_DEVICE(obj)->vbasedev, str, errp); in vfio_platform_set_fd()
667 dc->realize = vfio_platform_realize; in vfio_platform_class_init()
672 dc->vmsd = &vfio_platform_vmstate; in vfio_platform_class_init()
673 dc->desc = "VFIO-based platform device assignment"; in vfio_platform_class_init()
674 sbc->connect_irq_notifier = vfio_start_irqfd_injection; in vfio_platform_class_init()
675 set_bit(DEVICE_CATEGORY_MISC, dc->categories); in vfio_platform_class_init()
681 "x-no-mmap", in vfio_platform_class_init()
682 "Disable MMAP for device. Allows to trace MMIO " in vfio_platform_class_init()
685 "mmap-timeout-ms", in vfio_platform_class_init()
687 "(milliseconds) to re-enable device direct access " in vfio_platform_class_init()
690 "x-irqfd", in vfio_platform_class_init()
698 "Set host IOMMUFD backend device"); in vfio_platform_class_init()