1*db4728e6SMichael S. Tsirkin /* 2*db4728e6SMichael S. Tsirkin * QEMU<->ACPI BIOS PCI hotplug interface 3*db4728e6SMichael S. Tsirkin * 4*db4728e6SMichael S. Tsirkin * QEMU supports PCI hotplug via ACPI. This module 5*db4728e6SMichael S. Tsirkin * implements the interface between QEMU and the ACPI BIOS. 6*db4728e6SMichael S. Tsirkin * Interface specification - see docs/specs/acpi_pci_hotplug.txt 7*db4728e6SMichael S. Tsirkin * 8*db4728e6SMichael S. Tsirkin * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com) 9*db4728e6SMichael S. Tsirkin * Copyright (c) 2006 Fabrice Bellard 10*db4728e6SMichael S. Tsirkin * 11*db4728e6SMichael S. Tsirkin * This library is free software; you can redistribute it and/or 12*db4728e6SMichael S. Tsirkin * modify it under the terms of the GNU Lesser General Public 13*db4728e6SMichael S. Tsirkin * License version 2 as published by the Free Software Foundation. 14*db4728e6SMichael S. Tsirkin * 15*db4728e6SMichael S. Tsirkin * This library is distributed in the hope that it will be useful, 16*db4728e6SMichael S. Tsirkin * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*db4728e6SMichael S. Tsirkin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18*db4728e6SMichael S. Tsirkin * Lesser General Public License for more details. 19*db4728e6SMichael S. Tsirkin * 20*db4728e6SMichael S. Tsirkin * You should have received a copy of the GNU Lesser General Public 21*db4728e6SMichael S. Tsirkin * License along with this library; if not, see <http://www.gnu.org/licenses/> 22*db4728e6SMichael S. Tsirkin * 23*db4728e6SMichael S. Tsirkin * Contributions after 2012-01-13 are licensed under the terms of the 24*db4728e6SMichael S. Tsirkin * GNU GPL, version 2 or (at your option) any later version. 25*db4728e6SMichael S. Tsirkin */ 26*db4728e6SMichael S. Tsirkin 27*db4728e6SMichael S. Tsirkin #include "hw/acpi/pcihp.h" 28*db4728e6SMichael S. Tsirkin 29*db4728e6SMichael S. Tsirkin #include "hw/hw.h" 30*db4728e6SMichael S. Tsirkin #include "hw/i386/pc.h" 31*db4728e6SMichael S. Tsirkin #include "hw/pci/pci.h" 32*db4728e6SMichael S. Tsirkin #include "hw/acpi/acpi.h" 33*db4728e6SMichael S. Tsirkin #include "sysemu/sysemu.h" 34*db4728e6SMichael S. Tsirkin #include "qemu/range.h" 35*db4728e6SMichael S. Tsirkin #include "exec/ioport.h" 36*db4728e6SMichael S. Tsirkin #include "exec/address-spaces.h" 37*db4728e6SMichael S. Tsirkin #include "hw/pci/pci_bus.h" 38*db4728e6SMichael S. Tsirkin #include "qom/qom-qobject.h" 39*db4728e6SMichael S. Tsirkin #include "qapi/qmp/qint.h" 40*db4728e6SMichael S. Tsirkin 41*db4728e6SMichael S. Tsirkin //#define DEBUG 42*db4728e6SMichael S. Tsirkin 43*db4728e6SMichael S. Tsirkin #ifdef DEBUG 44*db4728e6SMichael S. Tsirkin # define ACPI_PCIHP_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) 45*db4728e6SMichael S. Tsirkin #else 46*db4728e6SMichael S. Tsirkin # define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0) 47*db4728e6SMichael S. Tsirkin #endif 48*db4728e6SMichael S. Tsirkin 49*db4728e6SMichael S. Tsirkin #define PCI_HOTPLUG_ADDR 0xae00 50*db4728e6SMichael S. Tsirkin #define PCI_HOTPLUG_SIZE 0x0014 51*db4728e6SMichael S. Tsirkin #define PCI_UP_BASE 0xae00 52*db4728e6SMichael S. Tsirkin #define PCI_DOWN_BASE 0xae04 53*db4728e6SMichael S. Tsirkin #define PCI_EJ_BASE 0xae08 54*db4728e6SMichael S. Tsirkin #define PCI_RMV_BASE 0xae0c 55*db4728e6SMichael S. Tsirkin #define PCI_SEL_BASE 0xae10 56*db4728e6SMichael S. Tsirkin 57*db4728e6SMichael S. Tsirkin typedef struct AcpiPciHpFind { 58*db4728e6SMichael S. Tsirkin int bsel; 59*db4728e6SMichael S. Tsirkin PCIBus *bus; 60*db4728e6SMichael S. Tsirkin } AcpiPciHpFind; 61*db4728e6SMichael S. Tsirkin 62*db4728e6SMichael S. Tsirkin static int acpi_pcihp_get_bsel(PCIBus *bus) 63*db4728e6SMichael S. Tsirkin { 64*db4728e6SMichael S. Tsirkin QObject *o = object_property_get_qobject(OBJECT(bus), 65*db4728e6SMichael S. Tsirkin ACPI_PCIHP_PROP_BSEL, NULL); 66*db4728e6SMichael S. Tsirkin int64_t bsel = -1; 67*db4728e6SMichael S. Tsirkin if (o) { 68*db4728e6SMichael S. Tsirkin bsel = qint_get_int(qobject_to_qint(o)); 69*db4728e6SMichael S. Tsirkin } 70*db4728e6SMichael S. Tsirkin if (bsel < 0) { 71*db4728e6SMichael S. Tsirkin return -1; 72*db4728e6SMichael S. Tsirkin } 73*db4728e6SMichael S. Tsirkin return bsel; 74*db4728e6SMichael S. Tsirkin } 75*db4728e6SMichael S. Tsirkin 76*db4728e6SMichael S. Tsirkin static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque) 77*db4728e6SMichael S. Tsirkin { 78*db4728e6SMichael S. Tsirkin AcpiPciHpFind *find = opaque; 79*db4728e6SMichael S. Tsirkin if (find->bsel == acpi_pcihp_get_bsel(bus)) { 80*db4728e6SMichael S. Tsirkin find->bus = bus; 81*db4728e6SMichael S. Tsirkin } 82*db4728e6SMichael S. Tsirkin } 83*db4728e6SMichael S. Tsirkin 84*db4728e6SMichael S. Tsirkin static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel) 85*db4728e6SMichael S. Tsirkin { 86*db4728e6SMichael S. Tsirkin AcpiPciHpFind find = { .bsel = bsel, .bus = NULL }; 87*db4728e6SMichael S. Tsirkin 88*db4728e6SMichael S. Tsirkin if (bsel < 0) { 89*db4728e6SMichael S. Tsirkin return NULL; 90*db4728e6SMichael S. Tsirkin } 91*db4728e6SMichael S. Tsirkin 92*db4728e6SMichael S. Tsirkin pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find); 93*db4728e6SMichael S. Tsirkin 94*db4728e6SMichael S. Tsirkin /* Make bsel 0 eject root bus if bsel property is not set, 95*db4728e6SMichael S. Tsirkin * for compatibility with non acpi setups. 96*db4728e6SMichael S. Tsirkin * TODO: really needed? 97*db4728e6SMichael S. Tsirkin */ 98*db4728e6SMichael S. Tsirkin if (!bsel && !find.bus) { 99*db4728e6SMichael S. Tsirkin find.bus = s->root; 100*db4728e6SMichael S. Tsirkin } 101*db4728e6SMichael S. Tsirkin return find.bus; 102*db4728e6SMichael S. Tsirkin } 103*db4728e6SMichael S. Tsirkin 104*db4728e6SMichael S. Tsirkin static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev) 105*db4728e6SMichael S. Tsirkin { 106*db4728e6SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); 107*db4728e6SMichael S. Tsirkin /* 108*db4728e6SMichael S. Tsirkin * ACPI doesn't allow hotplug of bridge devices. Don't allow 109*db4728e6SMichael S. Tsirkin * hot-unplug of bridge devices unless they were added by hotplug 110*db4728e6SMichael S. Tsirkin * (and so, not described by acpi). 111*db4728e6SMichael S. Tsirkin */ 112*db4728e6SMichael S. Tsirkin return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug; 113*db4728e6SMichael S. Tsirkin } 114*db4728e6SMichael S. Tsirkin 115*db4728e6SMichael S. Tsirkin static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots) 116*db4728e6SMichael S. Tsirkin { 117*db4728e6SMichael S. Tsirkin BusChild *kid, *next; 118*db4728e6SMichael S. Tsirkin int slot = ffs(slots) - 1; 119*db4728e6SMichael S. Tsirkin bool slot_free = true; 120*db4728e6SMichael S. Tsirkin PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel); 121*db4728e6SMichael S. Tsirkin 122*db4728e6SMichael S. Tsirkin if (!bus) { 123*db4728e6SMichael S. Tsirkin return; 124*db4728e6SMichael S. Tsirkin } 125*db4728e6SMichael S. Tsirkin 126*db4728e6SMichael S. Tsirkin /* Mark request as complete */ 127*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot); 128*db4728e6SMichael S. Tsirkin 129*db4728e6SMichael S. Tsirkin QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { 130*db4728e6SMichael S. Tsirkin DeviceState *qdev = kid->child; 131*db4728e6SMichael S. Tsirkin PCIDevice *dev = PCI_DEVICE(qdev); 132*db4728e6SMichael S. Tsirkin if (PCI_SLOT(dev->devfn) == slot) { 133*db4728e6SMichael S. Tsirkin if (acpi_pcihp_pc_no_hotplug(s, dev)) { 134*db4728e6SMichael S. Tsirkin slot_free = false; 135*db4728e6SMichael S. Tsirkin } else { 136*db4728e6SMichael S. Tsirkin object_unparent(OBJECT(qdev)); 137*db4728e6SMichael S. Tsirkin } 138*db4728e6SMichael S. Tsirkin } 139*db4728e6SMichael S. Tsirkin } 140*db4728e6SMichael S. Tsirkin if (slot_free) { 141*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot); 142*db4728e6SMichael S. Tsirkin } 143*db4728e6SMichael S. Tsirkin } 144*db4728e6SMichael S. Tsirkin 145*db4728e6SMichael S. Tsirkin static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) 146*db4728e6SMichael S. Tsirkin { 147*db4728e6SMichael S. Tsirkin BusChild *kid, *next; 148*db4728e6SMichael S. Tsirkin PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel); 149*db4728e6SMichael S. Tsirkin 150*db4728e6SMichael S. Tsirkin /* Execute any pending removes during reset */ 151*db4728e6SMichael S. Tsirkin while (s->acpi_pcihp_pci_status[bsel].down) { 152*db4728e6SMichael S. Tsirkin acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down); 153*db4728e6SMichael S. Tsirkin } 154*db4728e6SMichael S. Tsirkin 155*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0; 156*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].device_present = 0; 157*db4728e6SMichael S. Tsirkin 158*db4728e6SMichael S. Tsirkin if (!bus) { 159*db4728e6SMichael S. Tsirkin return; 160*db4728e6SMichael S. Tsirkin } 161*db4728e6SMichael S. Tsirkin QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { 162*db4728e6SMichael S. Tsirkin DeviceState *qdev = kid->child; 163*db4728e6SMichael S. Tsirkin PCIDevice *pdev = PCI_DEVICE(qdev); 164*db4728e6SMichael S. Tsirkin int slot = PCI_SLOT(pdev->devfn); 165*db4728e6SMichael S. Tsirkin 166*db4728e6SMichael S. Tsirkin if (acpi_pcihp_pc_no_hotplug(s, pdev)) { 167*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot); 168*db4728e6SMichael S. Tsirkin } 169*db4728e6SMichael S. Tsirkin 170*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); 171*db4728e6SMichael S. Tsirkin } 172*db4728e6SMichael S. Tsirkin } 173*db4728e6SMichael S. Tsirkin 174*db4728e6SMichael S. Tsirkin static void acpi_pcihp_update(AcpiPciHpState *s) 175*db4728e6SMichael S. Tsirkin { 176*db4728e6SMichael S. Tsirkin int i; 177*db4728e6SMichael S. Tsirkin 178*db4728e6SMichael S. Tsirkin for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) { 179*db4728e6SMichael S. Tsirkin acpi_pcihp_update_hotplug_bus(s, i); 180*db4728e6SMichael S. Tsirkin } 181*db4728e6SMichael S. Tsirkin } 182*db4728e6SMichael S. Tsirkin 183*db4728e6SMichael S. Tsirkin void acpi_pcihp_reset(AcpiPciHpState *s) 184*db4728e6SMichael S. Tsirkin { 185*db4728e6SMichael S. Tsirkin acpi_pcihp_update(s); 186*db4728e6SMichael S. Tsirkin } 187*db4728e6SMichael S. Tsirkin 188*db4728e6SMichael S. Tsirkin static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot) 189*db4728e6SMichael S. Tsirkin { 190*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); 191*db4728e6SMichael S. Tsirkin } 192*db4728e6SMichael S. Tsirkin 193*db4728e6SMichael S. Tsirkin static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot) 194*db4728e6SMichael S. Tsirkin { 195*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); 196*db4728e6SMichael S. Tsirkin } 197*db4728e6SMichael S. Tsirkin 198*db4728e6SMichael S. Tsirkin int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev, 199*db4728e6SMichael S. Tsirkin PCIHotplugState state) 200*db4728e6SMichael S. Tsirkin { 201*db4728e6SMichael S. Tsirkin int slot = PCI_SLOT(dev->devfn); 202*db4728e6SMichael S. Tsirkin int bsel = acpi_pcihp_get_bsel(dev->bus); 203*db4728e6SMichael S. Tsirkin if (bsel < 0) { 204*db4728e6SMichael S. Tsirkin return -1; 205*db4728e6SMichael S. Tsirkin } 206*db4728e6SMichael S. Tsirkin 207*db4728e6SMichael S. Tsirkin /* Don't send event when device is enabled during qemu machine creation: 208*db4728e6SMichael S. Tsirkin * it is present on boot, no hotplug event is necessary. We do send an 209*db4728e6SMichael S. Tsirkin * event when the device is disabled later. */ 210*db4728e6SMichael S. Tsirkin if (state == PCI_COLDPLUG_ENABLED) { 211*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); 212*db4728e6SMichael S. Tsirkin return 0; 213*db4728e6SMichael S. Tsirkin } 214*db4728e6SMichael S. Tsirkin 215*db4728e6SMichael S. Tsirkin if (state == PCI_HOTPLUG_ENABLED) { 216*db4728e6SMichael S. Tsirkin enable_device(s, bsel, slot); 217*db4728e6SMichael S. Tsirkin } else { 218*db4728e6SMichael S. Tsirkin disable_device(s, bsel, slot); 219*db4728e6SMichael S. Tsirkin } 220*db4728e6SMichael S. Tsirkin 221*db4728e6SMichael S. Tsirkin return 0; 222*db4728e6SMichael S. Tsirkin } 223*db4728e6SMichael S. Tsirkin 224*db4728e6SMichael S. Tsirkin static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) 225*db4728e6SMichael S. Tsirkin { 226*db4728e6SMichael S. Tsirkin AcpiPciHpState *s = opaque; 227*db4728e6SMichael S. Tsirkin uint32_t val = 0; 228*db4728e6SMichael S. Tsirkin int bsel = s->hotplug_select; 229*db4728e6SMichael S. Tsirkin 230*db4728e6SMichael S. Tsirkin if (bsel < 0 || bsel > ACPI_PCIHP_MAX_HOTPLUG_BUS) { 231*db4728e6SMichael S. Tsirkin return 0; 232*db4728e6SMichael S. Tsirkin } 233*db4728e6SMichael S. Tsirkin 234*db4728e6SMichael S. Tsirkin switch (addr) { 235*db4728e6SMichael S. Tsirkin case PCI_UP_BASE - PCI_HOTPLUG_ADDR: 236*db4728e6SMichael S. Tsirkin /* Manufacture an "up" value to cause a device check on any hotplug 237*db4728e6SMichael S. Tsirkin * slot with a device. Extra device checks are harmless. */ 238*db4728e6SMichael S. Tsirkin val = s->acpi_pcihp_pci_status[bsel].device_present & 239*db4728e6SMichael S. Tsirkin s->acpi_pcihp_pci_status[bsel].hotplug_enable; 240*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val); 241*db4728e6SMichael S. Tsirkin break; 242*db4728e6SMichael S. Tsirkin case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR: 243*db4728e6SMichael S. Tsirkin val = s->acpi_pcihp_pci_status[bsel].down; 244*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val); 245*db4728e6SMichael S. Tsirkin break; 246*db4728e6SMichael S. Tsirkin case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: 247*db4728e6SMichael S. Tsirkin /* No feature defined yet */ 248*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val); 249*db4728e6SMichael S. Tsirkin break; 250*db4728e6SMichael S. Tsirkin case PCI_RMV_BASE - PCI_HOTPLUG_ADDR: 251*db4728e6SMichael S. Tsirkin val = s->acpi_pcihp_pci_status[bsel].hotplug_enable; 252*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val); 253*db4728e6SMichael S. Tsirkin break; 254*db4728e6SMichael S. Tsirkin case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: 255*db4728e6SMichael S. Tsirkin val = s->hotplug_select; 256*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val); 257*db4728e6SMichael S. Tsirkin default: 258*db4728e6SMichael S. Tsirkin break; 259*db4728e6SMichael S. Tsirkin } 260*db4728e6SMichael S. Tsirkin 261*db4728e6SMichael S. Tsirkin return val; 262*db4728e6SMichael S. Tsirkin } 263*db4728e6SMichael S. Tsirkin 264*db4728e6SMichael S. Tsirkin static void pci_write(void *opaque, hwaddr addr, uint64_t data, 265*db4728e6SMichael S. Tsirkin unsigned int size) 266*db4728e6SMichael S. Tsirkin { 267*db4728e6SMichael S. Tsirkin AcpiPciHpState *s = opaque; 268*db4728e6SMichael S. Tsirkin switch (addr) { 269*db4728e6SMichael S. Tsirkin case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: 270*db4728e6SMichael S. Tsirkin if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { 271*db4728e6SMichael S. Tsirkin break; 272*db4728e6SMichael S. Tsirkin } 273*db4728e6SMichael S. Tsirkin acpi_pcihp_eject_slot(s, s->hotplug_select, data); 274*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n", 275*db4728e6SMichael S. Tsirkin addr, data); 276*db4728e6SMichael S. Tsirkin break; 277*db4728e6SMichael S. Tsirkin case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: 278*db4728e6SMichael S. Tsirkin s->hotplug_select = data; 279*db4728e6SMichael S. Tsirkin ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n", 280*db4728e6SMichael S. Tsirkin addr, data); 281*db4728e6SMichael S. Tsirkin default: 282*db4728e6SMichael S. Tsirkin break; 283*db4728e6SMichael S. Tsirkin } 284*db4728e6SMichael S. Tsirkin } 285*db4728e6SMichael S. Tsirkin 286*db4728e6SMichael S. Tsirkin static const MemoryRegionOps acpi_pcihp_io_ops = { 287*db4728e6SMichael S. Tsirkin .read = pci_read, 288*db4728e6SMichael S. Tsirkin .write = pci_write, 289*db4728e6SMichael S. Tsirkin .endianness = DEVICE_LITTLE_ENDIAN, 290*db4728e6SMichael S. Tsirkin .valid = { 291*db4728e6SMichael S. Tsirkin .min_access_size = 4, 292*db4728e6SMichael S. Tsirkin .max_access_size = 4, 293*db4728e6SMichael S. Tsirkin }, 294*db4728e6SMichael S. Tsirkin }; 295*db4728e6SMichael S. Tsirkin 296*db4728e6SMichael S. Tsirkin void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus, 297*db4728e6SMichael S. Tsirkin MemoryRegion *address_space_io) 298*db4728e6SMichael S. Tsirkin { 299*db4728e6SMichael S. Tsirkin s->root= root_bus; 300*db4728e6SMichael S. Tsirkin memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s, 301*db4728e6SMichael S. Tsirkin "acpi-pci-hotplug", 302*db4728e6SMichael S. Tsirkin PCI_HOTPLUG_SIZE); 303*db4728e6SMichael S. Tsirkin memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io); 304*db4728e6SMichael S. Tsirkin } 305*db4728e6SMichael S. Tsirkin 306*db4728e6SMichael S. Tsirkin const VMStateDescription vmstate_acpi_pcihp_pci_status = { 307*db4728e6SMichael S. Tsirkin .name = "acpi_pcihp_pci_status", 308*db4728e6SMichael S. Tsirkin .version_id = 1, 309*db4728e6SMichael S. Tsirkin .minimum_version_id = 1, 310*db4728e6SMichael S. Tsirkin .minimum_version_id_old = 1, 311*db4728e6SMichael S. Tsirkin .fields = (VMStateField []) { 312*db4728e6SMichael S. Tsirkin VMSTATE_UINT32(up, AcpiPciHpPciStatus), 313*db4728e6SMichael S. Tsirkin VMSTATE_UINT32(down, AcpiPciHpPciStatus), 314*db4728e6SMichael S. Tsirkin VMSTATE_END_OF_LIST() 315*db4728e6SMichael S. Tsirkin } 316*db4728e6SMichael S. Tsirkin }; 317