qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

designware.c (26230B)


      1 /*
      2  * Copyright (c) 2018, Impinj, Inc.
      3  *
      4  * Designware PCIe IP block emulation
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see
     18  * <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "qapi/error.h"
     23 #include "qemu/module.h"
     24 #include "qemu/log.h"
     25 #include "hw/pci/msi.h"
     26 #include "hw/pci/pci_bridge.h"
     27 #include "hw/pci/pci_host.h"
     28 #include "hw/pci/pcie_port.h"
     29 #include "hw/qdev-properties.h"
     30 #include "migration/vmstate.h"
     31 #include "hw/irq.h"
     32 #include "hw/pci-host/designware.h"
     33 
     34 #define DESIGNWARE_PCIE_PORT_LINK_CONTROL          0x710
     35 #define DESIGNWARE_PCIE_PHY_DEBUG_R1               0x72C
     36 #define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP  BIT(4)
     37 #define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL   0x80C
     38 #define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE    BIT(17)
     39 #define DESIGNWARE_PCIE_MSI_ADDR_LO                0x820
     40 #define DESIGNWARE_PCIE_MSI_ADDR_HI                0x824
     41 #define DESIGNWARE_PCIE_MSI_INTR0_ENABLE           0x828
     42 #define DESIGNWARE_PCIE_MSI_INTR0_MASK             0x82C
     43 #define DESIGNWARE_PCIE_MSI_INTR0_STATUS           0x830
     44 #define DESIGNWARE_PCIE_ATU_VIEWPORT               0x900
     45 #define DESIGNWARE_PCIE_ATU_REGION_INBOUND         BIT(31)
     46 #define DESIGNWARE_PCIE_ATU_CR1                    0x904
     47 #define DESIGNWARE_PCIE_ATU_TYPE_MEM               (0x0 << 0)
     48 #define DESIGNWARE_PCIE_ATU_CR2                    0x908
     49 #define DESIGNWARE_PCIE_ATU_ENABLE                 BIT(31)
     50 #define DESIGNWARE_PCIE_ATU_LOWER_BASE             0x90C
     51 #define DESIGNWARE_PCIE_ATU_UPPER_BASE             0x910
     52 #define DESIGNWARE_PCIE_ATU_LIMIT                  0x914
     53 #define DESIGNWARE_PCIE_ATU_LOWER_TARGET           0x918
     54 #define DESIGNWARE_PCIE_ATU_BUS(x)                 (((x) >> 24) & 0xff)
     55 #define DESIGNWARE_PCIE_ATU_DEVFN(x)               (((x) >> 16) & 0xff)
     56 #define DESIGNWARE_PCIE_ATU_UPPER_TARGET           0x91C
     57 
     58 #define DESIGNWARE_PCIE_IRQ_MSI                    3
     59 
     60 static DesignwarePCIEHost *
     61 designware_pcie_root_to_host(DesignwarePCIERoot *root)
     62 {
     63     BusState *bus = qdev_get_parent_bus(DEVICE(root));
     64     return DESIGNWARE_PCIE_HOST(bus->parent);
     65 }
     66 
     67 static uint64_t designware_pcie_root_msi_read(void *opaque, hwaddr addr,
     68                                               unsigned size)
     69 {
     70     /*
     71      * Attempts to read from the MSI address are undefined in
     72      * the PCI specifications. For this hardware, the datasheet
     73      * specifies that a read from the magic address is simply not
     74      * intercepted by the MSI controller, and will go out to the
     75      * AHB/AXI bus like any other PCI-device-initiated DMA read.
     76      * This is not trivial to implement in QEMU, so since
     77      * well-behaved guests won't ever ask a PCI device to DMA from
     78      * this address we just log the missing functionality.
     79      */
     80     qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
     81     return 0;
     82 }
     83 
     84 static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
     85                                            uint64_t val, unsigned len)
     86 {
     87     DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
     88     DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
     89 
     90     root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
     91 
     92     if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
     93         qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1);
     94     }
     95 }
     96 
     97 static const MemoryRegionOps designware_pci_host_msi_ops = {
     98     .read = designware_pcie_root_msi_read,
     99     .write = designware_pcie_root_msi_write,
    100     .endianness = DEVICE_LITTLE_ENDIAN,
    101     .valid = {
    102         .min_access_size = 4,
    103         .max_access_size = 4,
    104     },
    105 };
    106 
    107 static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root)
    108 
    109 {
    110     MemoryRegion *mem   = &root->msi.iomem;
    111     const uint64_t base = root->msi.base;
    112     const bool enable   = root->msi.intr[0].enable;
    113 
    114     memory_region_set_address(mem, base);
    115     memory_region_set_enabled(mem, enable);
    116 }
    117 
    118 static DesignwarePCIEViewport *
    119 designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root)
    120 {
    121     const unsigned int idx = root->atu_viewport & 0xF;
    122     const unsigned int dir =
    123         !!(root->atu_viewport & DESIGNWARE_PCIE_ATU_REGION_INBOUND);
    124     return &root->viewports[dir][idx];
    125 }
    126 
    127 static uint32_t
    128 designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len)
    129 {
    130     DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
    131     DesignwarePCIEViewport *viewport =
    132         designware_pcie_root_get_current_viewport(root);
    133 
    134     uint32_t val;
    135 
    136     switch (address) {
    137     case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
    138         /*
    139          * Linux guest uses this register only to configure number of
    140          * PCIE lane (which in our case is irrelevant) and doesn't
    141          * really care about the value it reads from this register
    142          */
    143         val = 0xDEADBEEF;
    144         break;
    145 
    146     case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
    147         /*
    148          * To make sure that any code in guest waiting for speed
    149          * change does not time out we always report
    150          * PORT_LOGIC_SPEED_CHANGE as set
    151          */
    152         val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE;
    153         break;
    154 
    155     case DESIGNWARE_PCIE_MSI_ADDR_LO:
    156         val = root->msi.base;
    157         break;
    158 
    159     case DESIGNWARE_PCIE_MSI_ADDR_HI:
    160         val = root->msi.base >> 32;
    161         break;
    162 
    163     case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
    164         val = root->msi.intr[0].enable;
    165         break;
    166 
    167     case DESIGNWARE_PCIE_MSI_INTR0_MASK:
    168         val = root->msi.intr[0].mask;
    169         break;
    170 
    171     case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
    172         val = root->msi.intr[0].status;
    173         break;
    174 
    175     case DESIGNWARE_PCIE_PHY_DEBUG_R1:
    176         val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
    177         break;
    178 
    179     case DESIGNWARE_PCIE_ATU_VIEWPORT:
    180         val = root->atu_viewport;
    181         break;
    182 
    183     case DESIGNWARE_PCIE_ATU_LOWER_BASE:
    184         val = viewport->base;
    185         break;
    186 
    187     case DESIGNWARE_PCIE_ATU_UPPER_BASE:
    188         val = viewport->base >> 32;
    189         break;
    190 
    191     case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
    192         val = viewport->target;
    193         break;
    194 
    195     case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
    196         val = viewport->target >> 32;
    197         break;
    198 
    199     case DESIGNWARE_PCIE_ATU_LIMIT:
    200         val = viewport->limit;
    201         break;
    202 
    203     case DESIGNWARE_PCIE_ATU_CR1:
    204     case DESIGNWARE_PCIE_ATU_CR2:
    205         val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) /
    206                            sizeof(uint32_t)];
    207         break;
    208 
    209     default:
    210         val = pci_default_read_config(d, address, len);
    211         break;
    212     }
    213 
    214     return val;
    215 }
    216 
    217 static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr,
    218                                                  uint64_t *val, unsigned len)
    219 {
    220     DesignwarePCIEViewport *viewport = opaque;
    221     DesignwarePCIERoot *root = viewport->root;
    222 
    223     const uint8_t busnum = DESIGNWARE_PCIE_ATU_BUS(viewport->target);
    224     const uint8_t devfn  = DESIGNWARE_PCIE_ATU_DEVFN(viewport->target);
    225     PCIBus    *pcibus    = pci_get_bus(PCI_DEVICE(root));
    226     PCIDevice *pcidev    = pci_find_device(pcibus, busnum, devfn);
    227 
    228     if (pcidev) {
    229         addr &= pci_config_size(pcidev) - 1;
    230 
    231         if (val) {
    232             pci_host_config_write_common(pcidev, addr,
    233                                          pci_config_size(pcidev),
    234                                          *val, len);
    235         } else {
    236             return pci_host_config_read_common(pcidev, addr,
    237                                                pci_config_size(pcidev),
    238                                                len);
    239         }
    240     }
    241 
    242     return UINT64_MAX;
    243 }
    244 
    245 static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr,
    246                                                unsigned len)
    247 {
    248     return designware_pcie_root_data_access(opaque, addr, NULL, len);
    249 }
    250 
    251 static void designware_pcie_root_data_write(void *opaque, hwaddr addr,
    252                                             uint64_t val, unsigned len)
    253 {
    254     designware_pcie_root_data_access(opaque, addr, &val, len);
    255 }
    256 
    257 static const MemoryRegionOps designware_pci_host_conf_ops = {
    258     .read = designware_pcie_root_data_read,
    259     .write = designware_pcie_root_data_write,
    260     .endianness = DEVICE_LITTLE_ENDIAN,
    261     .valid = {
    262         .min_access_size = 1,
    263         .max_access_size = 4,
    264     },
    265 };
    266 
    267 static void designware_pcie_update_viewport(DesignwarePCIERoot *root,
    268                                             DesignwarePCIEViewport *viewport)
    269 {
    270     const uint64_t target = viewport->target;
    271     const uint64_t base   = viewport->base;
    272     const uint64_t size   = (uint64_t)viewport->limit - base + 1;
    273     const bool enabled    = viewport->cr[1] & DESIGNWARE_PCIE_ATU_ENABLE;
    274 
    275     MemoryRegion *current, *other;
    276 
    277     if (viewport->cr[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM) {
    278         current = &viewport->mem;
    279         other   = &viewport->cfg;
    280         memory_region_set_alias_offset(current, target);
    281     } else {
    282         current = &viewport->cfg;
    283         other   = &viewport->mem;
    284     }
    285 
    286     /*
    287      * An outbound viewport can be reconfigure from being MEM to CFG,
    288      * to account for that we disable the "other" memory region that
    289      * becomes unused due to that fact.
    290      */
    291     memory_region_set_enabled(other, false);
    292     if (enabled) {
    293         memory_region_set_size(current, size);
    294         memory_region_set_address(current, base);
    295     }
    296     memory_region_set_enabled(current, enabled);
    297 }
    298 
    299 static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
    300                                               uint32_t val, int len)
    301 {
    302     DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
    303     DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
    304     DesignwarePCIEViewport *viewport =
    305         designware_pcie_root_get_current_viewport(root);
    306 
    307     switch (address) {
    308     case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
    309     case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
    310     case DESIGNWARE_PCIE_PHY_DEBUG_R1:
    311         /* No-op */
    312         break;
    313 
    314     case DESIGNWARE_PCIE_MSI_ADDR_LO:
    315         root->msi.base &= 0xFFFFFFFF00000000ULL;
    316         root->msi.base |= val;
    317         designware_pcie_root_update_msi_mapping(root);
    318         break;
    319 
    320     case DESIGNWARE_PCIE_MSI_ADDR_HI:
    321         root->msi.base &= 0x00000000FFFFFFFFULL;
    322         root->msi.base |= (uint64_t)val << 32;
    323         designware_pcie_root_update_msi_mapping(root);
    324         break;
    325 
    326     case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
    327         root->msi.intr[0].enable = val;
    328         designware_pcie_root_update_msi_mapping(root);
    329         break;
    330 
    331     case DESIGNWARE_PCIE_MSI_INTR0_MASK:
    332         root->msi.intr[0].mask = val;
    333         break;
    334 
    335     case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
    336         root->msi.intr[0].status ^= val;
    337         if (!root->msi.intr[0].status) {
    338             qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0);
    339         }
    340         break;
    341 
    342     case DESIGNWARE_PCIE_ATU_VIEWPORT:
    343         root->atu_viewport = val;
    344         break;
    345 
    346     case DESIGNWARE_PCIE_ATU_LOWER_BASE:
    347         viewport->base &= 0xFFFFFFFF00000000ULL;
    348         viewport->base |= val;
    349         break;
    350 
    351     case DESIGNWARE_PCIE_ATU_UPPER_BASE:
    352         viewport->base &= 0x00000000FFFFFFFFULL;
    353         viewport->base |= (uint64_t)val << 32;
    354         break;
    355 
    356     case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
    357         viewport->target &= 0xFFFFFFFF00000000ULL;
    358         viewport->target |= val;
    359         break;
    360 
    361     case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
    362         viewport->target &= 0x00000000FFFFFFFFULL;
    363         viewport->target |= val;
    364         break;
    365 
    366     case DESIGNWARE_PCIE_ATU_LIMIT:
    367         viewport->limit = val;
    368         break;
    369 
    370     case DESIGNWARE_PCIE_ATU_CR1:
    371         viewport->cr[0] = val;
    372         break;
    373     case DESIGNWARE_PCIE_ATU_CR2:
    374         viewport->cr[1] = val;
    375         designware_pcie_update_viewport(root, viewport);
    376         break;
    377 
    378     default:
    379         pci_bridge_write_config(d, address, val, len);
    380         break;
    381     }
    382 }
    383 
    384 static char *designware_pcie_viewport_name(const char *direction,
    385                                            unsigned int i,
    386                                            const char *type)
    387 {
    388     return g_strdup_printf("PCI %s Viewport %u [%s]",
    389                            direction, i, type);
    390 }
    391 
    392 static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
    393 {
    394     DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
    395     DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
    396     MemoryRegion *address_space = &host->pci.memory;
    397     PCIBridge *br = PCI_BRIDGE(dev);
    398     DesignwarePCIEViewport *viewport;
    399     /*
    400      * Dummy values used for initial configuration of MemoryRegions
    401      * that belong to a given viewport
    402      */
    403     const hwaddr dummy_offset = 0;
    404     const uint64_t dummy_size = 4;
    405     size_t i;
    406 
    407     br->bus_name  = "dw-pcie";
    408 
    409     pci_set_word(dev->config + PCI_COMMAND,
    410                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    411 
    412     pci_config_set_interrupt_pin(dev->config, 1);
    413     pci_bridge_initfn(dev, TYPE_PCIE_BUS);
    414 
    415     pcie_port_init_reg(dev);
    416 
    417     pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT,
    418                   0, &error_fatal);
    419 
    420     msi_nonbroken = true;
    421     msi_init(dev, 0x50, 32, true, true, &error_fatal);
    422 
    423     for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) {
    424         MemoryRegion *source, *destination, *mem;
    425         const char *direction;
    426         char *name;
    427 
    428         viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][i];
    429         viewport->inbound = true;
    430         viewport->base    = 0x0000000000000000ULL;
    431         viewport->target  = 0x0000000000000000ULL;
    432         viewport->limit   = UINT32_MAX;
    433         viewport->cr[0]   = DESIGNWARE_PCIE_ATU_TYPE_MEM;
    434 
    435         source      = &host->pci.address_space_root;
    436         destination = get_system_memory();
    437         direction   = "Inbound";
    438 
    439         /*
    440          * Configure MemoryRegion implementing PCI -> CPU memory
    441          * access
    442          */
    443         mem  = &viewport->mem;
    444         name = designware_pcie_viewport_name(direction, i, "MEM");
    445         memory_region_init_alias(mem, OBJECT(root), name, destination,
    446                                  dummy_offset, dummy_size);
    447         memory_region_add_subregion_overlap(source, dummy_offset, mem, -1);
    448         memory_region_set_enabled(mem, false);
    449         g_free(name);
    450 
    451         viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND][i];
    452         viewport->root    = root;
    453         viewport->inbound = false;
    454         viewport->base    = 0x0000000000000000ULL;
    455         viewport->target  = 0x0000000000000000ULL;
    456         viewport->limit   = UINT32_MAX;
    457         viewport->cr[0]   = DESIGNWARE_PCIE_ATU_TYPE_MEM;
    458 
    459         destination = &host->pci.memory;
    460         direction   = "Outbound";
    461         source      = get_system_memory();
    462 
    463         /*
    464          * Configure MemoryRegion implementing CPU -> PCI memory
    465          * access
    466          */
    467         mem  = &viewport->mem;
    468         name = designware_pcie_viewport_name(direction, i, "MEM");
    469         memory_region_init_alias(mem, OBJECT(root), name, destination,
    470                                  dummy_offset, dummy_size);
    471         memory_region_add_subregion(source, dummy_offset, mem);
    472         memory_region_set_enabled(mem, false);
    473         g_free(name);
    474 
    475         /*
    476          * Configure MemoryRegion implementing access to configuration
    477          * space
    478          */
    479         mem  = &viewport->cfg;
    480         name = designware_pcie_viewport_name(direction, i, "CFG");
    481         memory_region_init_io(&viewport->cfg, OBJECT(root),
    482                               &designware_pci_host_conf_ops,
    483                               viewport, name, dummy_size);
    484         memory_region_add_subregion(source, dummy_offset, mem);
    485         memory_region_set_enabled(mem, false);
    486         g_free(name);
    487     }
    488 
    489     /*
    490      * If no inbound iATU windows are configured, HW defaults to
    491      * letting inbound TLPs to pass in. We emulate that by exlicitly
    492      * configuring first inbound window to cover all of target's
    493      * address space.
    494      *
    495      * NOTE: This will not work correctly for the case when first
    496      * configured inbound window is window 0
    497      */
    498     viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0];
    499     viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE;
    500     designware_pcie_update_viewport(root, viewport);
    501 
    502     memory_region_init_io(&root->msi.iomem, OBJECT(root),
    503                           &designware_pci_host_msi_ops,
    504                           root, "pcie-msi", 0x4);
    505     /*
    506      * We initially place MSI interrupt I/O region a adress 0 and
    507      * disable it. It'll be later moved to correct offset and enabled
    508      * in designware_pcie_root_update_msi_mapping() as a part of
    509      * initialization done by guest OS
    510      */
    511     memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem);
    512     memory_region_set_enabled(&root->msi.iomem, false);
    513 }
    514 
    515 static void designware_pcie_set_irq(void *opaque, int irq_num, int level)
    516 {
    517     DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque);
    518 
    519     qemu_set_irq(host->pci.irqs[irq_num], level);
    520 }
    521 
    522 static const char *
    523 designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus)
    524 {
    525     return "0000:00";
    526 }
    527 
    528 static const VMStateDescription vmstate_designware_pcie_msi_bank = {
    529     .name = "designware-pcie-msi-bank",
    530     .version_id = 1,
    531     .minimum_version_id = 1,
    532     .fields = (VMStateField[]) {
    533         VMSTATE_UINT32(enable, DesignwarePCIEMSIBank),
    534         VMSTATE_UINT32(mask, DesignwarePCIEMSIBank),
    535         VMSTATE_UINT32(status, DesignwarePCIEMSIBank),
    536         VMSTATE_END_OF_LIST()
    537     }
    538 };
    539 
    540 static const VMStateDescription vmstate_designware_pcie_msi = {
    541     .name = "designware-pcie-msi",
    542     .version_id = 1,
    543     .minimum_version_id = 1,
    544     .fields = (VMStateField[]) {
    545         VMSTATE_UINT64(base, DesignwarePCIEMSI),
    546         VMSTATE_STRUCT_ARRAY(intr,
    547                              DesignwarePCIEMSI,
    548                              DESIGNWARE_PCIE_NUM_MSI_BANKS,
    549                              1,
    550                              vmstate_designware_pcie_msi_bank,
    551                              DesignwarePCIEMSIBank),
    552         VMSTATE_END_OF_LIST()
    553     }
    554 };
    555 
    556 static const VMStateDescription vmstate_designware_pcie_viewport = {
    557     .name = "designware-pcie-viewport",
    558     .version_id = 1,
    559     .minimum_version_id = 1,
    560     .fields = (VMStateField[]) {
    561         VMSTATE_UINT64(base, DesignwarePCIEViewport),
    562         VMSTATE_UINT64(target, DesignwarePCIEViewport),
    563         VMSTATE_UINT32(limit, DesignwarePCIEViewport),
    564         VMSTATE_UINT32_ARRAY(cr, DesignwarePCIEViewport, 2),
    565         VMSTATE_END_OF_LIST()
    566     }
    567 };
    568 
    569 static const VMStateDescription vmstate_designware_pcie_root = {
    570     .name = "designware-pcie-root",
    571     .version_id = 1,
    572     .minimum_version_id = 1,
    573     .fields = (VMStateField[]) {
    574         VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
    575         VMSTATE_UINT32(atu_viewport, DesignwarePCIERoot),
    576         VMSTATE_STRUCT_2DARRAY(viewports,
    577                                DesignwarePCIERoot,
    578                                2,
    579                                DESIGNWARE_PCIE_NUM_VIEWPORTS,
    580                                1,
    581                                vmstate_designware_pcie_viewport,
    582                                DesignwarePCIEViewport),
    583         VMSTATE_STRUCT(msi,
    584                        DesignwarePCIERoot,
    585                        1,
    586                        vmstate_designware_pcie_msi,
    587                        DesignwarePCIEMSI),
    588         VMSTATE_END_OF_LIST()
    589     }
    590 };
    591 
    592 static void designware_pcie_root_class_init(ObjectClass *klass, void *data)
    593 {
    594     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    595     DeviceClass *dc = DEVICE_CLASS(klass);
    596 
    597     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    598 
    599     k->vendor_id = PCI_VENDOR_ID_SYNOPSYS;
    600     k->device_id = 0xABCD;
    601     k->revision = 0;
    602     k->class_id = PCI_CLASS_BRIDGE_PCI;
    603     k->is_bridge = true;
    604     k->exit = pci_bridge_exitfn;
    605     k->realize = designware_pcie_root_realize;
    606     k->config_read = designware_pcie_root_config_read;
    607     k->config_write = designware_pcie_root_config_write;
    608 
    609     dc->reset = pci_bridge_reset;
    610     /*
    611      * PCI-facing part of the host bridge, not usable without the
    612      * host-facing part, which can't be device_add'ed, yet.
    613      */
    614     dc->user_creatable = false;
    615     dc->vmsd = &vmstate_designware_pcie_root;
    616 }
    617 
    618 static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr,
    619                                                unsigned int size)
    620 {
    621     PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
    622     PCIDevice *device = pci_find_device(pci->bus, 0, 0);
    623 
    624     return pci_host_config_read_common(device,
    625                                        addr,
    626                                        pci_config_size(device),
    627                                        size);
    628 }
    629 
    630 static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr,
    631                                             uint64_t val, unsigned int size)
    632 {
    633     PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
    634     PCIDevice *device = pci_find_device(pci->bus, 0, 0);
    635 
    636     return pci_host_config_write_common(device,
    637                                         addr,
    638                                         pci_config_size(device),
    639                                         val, size);
    640 }
    641 
    642 static const MemoryRegionOps designware_pci_mmio_ops = {
    643     .read       = designware_pcie_host_mmio_read,
    644     .write      = designware_pcie_host_mmio_write,
    645     .endianness = DEVICE_LITTLE_ENDIAN,
    646     .impl = {
    647         /*
    648          * Our device would not work correctly if the guest was doing
    649          * unaligned access. This might not be a limitation on the real
    650          * device but in practice there is no reason for a guest to access
    651          * this device unaligned.
    652          */
    653         .min_access_size = 4,
    654         .max_access_size = 4,
    655         .unaligned = false,
    656     },
    657 };
    658 
    659 static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
    660                                                     int devfn)
    661 {
    662     DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
    663 
    664     return &s->pci.address_space;
    665 }
    666 
    667 static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
    668 {
    669     PCIHostState *pci = PCI_HOST_BRIDGE(dev);
    670     DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(dev);
    671     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    672     size_t i;
    673 
    674     for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
    675         sysbus_init_irq(sbd, &s->pci.irqs[i]);
    676     }
    677 
    678     memory_region_init_io(&s->mmio,
    679                           OBJECT(s),
    680                           &designware_pci_mmio_ops,
    681                           s,
    682                           "pcie.reg", 4 * 1024);
    683     sysbus_init_mmio(sbd, &s->mmio);
    684 
    685     memory_region_init(&s->pci.io, OBJECT(s), "pcie-pio", 16);
    686     memory_region_init(&s->pci.memory, OBJECT(s),
    687                        "pcie-bus-memory",
    688                        UINT64_MAX);
    689 
    690     pci->bus = pci_register_root_bus(dev, "pcie",
    691                                      designware_pcie_set_irq,
    692                                      pci_swizzle_map_irq_fn,
    693                                      s,
    694                                      &s->pci.memory,
    695                                      &s->pci.io,
    696                                      0, 4,
    697                                      TYPE_PCIE_BUS);
    698 
    699     memory_region_init(&s->pci.address_space_root,
    700                        OBJECT(s),
    701                        "pcie-bus-address-space-root",
    702                        UINT64_MAX);
    703     memory_region_add_subregion(&s->pci.address_space_root,
    704                                 0x0, &s->pci.memory);
    705     address_space_init(&s->pci.address_space,
    706                        &s->pci.address_space_root,
    707                        "pcie-bus-address-space");
    708     pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
    709 
    710     qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal);
    711 }
    712 
    713 static const VMStateDescription vmstate_designware_pcie_host = {
    714     .name = "designware-pcie-host",
    715     .version_id = 1,
    716     .minimum_version_id = 1,
    717     .fields = (VMStateField[]) {
    718         VMSTATE_STRUCT(root,
    719                        DesignwarePCIEHost,
    720                        1,
    721                        vmstate_designware_pcie_root,
    722                        DesignwarePCIERoot),
    723         VMSTATE_END_OF_LIST()
    724     }
    725 };
    726 
    727 static void designware_pcie_host_class_init(ObjectClass *klass, void *data)
    728 {
    729     DeviceClass *dc = DEVICE_CLASS(klass);
    730     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
    731 
    732     hc->root_bus_path = designware_pcie_host_root_bus_path;
    733     dc->realize = designware_pcie_host_realize;
    734     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    735     dc->fw_name = "pci";
    736     dc->vmsd = &vmstate_designware_pcie_host;
    737 }
    738 
    739 static void designware_pcie_host_init(Object *obj)
    740 {
    741     DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj);
    742     DesignwarePCIERoot *root = &s->root;
    743 
    744     object_initialize_child(obj, "root", root, TYPE_DESIGNWARE_PCIE_ROOT);
    745     qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
    746     qdev_prop_set_bit(DEVICE(root), "multifunction", false);
    747 }
    748 
    749 static const TypeInfo designware_pcie_root_info = {
    750     .name = TYPE_DESIGNWARE_PCIE_ROOT,
    751     .parent = TYPE_PCI_BRIDGE,
    752     .instance_size = sizeof(DesignwarePCIERoot),
    753     .class_init = designware_pcie_root_class_init,
    754     .interfaces = (InterfaceInfo[]) {
    755         { INTERFACE_PCIE_DEVICE },
    756         { }
    757     },
    758 };
    759 
    760 static const TypeInfo designware_pcie_host_info = {
    761     .name       = TYPE_DESIGNWARE_PCIE_HOST,
    762     .parent     = TYPE_PCI_HOST_BRIDGE,
    763     .instance_size = sizeof(DesignwarePCIEHost),
    764     .instance_init = designware_pcie_host_init,
    765     .class_init = designware_pcie_host_class_init,
    766 };
    767 
    768 static void designware_pcie_register(void)
    769 {
    770     type_register_static(&designware_pcie_root_info);
    771     type_register_static(&designware_pcie_host_info);
    772 }
    773 type_init(designware_pcie_register)