qemu/hw/pci/msix.c
<<
>>
Prefs
   1/*
   2 * MSI-X device support
   3 *
   4 * This module includes support for MSI-X in pci devices.
   5 *
   6 * Author: Michael S. Tsirkin <mst@redhat.com>
   7 *
   8 *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
   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 * Contributions after 2012-01-13 are licensed under the terms of the
  14 * GNU GPL, version 2 or (at your option) any later version.
  15 */
  16
  17#include "qemu/osdep.h"
  18#include "hw/pci/msi.h"
  19#include "hw/pci/msix.h"
  20#include "hw/pci/pci.h"
  21#include "hw/xen/xen.h"
  22#include "sysemu/xen.h"
  23#include "migration/qemu-file-types.h"
  24#include "migration/vmstate.h"
  25#include "qemu/range.h"
  26#include "qapi/error.h"
  27#include "trace.h"
  28
  29/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
  30#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
  31#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
  32#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
  33
  34MSIMessage msix_get_message(PCIDevice *dev, unsigned vector)
  35{
  36    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
  37    MSIMessage msg;
  38
  39    msg.address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
  40    msg.data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
  41    return msg;
  42}
  43
  44/*
  45 * Special API for POWER to configure the vectors through
  46 * a side channel. Should never be used by devices.
  47 */
  48void msix_set_message(PCIDevice *dev, int vector, struct MSIMessage msg)
  49{
  50    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
  51
  52    pci_set_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR, msg.address);
  53    pci_set_long(table_entry + PCI_MSIX_ENTRY_DATA, msg.data);
  54    table_entry[PCI_MSIX_ENTRY_VECTOR_CTRL] &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
  55}
  56
  57static uint8_t msix_pending_mask(int vector)
  58{
  59    return 1 << (vector % 8);
  60}
  61
  62static uint8_t *msix_pending_byte(PCIDevice *dev, int vector)
  63{
  64    return dev->msix_pba + vector / 8;
  65}
  66
  67static int msix_is_pending(PCIDevice *dev, int vector)
  68{
  69    return *msix_pending_byte(dev, vector) & msix_pending_mask(vector);
  70}
  71
  72void msix_set_pending(PCIDevice *dev, unsigned int vector)
  73{
  74    *msix_pending_byte(dev, vector) |= msix_pending_mask(vector);
  75}
  76
  77void msix_clr_pending(PCIDevice *dev, int vector)
  78{
  79    *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
  80}
  81
  82static bool msix_vector_masked(PCIDevice *dev, unsigned int vector, bool fmask)
  83{
  84    unsigned offset = vector * PCI_MSIX_ENTRY_SIZE;
  85    uint8_t *data = &dev->msix_table[offset + PCI_MSIX_ENTRY_DATA];
  86    /* MSIs on Xen can be remapped into pirqs. In those cases, masking
  87     * and unmasking go through the PV evtchn path. */
  88    if (xen_enabled() && xen_is_pirq_msi(pci_get_long(data))) {
  89        return false;
  90    }
  91    return fmask || dev->msix_table[offset + PCI_MSIX_ENTRY_VECTOR_CTRL] &
  92        PCI_MSIX_ENTRY_CTRL_MASKBIT;
  93}
  94
  95bool msix_is_masked(PCIDevice *dev, unsigned int vector)
  96{
  97    return msix_vector_masked(dev, vector, dev->msix_function_masked);
  98}
  99
 100static void msix_fire_vector_notifier(PCIDevice *dev,
 101                                      unsigned int vector, bool is_masked)
 102{
 103    MSIMessage msg;
 104    int ret;
 105
 106    if (!dev->msix_vector_use_notifier) {
 107        return;
 108    }
 109    if (is_masked) {
 110        dev->msix_vector_release_notifier(dev, vector);
 111    } else {
 112        msg = msix_get_message(dev, vector);
 113        ret = dev->msix_vector_use_notifier(dev, vector, msg);
 114        assert(ret >= 0);
 115    }
 116}
 117
 118static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked)
 119{
 120    bool is_masked = msix_is_masked(dev, vector);
 121
 122    if (is_masked == was_masked) {
 123        return;
 124    }
 125
 126    msix_fire_vector_notifier(dev, vector, is_masked);
 127
 128    if (!is_masked && msix_is_pending(dev, vector)) {
 129        msix_clr_pending(dev, vector);
 130        msix_notify(dev, vector);
 131    }
 132}
 133
 134static bool msix_masked(PCIDevice *dev)
 135{
 136    return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
 137}
 138
 139static void msix_update_function_masked(PCIDevice *dev)
 140{
 141    dev->msix_function_masked = !msix_enabled(dev) || msix_masked(dev);
 142}
 143
 144/* Handle MSI-X capability config write. */
 145void msix_write_config(PCIDevice *dev, uint32_t addr,
 146                       uint32_t val, int len)
 147{
 148    unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
 149    int vector;
 150    bool was_masked;
 151
 152    if (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) {
 153        return;
 154    }
 155
 156    trace_msix_write_config(dev->name, msix_enabled(dev), msix_masked(dev));
 157
 158    was_masked = dev->msix_function_masked;
 159    msix_update_function_masked(dev);
 160
 161    if (!msix_enabled(dev)) {
 162        return;
 163    }
 164
 165    pci_device_deassert_intx(dev);
 166
 167    if (dev->msix_function_masked == was_masked) {
 168        return;
 169    }
 170
 171    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
 172        msix_handle_mask_update(dev, vector,
 173                                msix_vector_masked(dev, vector, was_masked));
 174    }
 175}
 176
 177static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
 178                                     unsigned size)
 179{
 180    PCIDevice *dev = opaque;
 181
 182    return pci_get_long(dev->msix_table + addr);
 183}
 184
 185static void msix_table_mmio_write(void *opaque, hwaddr addr,
 186                                  uint64_t val, unsigned size)
 187{
 188    PCIDevice *dev = opaque;
 189    int vector = addr / PCI_MSIX_ENTRY_SIZE;
 190    bool was_masked;
 191
 192    was_masked = msix_is_masked(dev, vector);
 193    pci_set_long(dev->msix_table + addr, val);
 194    msix_handle_mask_update(dev, vector, was_masked);
 195}
 196
 197static const MemoryRegionOps msix_table_mmio_ops = {
 198    .read = msix_table_mmio_read,
 199    .write = msix_table_mmio_write,
 200    .endianness = DEVICE_LITTLE_ENDIAN,
 201    .valid = {
 202        .min_access_size = 4,
 203        .max_access_size = 8,
 204    },
 205    .impl = {
 206        .max_access_size = 4,
 207    },
 208};
 209
 210static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
 211                                   unsigned size)
 212{
 213    PCIDevice *dev = opaque;
 214    if (dev->msix_vector_poll_notifier) {
 215        unsigned vector_start = addr * 8;
 216        unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr);
 217        dev->msix_vector_poll_notifier(dev, vector_start, vector_end);
 218    }
 219
 220    return pci_get_long(dev->msix_pba + addr);
 221}
 222
 223static void msix_pba_mmio_write(void *opaque, hwaddr addr,
 224                                uint64_t val, unsigned size)
 225{
 226}
 227
 228static const MemoryRegionOps msix_pba_mmio_ops = {
 229    .read = msix_pba_mmio_read,
 230    .write = msix_pba_mmio_write,
 231    .endianness = DEVICE_LITTLE_ENDIAN,
 232    .valid = {
 233        .min_access_size = 4,
 234        .max_access_size = 8,
 235    },
 236    .impl = {
 237        .max_access_size = 4,
 238    },
 239};
 240
 241static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
 242{
 243    int vector;
 244
 245    for (vector = 0; vector < nentries; ++vector) {
 246        unsigned offset =
 247            vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
 248        bool was_masked = msix_is_masked(dev, vector);
 249
 250        dev->msix_table[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
 251        msix_handle_mask_update(dev, vector, was_masked);
 252    }
 253}
 254
 255/*
 256 * Make PCI device @dev MSI-X capable
 257 * @nentries is the max number of MSI-X vectors that the device support.
 258 * @table_bar is the MemoryRegion that MSI-X table structure resides.
 259 * @table_bar_nr is number of base address register corresponding to @table_bar.
 260 * @table_offset indicates the offset that the MSI-X table structure starts with
 261 * in @table_bar.
 262 * @pba_bar is the MemoryRegion that the Pending Bit Array structure resides.
 263 * @pba_bar_nr is number of base address register corresponding to @pba_bar.
 264 * @pba_offset indicates the offset that the Pending Bit Array structure
 265 * starts with in @pba_bar.
 266 * Non-zero @cap_pos puts capability MSI-X at that offset in PCI config space.
 267 * @errp is for returning errors.
 268 *
 269 * Return 0 on success; set @errp and return -errno on error:
 270 * -ENOTSUP means lacking msi support for a msi-capable platform.
 271 * -EINVAL means capability overlap, happens when @cap_pos is non-zero,
 272 * also means a programming error, except device assignment, which can check
 273 * if a real HW is broken.
 274 */
 275int msix_init(struct PCIDevice *dev, unsigned short nentries,
 276              MemoryRegion *table_bar, uint8_t table_bar_nr,
 277              unsigned table_offset, MemoryRegion *pba_bar,
 278              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos,
 279              Error **errp)
 280{
 281    int cap;
 282    unsigned table_size, pba_size;
 283    uint8_t *config;
 284
 285    /* Nothing to do if MSI is not supported by interrupt controller */
 286    if (!msi_nonbroken) {
 287        error_setg(errp, "MSI-X is not supported by interrupt controller");
 288        return -ENOTSUP;
 289    }
 290
 291    if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1) {
 292        error_setg(errp, "The number of MSI-X vectors is invalid");
 293        return -EINVAL;
 294    }
 295
 296    table_size = nentries * PCI_MSIX_ENTRY_SIZE;
 297    pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;
 298
 299    /* Sanity test: table & pba don't overlap, fit within BARs, min aligned */
 300    if ((table_bar_nr == pba_bar_nr &&
 301         ranges_overlap(table_offset, table_size, pba_offset, pba_size)) ||
 302        table_offset + table_size > memory_region_size(table_bar) ||
 303        pba_offset + pba_size > memory_region_size(pba_bar) ||
 304        (table_offset | pba_offset) & PCI_MSIX_FLAGS_BIRMASK) {
 305        error_setg(errp, "table & pba overlap, or they don't fit in BARs,"
 306                   " or don't align");
 307        return -EINVAL;
 308    }
 309
 310    cap = pci_add_capability(dev, PCI_CAP_ID_MSIX,
 311                              cap_pos, MSIX_CAP_LENGTH, errp);
 312    if (cap < 0) {
 313        return cap;
 314    }
 315
 316    dev->msix_cap = cap;
 317    dev->cap_present |= QEMU_PCI_CAP_MSIX;
 318    config = dev->config + cap;
 319
 320    pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
 321    dev->msix_entries_nr = nentries;
 322    dev->msix_function_masked = true;
 323
 324    pci_set_long(config + PCI_MSIX_TABLE, table_offset | table_bar_nr);
 325    pci_set_long(config + PCI_MSIX_PBA, pba_offset | pba_bar_nr);
 326
 327    /* Make flags bit writable. */
 328    dev->wmask[cap + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
 329                                             MSIX_MASKALL_MASK;
 330
 331    dev->msix_table = g_malloc0(table_size);
 332    dev->msix_pba = g_malloc0(pba_size);
 333    dev->msix_entry_used = g_malloc0(nentries * sizeof *dev->msix_entry_used);
 334
 335    msix_mask_all(dev, nentries);
 336
 337    memory_region_init_io(&dev->msix_table_mmio, OBJECT(dev), &msix_table_mmio_ops, dev,
 338                          "msix-table", table_size);
 339    memory_region_add_subregion(table_bar, table_offset, &dev->msix_table_mmio);
 340    memory_region_init_io(&dev->msix_pba_mmio, OBJECT(dev), &msix_pba_mmio_ops, dev,
 341                          "msix-pba", pba_size);
 342    memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio);
 343
 344    return 0;
 345}
 346
 347int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
 348                            uint8_t bar_nr, Error **errp)
 349{
 350    int ret;
 351    char *name;
 352    uint32_t bar_size = 4096;
 353    uint32_t bar_pba_offset = bar_size / 2;
 354    uint32_t bar_pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;
 355
 356    /*
 357     * Migration compatibility dictates that this remains a 4k
 358     * BAR with the vector table in the lower half and PBA in
 359     * the upper half for nentries which is lower or equal to 128.
 360     * No need to care about using more than 65 entries for legacy
 361     * machine types who has at most 64 queues.
 362     */
 363    if (nentries * PCI_MSIX_ENTRY_SIZE > bar_pba_offset) {
 364        bar_pba_offset = nentries * PCI_MSIX_ENTRY_SIZE;
 365    }
 366
 367    if (bar_pba_offset + bar_pba_size > 4096) {
 368        bar_size = bar_pba_offset + bar_pba_size;
 369    }
 370
 371    bar_size = pow2ceil(bar_size);
 372
 373    name = g_strdup_printf("%s-msix", dev->name);
 374    memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, bar_size);
 375    g_free(name);
 376
 377    ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
 378                    0, &dev->msix_exclusive_bar,
 379                    bar_nr, bar_pba_offset,
 380                    0, errp);
 381    if (ret) {
 382        return ret;
 383    }
 384
 385    pci_register_bar(dev, bar_nr, PCI_BASE_ADDRESS_SPACE_MEMORY,
 386                     &dev->msix_exclusive_bar);
 387
 388    return 0;
 389}
 390
 391static void msix_free_irq_entries(PCIDevice *dev)
 392{
 393    int vector;
 394
 395    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
 396        dev->msix_entry_used[vector] = 0;
 397        msix_clr_pending(dev, vector);
 398    }
 399}
 400
 401static void msix_clear_all_vectors(PCIDevice *dev)
 402{
 403    int vector;
 404
 405    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
 406        msix_clr_pending(dev, vector);
 407    }
 408}
 409
 410/* Clean up resources for the device. */
 411void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar)
 412{
 413    if (!msix_present(dev)) {
 414        return;
 415    }
 416    pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH);
 417    dev->msix_cap = 0;
 418    msix_free_irq_entries(dev);
 419    dev->msix_entries_nr = 0;
 420    memory_region_del_subregion(pba_bar, &dev->msix_pba_mmio);
 421    g_free(dev->msix_pba);
 422    dev->msix_pba = NULL;
 423    memory_region_del_subregion(table_bar, &dev->msix_table_mmio);
 424    g_free(dev->msix_table);
 425    dev->msix_table = NULL;
 426    g_free(dev->msix_entry_used);
 427    dev->msix_entry_used = NULL;
 428    dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
 429}
 430
 431void msix_uninit_exclusive_bar(PCIDevice *dev)
 432{
 433    if (msix_present(dev)) {
 434        msix_uninit(dev, &dev->msix_exclusive_bar, &dev->msix_exclusive_bar);
 435    }
 436}
 437
 438void msix_save(PCIDevice *dev, QEMUFile *f)
 439{
 440    unsigned n = dev->msix_entries_nr;
 441
 442    if (!msix_present(dev)) {
 443        return;
 444    }
 445
 446    qemu_put_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
 447    qemu_put_buffer(f, dev->msix_pba, DIV_ROUND_UP(n, 8));
 448}
 449
 450/* Should be called after restoring the config space. */
 451void msix_load(PCIDevice *dev, QEMUFile *f)
 452{
 453    unsigned n = dev->msix_entries_nr;
 454    unsigned int vector;
 455
 456    if (!msix_present(dev)) {
 457        return;
 458    }
 459
 460    msix_clear_all_vectors(dev);
 461    qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
 462    qemu_get_buffer(f, dev->msix_pba, DIV_ROUND_UP(n, 8));
 463    msix_update_function_masked(dev);
 464
 465    for (vector = 0; vector < n; vector++) {
 466        msix_handle_mask_update(dev, vector, true);
 467    }
 468}
 469
 470/* Does device support MSI-X? */
 471int msix_present(PCIDevice *dev)
 472{
 473    return dev->cap_present & QEMU_PCI_CAP_MSIX;
 474}
 475
 476/* Is MSI-X enabled? */
 477int msix_enabled(PCIDevice *dev)
 478{
 479    return (dev->cap_present & QEMU_PCI_CAP_MSIX) &&
 480        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
 481         MSIX_ENABLE_MASK);
 482}
 483
 484/* Send an MSI-X message */
 485void msix_notify(PCIDevice *dev, unsigned vector)
 486{
 487    MSIMessage msg;
 488
 489    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) {
 490        return;
 491    }
 492
 493    if (msix_is_masked(dev, vector)) {
 494        msix_set_pending(dev, vector);
 495        return;
 496    }
 497
 498    msg = msix_get_message(dev, vector);
 499
 500    msi_send_message(dev, msg);
 501}
 502
 503void msix_reset(PCIDevice *dev)
 504{
 505    if (!msix_present(dev)) {
 506        return;
 507    }
 508    msix_clear_all_vectors(dev);
 509    dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
 510            ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
 511    memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
 512    memset(dev->msix_pba, 0, QEMU_ALIGN_UP(dev->msix_entries_nr, 64) / 8);
 513    msix_mask_all(dev, dev->msix_entries_nr);
 514}
 515
 516/* PCI spec suggests that devices make it possible for software to configure
 517 * less vectors than supported by the device, but does not specify a standard
 518 * mechanism for devices to do so.
 519 *
 520 * We support this by asking devices to declare vectors software is going to
 521 * actually use, and checking this on the notification path. Devices that
 522 * don't want to follow the spec suggestion can declare all vectors as used. */
 523
 524/* Mark vector as used. */
 525int msix_vector_use(PCIDevice *dev, unsigned vector)
 526{
 527    if (vector >= dev->msix_entries_nr) {
 528        return -EINVAL;
 529    }
 530
 531    dev->msix_entry_used[vector]++;
 532    return 0;
 533}
 534
 535/* Mark vector as unused. */
 536void msix_vector_unuse(PCIDevice *dev, unsigned vector)
 537{
 538    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) {
 539        return;
 540    }
 541    if (--dev->msix_entry_used[vector]) {
 542        return;
 543    }
 544    msix_clr_pending(dev, vector);
 545}
 546
 547void msix_unuse_all_vectors(PCIDevice *dev)
 548{
 549    if (!msix_present(dev)) {
 550        return;
 551    }
 552    msix_free_irq_entries(dev);
 553}
 554
 555unsigned int msix_nr_vectors_allocated(const PCIDevice *dev)
 556{
 557    return dev->msix_entries_nr;
 558}
 559
 560static int msix_set_notifier_for_vector(PCIDevice *dev, unsigned int vector)
 561{
 562    MSIMessage msg;
 563
 564    if (msix_is_masked(dev, vector)) {
 565        return 0;
 566    }
 567    msg = msix_get_message(dev, vector);
 568    return dev->msix_vector_use_notifier(dev, vector, msg);
 569}
 570
 571static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector)
 572{
 573    if (msix_is_masked(dev, vector)) {
 574        return;
 575    }
 576    dev->msix_vector_release_notifier(dev, vector);
 577}
 578
 579int msix_set_vector_notifiers(PCIDevice *dev,
 580                              MSIVectorUseNotifier use_notifier,
 581                              MSIVectorReleaseNotifier release_notifier,
 582                              MSIVectorPollNotifier poll_notifier)
 583{
 584    int vector, ret;
 585
 586    assert(use_notifier && release_notifier);
 587
 588    dev->msix_vector_use_notifier = use_notifier;
 589    dev->msix_vector_release_notifier = release_notifier;
 590    dev->msix_vector_poll_notifier = poll_notifier;
 591
 592    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
 593        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
 594        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
 595            ret = msix_set_notifier_for_vector(dev, vector);
 596            if (ret < 0) {
 597                goto undo;
 598            }
 599        }
 600    }
 601    if (dev->msix_vector_poll_notifier) {
 602        dev->msix_vector_poll_notifier(dev, 0, dev->msix_entries_nr);
 603    }
 604    return 0;
 605
 606undo:
 607    while (--vector >= 0) {
 608        msix_unset_notifier_for_vector(dev, vector);
 609    }
 610    dev->msix_vector_use_notifier = NULL;
 611    dev->msix_vector_release_notifier = NULL;
 612    return ret;
 613}
 614
 615void msix_unset_vector_notifiers(PCIDevice *dev)
 616{
 617    int vector;
 618
 619    assert(dev->msix_vector_use_notifier &&
 620           dev->msix_vector_release_notifier);
 621
 622    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
 623        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
 624        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
 625            msix_unset_notifier_for_vector(dev, vector);
 626        }
 627    }
 628    dev->msix_vector_use_notifier = NULL;
 629    dev->msix_vector_release_notifier = NULL;
 630    dev->msix_vector_poll_notifier = NULL;
 631}
 632
 633static int put_msix_state(QEMUFile *f, void *pv, size_t size,
 634                          const VMStateField *field, QJSON *vmdesc)
 635{
 636    msix_save(pv, f);
 637
 638    return 0;
 639}
 640
 641static int get_msix_state(QEMUFile *f, void *pv, size_t size,
 642                          const VMStateField *field)
 643{
 644    msix_load(pv, f);
 645    return 0;
 646}
 647
 648static VMStateInfo vmstate_info_msix = {
 649    .name = "msix state",
 650    .get  = get_msix_state,
 651    .put  = put_msix_state,
 652};
 653
 654const VMStateDescription vmstate_msix = {
 655    .name = "msix",
 656    .fields = (VMStateField[]) {
 657        {
 658            .name         = "msix",
 659            .version_id   = 0,
 660            .field_exists = NULL,
 661            .size         = 0,   /* ouch */
 662            .info         = &vmstate_info_msix,
 663            .flags        = VMS_SINGLE,
 664            .offset       = 0,
 665        },
 666        VMSTATE_END_OF_LIST()
 667    }
 668};
 669