cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

platform.c (21636B)


      1/*
      2 * vfio based device assignment support - platform devices
      3 *
      4 * Copyright Linaro Limited, 2014
      5 *
      6 * Authors:
      7 *  Kim Phillips <kim.phillips@linaro.org>
      8 *  Eric Auger <eric.auger@linaro.org>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2.  See
     11 * the COPYING file in the top-level directory.
     12 *
     13 * Based on vfio based PCI device assignment support:
     14 *  Copyright Red Hat, Inc. 2012
     15 */
     16
     17#include "qemu/osdep.h"
     18#include "qapi/error.h"
     19#include <sys/ioctl.h>
     20#include <linux/vfio.h>
     21
     22#include "hw/vfio/vfio-platform.h"
     23#include "migration/vmstate.h"
     24#include "qemu/error-report.h"
     25#include "qemu/lockable.h"
     26#include "qemu/main-loop.h"
     27#include "qemu/module.h"
     28#include "qemu/range.h"
     29#include "exec/memory.h"
     30#include "exec/address-spaces.h"
     31#include "qemu/queue.h"
     32#include "hw/sysbus.h"
     33#include "trace.h"
     34#include "hw/irq.h"
     35#include "hw/platform-bus.h"
     36#include "hw/qdev-properties.h"
     37#include "sysemu/kvm.h"
     38
     39/*
     40 * Functions used whatever the injection method
     41 */
     42
     43static inline bool vfio_irq_is_automasked(VFIOINTp *intp)
     44{
     45    return intp->flags & VFIO_IRQ_INFO_AUTOMASKED;
     46}
     47
     48/**
     49 * vfio_init_intp - allocate, initialize the IRQ struct pointer
     50 * and add it into the list of IRQs
     51 * @vbasedev: the VFIO device handle
     52 * @info: irq info struct retrieved from VFIO driver
     53 * @errp: error object
     54 */
     55static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
     56                                struct vfio_irq_info info, Error **errp)
     57{
     58    int ret;
     59    VFIOPlatformDevice *vdev =
     60        container_of(vbasedev, VFIOPlatformDevice, vbasedev);
     61    SysBusDevice *sbdev = SYS_BUS_DEVICE(vdev);
     62    VFIOINTp *intp;
     63
     64    intp = g_malloc0(sizeof(*intp));
     65    intp->vdev = vdev;
     66    intp->pin = info.index;
     67    intp->flags = info.flags;
     68    intp->state = VFIO_IRQ_INACTIVE;
     69    intp->kvm_accel = false;
     70
     71    sysbus_init_irq(sbdev, &intp->qemuirq);
     72
     73    /* Get an eventfd for trigger */
     74    intp->interrupt = g_malloc0(sizeof(EventNotifier));
     75    ret = event_notifier_init(intp->interrupt, 0);
     76    if (ret) {
     77        g_free(intp->interrupt);
     78        g_free(intp);
     79        error_setg_errno(errp, -ret,
     80                         "failed to initialize trigger eventfd notifier");
     81        return NULL;
     82    }
     83    if (vfio_irq_is_automasked(intp)) {
     84        /* Get an eventfd for resample/unmask */
     85        intp->unmask = g_malloc0(sizeof(EventNotifier));
     86        ret = event_notifier_init(intp->unmask, 0);
     87        if (ret) {
     88            g_free(intp->interrupt);
     89            g_free(intp->unmask);
     90            g_free(intp);
     91            error_setg_errno(errp, -ret,
     92                             "failed to initialize resample eventfd notifier");
     93            return NULL;
     94        }
     95    }
     96
     97    QLIST_INSERT_HEAD(&vdev->intp_list, intp, next);
     98    return intp;
     99}
    100
    101/**
    102 * vfio_set_trigger_eventfd - set VFIO eventfd handling
    103 *
    104 * @intp: IRQ struct handle
    105 * @handler: handler to be called on eventfd signaling
    106 *
    107 * Setup VFIO signaling and attach an optional user-side handler
    108 * to the eventfd
    109 */
    110static int vfio_set_trigger_eventfd(VFIOINTp *intp,
    111                                    eventfd_user_side_handler_t handler)
    112{
    113    VFIODevice *vbasedev = &intp->vdev->vbasedev;
    114    int32_t fd = event_notifier_get_fd(intp->interrupt);
    115    Error *err = NULL;
    116    int ret;
    117
    118    qemu_set_fd_handler(fd, (IOHandler *)handler, NULL, intp);
    119
    120    ret = vfio_set_irq_signaling(vbasedev, intp->pin, 0,
    121                                 VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err);
    122    if (ret) {
    123        error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
    124        qemu_set_fd_handler(fd, NULL, NULL, NULL);
    125    }
    126
    127    return ret;
    128}
    129
    130/*
    131 * Functions only used when eventfds are handled on user-side
    132 * ie. without irqfd
    133 */
    134
    135/**
    136 * vfio_mmap_set_enabled - enable/disable the fast path mode
    137 * @vdev: the VFIO platform device
    138 * @enabled: the target mmap state
    139 *
    140 * enabled = true ~ fast path = MMIO region is mmaped (no KVM TRAP);
    141 * enabled = false ~ slow path = MMIO region is trapped and region callbacks
    142 * are called; slow path enables to trap the device IRQ status register reset
    143*/
    144
    145static void vfio_mmap_set_enabled(VFIOPlatformDevice *vdev, bool enabled)
    146{
    147    int i;
    148
    149    for (i = 0; i < vdev->vbasedev.num_regions; i++) {
    150        vfio_region_mmaps_set_enabled(vdev->regions[i], enabled);
    151    }
    152}
    153
    154/**
    155 * vfio_intp_mmap_enable - timer function, restores the fast path
    156 * if there is no more active IRQ
    157 * @opaque: actually points to the VFIO platform device
    158 *
    159 * Called on mmap timer timeout, this function checks whether the
    160 * IRQ is still active and if not, restores the fast path.
    161 * by construction a single eventfd is handled at a time.
    162 * if the IRQ is still active, the timer is re-programmed.
    163 */
    164static void vfio_intp_mmap_enable(void *opaque)
    165{
    166    VFIOINTp *tmp;
    167    VFIOPlatformDevice *vdev = (VFIOPlatformDevice *)opaque;
    168
    169    QEMU_LOCK_GUARD(&vdev->intp_mutex);
    170    QLIST_FOREACH(tmp, &vdev->intp_list, next) {
    171        if (tmp->state == VFIO_IRQ_ACTIVE) {
    172            trace_vfio_platform_intp_mmap_enable(tmp->pin);
    173            /* re-program the timer to check active status later */
    174            timer_mod(vdev->mmap_timer,
    175                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    176                          vdev->mmap_timeout);
    177            return;
    178        }
    179    }
    180    vfio_mmap_set_enabled(vdev, true);
    181}
    182
    183/**
    184 * vfio_intp_inject_pending_lockheld - Injects a pending IRQ
    185 * @opaque: opaque pointer, in practice the VFIOINTp handle
    186 *
    187 * The function is called on a previous IRQ completion, from
    188 * vfio_platform_eoi, while the intp_mutex is locked.
    189 * Also in such situation, the slow path already is set and
    190 * the mmap timer was already programmed.
    191 */
    192static void vfio_intp_inject_pending_lockheld(VFIOINTp *intp)
    193{
    194    trace_vfio_platform_intp_inject_pending_lockheld(intp->pin,
    195                              event_notifier_get_fd(intp->interrupt));
    196
    197    intp->state = VFIO_IRQ_ACTIVE;
    198
    199    /* trigger the virtual IRQ */
    200    qemu_set_irq(intp->qemuirq, 1);
    201}
    202
    203/**
    204 * vfio_intp_interrupt - The user-side eventfd handler
    205 * @opaque: opaque pointer which in practice is the VFIOINTp handle
    206 *
    207 * the function is entered in event handler context:
    208 * the vIRQ is injected into the guest if there is no other active
    209 * or pending IRQ.
    210 */
    211static void vfio_intp_interrupt(VFIOINTp *intp)
    212{
    213    int ret;
    214    VFIOINTp *tmp;
    215    VFIOPlatformDevice *vdev = intp->vdev;
    216    bool delay_handling = false;
    217
    218    QEMU_LOCK_GUARD(&vdev->intp_mutex);
    219    if (intp->state == VFIO_IRQ_INACTIVE) {
    220        QLIST_FOREACH(tmp, &vdev->intp_list, next) {
    221            if (tmp->state == VFIO_IRQ_ACTIVE ||
    222                tmp->state == VFIO_IRQ_PENDING) {
    223                delay_handling = true;
    224                break;
    225            }
    226        }
    227    }
    228    if (delay_handling) {
    229        /*
    230         * the new IRQ gets a pending status and is pushed in
    231         * the pending queue
    232         */
    233        intp->state = VFIO_IRQ_PENDING;
    234        trace_vfio_intp_interrupt_set_pending(intp->pin);
    235        QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue,
    236                             intp, pqnext);
    237        event_notifier_test_and_clear(intp->interrupt);
    238        return;
    239    }
    240
    241    trace_vfio_platform_intp_interrupt(intp->pin,
    242                              event_notifier_get_fd(intp->interrupt));
    243
    244    ret = event_notifier_test_and_clear(intp->interrupt);
    245    if (!ret) {
    246        error_report("Error when clearing fd=%d (ret = %d)",
    247                     event_notifier_get_fd(intp->interrupt), ret);
    248    }
    249
    250    intp->state = VFIO_IRQ_ACTIVE;
    251
    252    /* sets slow path */
    253    vfio_mmap_set_enabled(vdev, false);
    254
    255    /* trigger the virtual IRQ */
    256    qemu_set_irq(intp->qemuirq, 1);
    257
    258    /*
    259     * Schedule the mmap timer which will restore fastpath when no IRQ
    260     * is active anymore
    261     */
    262    if (vdev->mmap_timeout) {
    263        timer_mod(vdev->mmap_timer,
    264                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    265                      vdev->mmap_timeout);
    266    }
    267}
    268
    269/**
    270 * vfio_platform_eoi - IRQ completion routine
    271 * @vbasedev: the VFIO device handle
    272 *
    273 * De-asserts the active virtual IRQ and unmasks the physical IRQ
    274 * (effective for level sensitive IRQ auto-masked by the  VFIO driver).
    275 * Then it handles next pending IRQ if any.
    276 * eoi function is called on the first access to any MMIO region
    277 * after an IRQ was triggered, trapped since slow path was set.
    278 * It is assumed this access corresponds to the IRQ status
    279 * register reset. With such a mechanism, a single IRQ can be
    280 * handled at a time since there is no way to know which IRQ
    281 * was completed by the guest (we would need additional details
    282 * about the IRQ status register mask).
    283 */
    284static void vfio_platform_eoi(VFIODevice *vbasedev)
    285{
    286    VFIOINTp *intp;
    287    VFIOPlatformDevice *vdev =
    288        container_of(vbasedev, VFIOPlatformDevice, vbasedev);
    289
    290    QEMU_LOCK_GUARD(&vdev->intp_mutex);
    291    QLIST_FOREACH(intp, &vdev->intp_list, next) {
    292        if (intp->state == VFIO_IRQ_ACTIVE) {
    293            trace_vfio_platform_eoi(intp->pin,
    294                                event_notifier_get_fd(intp->interrupt));
    295            intp->state = VFIO_IRQ_INACTIVE;
    296
    297            /* deassert the virtual IRQ */
    298            qemu_set_irq(intp->qemuirq, 0);
    299
    300            if (vfio_irq_is_automasked(intp)) {
    301                /* unmasks the physical level-sensitive IRQ */
    302                vfio_unmask_single_irqindex(vbasedev, intp->pin);
    303            }
    304
    305            /* a single IRQ can be active at a time */
    306            break;
    307        }
    308    }
    309    /* in case there are pending IRQs, handle the first one */
    310    if (!QSIMPLEQ_EMPTY(&vdev->pending_intp_queue)) {
    311        intp = QSIMPLEQ_FIRST(&vdev->pending_intp_queue);
    312        vfio_intp_inject_pending_lockheld(intp);
    313        QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext);
    314    }
    315}
    316
    317/**
    318 * vfio_start_eventfd_injection - starts the virtual IRQ injection using
    319 * user-side handled eventfds
    320 * @sbdev: the sysbus device handle
    321 * @irq: the qemu irq handle
    322 */
    323
    324static void vfio_start_eventfd_injection(SysBusDevice *sbdev, qemu_irq irq)
    325{
    326    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
    327    VFIOINTp *intp;
    328
    329    QLIST_FOREACH(intp, &vdev->intp_list, next) {
    330        if (intp->qemuirq == irq) {
    331            break;
    332        }
    333    }
    334    assert(intp);
    335
    336    if (vfio_set_trigger_eventfd(intp, vfio_intp_interrupt)) {
    337        abort();
    338    }
    339}
    340
    341/*
    342 * Functions used for irqfd
    343 */
    344
    345/**
    346 * vfio_set_resample_eventfd - sets the resamplefd for an IRQ
    347 * @intp: the IRQ struct handle
    348 * programs the VFIO driver to unmask this IRQ when the
    349 * intp->unmask eventfd is triggered
    350 */
    351static int vfio_set_resample_eventfd(VFIOINTp *intp)
    352{
    353    int32_t fd = event_notifier_get_fd(intp->unmask);
    354    VFIODevice *vbasedev = &intp->vdev->vbasedev;
    355    Error *err = NULL;
    356    int ret;
    357
    358    qemu_set_fd_handler(fd, NULL, NULL, NULL);
    359    ret = vfio_set_irq_signaling(vbasedev, intp->pin, 0,
    360                                 VFIO_IRQ_SET_ACTION_UNMASK, fd, &err);
    361    if (ret) {
    362        error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
    363    }
    364    return ret;
    365}
    366
    367/**
    368 * vfio_start_irqfd_injection - starts the virtual IRQ injection using
    369 * irqfd
    370 *
    371 * @sbdev: the sysbus device handle
    372 * @irq: the qemu irq handle
    373 *
    374 * In case the irqfd setup fails, we fallback to userspace handled eventfd
    375 */
    376static void vfio_start_irqfd_injection(SysBusDevice *sbdev, qemu_irq irq)
    377{
    378    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
    379    VFIOINTp *intp;
    380
    381    if (!kvm_irqfds_enabled() || !kvm_resamplefds_enabled() ||
    382        !vdev->irqfd_allowed) {
    383        goto fail_irqfd;
    384    }
    385
    386    QLIST_FOREACH(intp, &vdev->intp_list, next) {
    387        if (intp->qemuirq == irq) {
    388            break;
    389        }
    390    }
    391    assert(intp);
    392
    393    if (kvm_irqchip_add_irqfd_notifier(kvm_state, intp->interrupt,
    394                                   intp->unmask, irq) < 0) {
    395        goto fail_irqfd;
    396    }
    397
    398    if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
    399        goto fail_vfio;
    400    }
    401    if (vfio_irq_is_automasked(intp)) {
    402        if (vfio_set_resample_eventfd(intp) < 0) {
    403            goto fail_vfio;
    404        }
    405        trace_vfio_platform_start_level_irqfd_injection(intp->pin,
    406                                    event_notifier_get_fd(intp->interrupt),
    407                                    event_notifier_get_fd(intp->unmask));
    408    } else {
    409        trace_vfio_platform_start_edge_irqfd_injection(intp->pin,
    410                                    event_notifier_get_fd(intp->interrupt));
    411    }
    412
    413    intp->kvm_accel = true;
    414
    415    return;
    416fail_vfio:
    417    kvm_irqchip_remove_irqfd_notifier(kvm_state, intp->interrupt, irq);
    418    abort();
    419fail_irqfd:
    420    vfio_start_eventfd_injection(sbdev, irq);
    421    return;
    422}
    423
    424/* VFIO skeleton */
    425
    426static void vfio_platform_compute_needs_reset(VFIODevice *vbasedev)
    427{
    428    vbasedev->needs_reset = true;
    429}
    430
    431/* not implemented yet */
    432static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev)
    433{
    434    return -1;
    435}
    436
    437/**
    438 * vfio_populate_device - Allocate and populate MMIO region
    439 * and IRQ structs according to driver returned information
    440 * @vbasedev: the VFIO device handle
    441 * @errp: error object
    442 *
    443 */
    444static int vfio_populate_device(VFIODevice *vbasedev, Error **errp)
    445{
    446    VFIOINTp *intp, *tmp;
    447    int i, ret = -1;
    448    VFIOPlatformDevice *vdev =
    449        container_of(vbasedev, VFIOPlatformDevice, vbasedev);
    450
    451    if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) {
    452        error_setg(errp, "this isn't a platform device");
    453        return ret;
    454    }
    455
    456    vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions);
    457
    458    for (i = 0; i < vbasedev->num_regions; i++) {
    459        char *name = g_strdup_printf("VFIO %s region %d\n", vbasedev->name, i);
    460
    461        vdev->regions[i] = g_new0(VFIORegion, 1);
    462        ret = vfio_region_setup(OBJECT(vdev), vbasedev,
    463                                vdev->regions[i], i, name);
    464        g_free(name);
    465        if (ret) {
    466            error_setg_errno(errp, -ret, "failed to get region %d info", i);
    467            goto reg_error;
    468        }
    469    }
    470
    471    vdev->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
    472                                    vfio_intp_mmap_enable, vdev);
    473
    474    QSIMPLEQ_INIT(&vdev->pending_intp_queue);
    475
    476    for (i = 0; i < vbasedev->num_irqs; i++) {
    477        struct vfio_irq_info irq = { .argsz = sizeof(irq) };
    478
    479        irq.index = i;
    480        ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
    481        if (ret) {
    482            error_setg_errno(errp, -ret, "failed to get device irq info");
    483            goto irq_err;
    484        } else {
    485            trace_vfio_platform_populate_interrupts(irq.index,
    486                                                    irq.count,
    487                                                    irq.flags);
    488            intp = vfio_init_intp(vbasedev, irq, errp);
    489            if (!intp) {
    490                ret = -1;
    491                goto irq_err;
    492            }
    493        }
    494    }
    495    return 0;
    496irq_err:
    497    timer_del(vdev->mmap_timer);
    498    QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) {
    499        QLIST_REMOVE(intp, next);
    500        g_free(intp);
    501    }
    502reg_error:
    503    for (i = 0; i < vbasedev->num_regions; i++) {
    504        if (vdev->regions[i]) {
    505            vfio_region_finalize(vdev->regions[i]);
    506        }
    507        g_free(vdev->regions[i]);
    508    }
    509    g_free(vdev->regions);
    510    return ret;
    511}
    512
    513/* specialized functions for VFIO Platform devices */
    514static VFIODeviceOps vfio_platform_ops = {
    515    .vfio_compute_needs_reset = vfio_platform_compute_needs_reset,
    516    .vfio_hot_reset_multi = vfio_platform_hot_reset_multi,
    517    .vfio_eoi = vfio_platform_eoi,
    518};
    519
    520/**
    521 * vfio_base_device_init - perform preliminary VFIO setup
    522 * @vbasedev: the VFIO device handle
    523 * @errp: error object
    524 *
    525 * Implement the VFIO command sequence that allows to discover
    526 * assigned device resources: group extraction, device
    527 * fd retrieval, resource query.
    528 * Precondition: the device name must be initialized
    529 */
    530static int vfio_base_device_init(VFIODevice *vbasedev, Error **errp)
    531{
    532    VFIOGroup *group;
    533    VFIODevice *vbasedev_iter;
    534    char *tmp, group_path[PATH_MAX], *group_name;
    535    ssize_t len;
    536    struct stat st;
    537    int groupid;
    538    int ret;
    539
    540    /* @sysfsdev takes precedence over @host */
    541    if (vbasedev->sysfsdev) {
    542        g_free(vbasedev->name);
    543        vbasedev->name = g_path_get_basename(vbasedev->sysfsdev);
    544    } else {
    545        if (!vbasedev->name || strchr(vbasedev->name, '/')) {
    546            error_setg(errp, "wrong host device name");
    547            return -EINVAL;
    548        }
    549
    550        vbasedev->sysfsdev = g_strdup_printf("/sys/bus/platform/devices/%s",
    551                                             vbasedev->name);
    552    }
    553
    554    if (stat(vbasedev->sysfsdev, &st) < 0) {
    555        error_setg_errno(errp, errno,
    556                         "failed to get the sysfs host device file status");
    557        return -errno;
    558    }
    559
    560    tmp = g_strdup_printf("%s/iommu_group", vbasedev->sysfsdev);
    561    len = readlink(tmp, group_path, sizeof(group_path));
    562    g_free(tmp);
    563
    564    if (len < 0 || len >= sizeof(group_path)) {
    565        ret = len < 0 ? -errno : -ENAMETOOLONG;
    566        error_setg_errno(errp, -ret, "no iommu_group found");
    567        return ret;
    568    }
    569
    570    group_path[len] = 0;
    571
    572    group_name = basename(group_path);
    573    if (sscanf(group_name, "%d", &groupid) != 1) {
    574        error_setg_errno(errp, errno, "failed to read %s", group_path);
    575        return -errno;
    576    }
    577
    578    trace_vfio_platform_base_device_init(vbasedev->name, groupid);
    579
    580    group = vfio_get_group(groupid, &address_space_memory, errp);
    581    if (!group) {
    582        return -ENOENT;
    583    }
    584
    585    QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
    586        if (strcmp(vbasedev_iter->name, vbasedev->name) == 0) {
    587            error_setg(errp, "device is already attached");
    588            vfio_put_group(group);
    589            return -EBUSY;
    590        }
    591    }
    592    ret = vfio_get_device(group, vbasedev->name, vbasedev, errp);
    593    if (ret) {
    594        vfio_put_group(group);
    595        return ret;
    596    }
    597
    598    ret = vfio_populate_device(vbasedev, errp);
    599    if (ret) {
    600        vfio_put_group(group);
    601    }
    602
    603    return ret;
    604}
    605
    606/**
    607 * vfio_platform_realize  - the device realize function
    608 * @dev: device state pointer
    609 * @errp: error
    610 *
    611 * initialize the device, its memory regions and IRQ structures
    612 * IRQ are started separately
    613 */
    614static void vfio_platform_realize(DeviceState *dev, Error **errp)
    615{
    616    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
    617    SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
    618    VFIODevice *vbasedev = &vdev->vbasedev;
    619    int i, ret;
    620
    621    vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
    622    vbasedev->dev = dev;
    623    vbasedev->ops = &vfio_platform_ops;
    624
    625    qemu_mutex_init(&vdev->intp_mutex);
    626
    627    trace_vfio_platform_realize(vbasedev->sysfsdev ?
    628                                vbasedev->sysfsdev : vbasedev->name,
    629                                vdev->compat);
    630
    631    ret = vfio_base_device_init(vbasedev, errp);
    632    if (ret) {
    633        goto out;
    634    }
    635
    636    if (!vdev->compat) {
    637        GError *gerr = NULL;
    638        gchar *contents;
    639        gsize length;
    640        char *path;
    641
    642        path = g_strdup_printf("%s/of_node/compatible", vbasedev->sysfsdev);
    643        if (!g_file_get_contents(path, &contents, &length, &gerr)) {
    644            error_setg(errp, "%s", gerr->message);
    645            g_error_free(gerr);
    646            g_free(path);
    647            return;
    648        }
    649        g_free(path);
    650        vdev->compat = contents;
    651        for (vdev->num_compat = 0; length; vdev->num_compat++) {
    652            size_t skip = strlen(contents) + 1;
    653            contents += skip;
    654            length -= skip;
    655        }
    656    }
    657
    658    for (i = 0; i < vbasedev->num_regions; i++) {
    659        if (vfio_region_mmap(vdev->regions[i])) {
    660            warn_report("%s mmap unsupported, performance may be slow",
    661                        memory_region_name(vdev->regions[i]->mem));
    662        }
    663        sysbus_init_mmio(sbdev, vdev->regions[i]->mem);
    664    }
    665out:
    666    if (!ret) {
    667        return;
    668    }
    669
    670    if (vdev->vbasedev.name) {
    671        error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
    672    } else {
    673        error_prepend(errp, "vfio error: ");
    674    }
    675}
    676
    677static const VMStateDescription vfio_platform_vmstate = {
    678    .name = "vfio-platform",
    679    .unmigratable = 1,
    680};
    681
    682static Property vfio_platform_dev_properties[] = {
    683    DEFINE_PROP_STRING("host", VFIOPlatformDevice, vbasedev.name),
    684    DEFINE_PROP_STRING("sysfsdev", VFIOPlatformDevice, vbasedev.sysfsdev),
    685    DEFINE_PROP_BOOL("x-no-mmap", VFIOPlatformDevice, vbasedev.no_mmap, false),
    686    DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
    687                       mmap_timeout, 1100),
    688    DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
    689    DEFINE_PROP_END_OF_LIST(),
    690};
    691
    692static void vfio_platform_class_init(ObjectClass *klass, void *data)
    693{
    694    DeviceClass *dc = DEVICE_CLASS(klass);
    695    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
    696
    697    dc->realize = vfio_platform_realize;
    698    device_class_set_props(dc, vfio_platform_dev_properties);
    699    dc->vmsd = &vfio_platform_vmstate;
    700    dc->desc = "VFIO-based platform device assignment";
    701    sbc->connect_irq_notifier = vfio_start_irqfd_injection;
    702    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    703    /* Supported by TYPE_VIRT_MACHINE */
    704    dc->user_creatable = true;
    705}
    706
    707static const TypeInfo vfio_platform_dev_info = {
    708    .name = TYPE_VFIO_PLATFORM,
    709    .parent = TYPE_SYS_BUS_DEVICE,
    710    .instance_size = sizeof(VFIOPlatformDevice),
    711    .class_init = vfio_platform_class_init,
    712    .class_size = sizeof(VFIOPlatformDeviceClass),
    713};
    714
    715static void register_vfio_platform_dev_type(void)
    716{
    717    type_register_static(&vfio_platform_dev_info);
    718}
    719
    720type_init(register_vfio_platform_dev_type)