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