qemu/hw/pci-bridge/pci_expander_bridge.c
<<
>>
Prefs
   1/*
   2 * PCI Expander Bridge Device Emulation
   3 *
   4 * Copyright (C) 2015 Red Hat Inc
   5 *
   6 * Authors:
   7 *   Marcel Apfelbaum <marcel@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qapi/error.h"
  15#include "hw/pci/pci.h"
  16#include "hw/pci/pci_bus.h"
  17#include "hw/pci/pci_host.h"
  18#include "hw/pci/pci_bridge.h"
  19#include "qemu/range.h"
  20#include "qemu/error-report.h"
  21#include "qemu/module.h"
  22#include "sysemu/numa.h"
  23
  24#define TYPE_PXB_BUS "pxb-bus"
  25#define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
  26
  27#define TYPE_PXB_PCIE_BUS "pxb-pcie-bus"
  28#define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS)
  29
  30typedef struct PXBBus {
  31    /*< private >*/
  32    PCIBus parent_obj;
  33    /*< public >*/
  34
  35    char bus_path[8];
  36} PXBBus;
  37
  38#define TYPE_PXB_DEVICE "pxb"
  39#define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE)
  40
  41#define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
  42#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
  43
  44typedef struct PXBDev {
  45    /*< private >*/
  46    PCIDevice parent_obj;
  47    /*< public >*/
  48
  49    uint8_t bus_nr;
  50    uint16_t numa_node;
  51} PXBDev;
  52
  53static PXBDev *convert_to_pxb(PCIDevice *dev)
  54{
  55    return pci_bus_is_express(pci_get_bus(dev))
  56        ? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
  57}
  58
  59static GList *pxb_dev_list;
  60
  61#define TYPE_PXB_HOST "pxb-host"
  62
  63static int pxb_bus_num(PCIBus *bus)
  64{
  65    PXBDev *pxb = convert_to_pxb(bus->parent_dev);
  66
  67    return pxb->bus_nr;
  68}
  69
  70static uint16_t pxb_bus_numa_node(PCIBus *bus)
  71{
  72    PXBDev *pxb = convert_to_pxb(bus->parent_dev);
  73
  74    return pxb->numa_node;
  75}
  76
  77static void pxb_bus_class_init(ObjectClass *class, void *data)
  78{
  79    PCIBusClass *pbc = PCI_BUS_CLASS(class);
  80
  81    pbc->bus_num = pxb_bus_num;
  82    pbc->numa_node = pxb_bus_numa_node;
  83}
  84
  85static const TypeInfo pxb_bus_info = {
  86    .name          = TYPE_PXB_BUS,
  87    .parent        = TYPE_PCI_BUS,
  88    .instance_size = sizeof(PXBBus),
  89    .class_init    = pxb_bus_class_init,
  90};
  91
  92static const TypeInfo pxb_pcie_bus_info = {
  93    .name          = TYPE_PXB_PCIE_BUS,
  94    .parent        = TYPE_PCIE_BUS,
  95    .instance_size = sizeof(PXBBus),
  96    .class_init    = pxb_bus_class_init,
  97};
  98
  99static const char *pxb_host_root_bus_path(PCIHostState *host_bridge,
 100                                          PCIBus *rootbus)
 101{
 102    PXBBus *bus = pci_bus_is_express(rootbus) ?
 103                  PXB_PCIE_BUS(rootbus) : PXB_BUS(rootbus);
 104
 105    snprintf(bus->bus_path, 8, "0000:%02x", pxb_bus_num(rootbus));
 106    return bus->bus_path;
 107}
 108
 109static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 110{
 111    const PCIHostState *pxb_host;
 112    const PCIBus *pxb_bus;
 113    const PXBDev *pxb_dev;
 114    int position;
 115    const DeviceState *pxb_dev_base;
 116    const PCIHostState *main_host;
 117    const SysBusDevice *main_host_sbd;
 118
 119    pxb_host = PCI_HOST_BRIDGE(dev);
 120    pxb_bus = pxb_host->bus;
 121    pxb_dev = convert_to_pxb(pxb_bus->parent_dev);
 122    position = g_list_index(pxb_dev_list, pxb_dev);
 123    assert(position >= 0);
 124
 125    pxb_dev_base = DEVICE(pxb_dev);
 126    main_host = PCI_HOST_BRIDGE(pxb_dev_base->parent_bus->parent);
 127    main_host_sbd = SYS_BUS_DEVICE(main_host);
 128
 129    if (main_host_sbd->num_mmio > 0) {
 130        return g_strdup_printf(TARGET_FMT_plx ",%x",
 131                               main_host_sbd->mmio[0].addr, position + 1);
 132    }
 133    if (main_host_sbd->num_pio > 0) {
 134        return g_strdup_printf("i%04x,%x",
 135                               main_host_sbd->pio[0], position + 1);
 136    }
 137    return NULL;
 138}
 139
 140static void pxb_host_class_init(ObjectClass *class, void *data)
 141{
 142    DeviceClass *dc = DEVICE_CLASS(class);
 143    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
 144    PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
 145
 146    dc->fw_name = "pci";
 147    /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */
 148    dc->user_creatable = false;
 149    sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
 150    hc->root_bus_path = pxb_host_root_bus_path;
 151}
 152
 153static const TypeInfo pxb_host_info = {
 154    .name          = TYPE_PXB_HOST,
 155    .parent        = TYPE_PCI_HOST_BRIDGE,
 156    .class_init    = pxb_host_class_init,
 157};
 158
 159/*
 160 * Registers the PXB bus as a child of pci host root bus.
 161 */
 162static void pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus, Error **errp)
 163{
 164    PCIBus *bus = pci_get_bus(dev);
 165    int pxb_bus_num = pci_bus_num(pxb_bus);
 166
 167    if (bus->parent_dev) {
 168        error_setg(errp, "PXB devices can be attached only to root bus");
 169        return;
 170    }
 171
 172    QLIST_FOREACH(bus, &bus->child, sibling) {
 173        if (pci_bus_num(bus) == pxb_bus_num) {
 174            error_setg(errp, "Bus %d is already in use", pxb_bus_num);
 175            return;
 176        }
 177    }
 178    QLIST_INSERT_HEAD(&pci_get_bus(dev)->child, pxb_bus, sibling);
 179}
 180
 181static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
 182{
 183    PCIDevice *pxb = pci_get_bus(pci_dev)->parent_dev;
 184
 185    /*
 186     * The bios does not index the pxb slot number when
 187     * it computes the IRQ because it resides on bus 0
 188     * and not on the current bus.
 189     * However QEMU routes the irq through bus 0 and adds
 190     * the pxb slot to the IRQ computation of the PXB
 191     * device.
 192     *
 193     * Synchronize between bios and QEMU by canceling
 194     * pxb's effect.
 195     */
 196    return pin - PCI_SLOT(pxb->devfn);
 197}
 198
 199static gint pxb_compare(gconstpointer a, gconstpointer b)
 200{
 201    const PXBDev *pxb_a = a, *pxb_b = b;
 202
 203    return pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
 204           pxb_a->bus_nr > pxb_b->bus_nr ?  1 :
 205           0;
 206}
 207
 208static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
 209{
 210    PXBDev *pxb = convert_to_pxb(dev);
 211    DeviceState *ds, *bds = NULL;
 212    PCIBus *bus;
 213    const char *dev_name = NULL;
 214    Error *local_err = NULL;
 215
 216    if (pxb->numa_node != NUMA_NODE_UNASSIGNED &&
 217        pxb->numa_node >= nb_numa_nodes) {
 218        error_setg(errp, "Illegal numa node %d", pxb->numa_node);
 219        return;
 220    }
 221
 222    if (dev->qdev.id && *dev->qdev.id) {
 223        dev_name = dev->qdev.id;
 224    }
 225
 226    ds = qdev_create(NULL, TYPE_PXB_HOST);
 227    if (pcie) {
 228        bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
 229    } else {
 230        bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
 231        bds = qdev_create(BUS(bus), "pci-bridge");
 232        bds->id = dev_name;
 233        qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
 234        qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false);
 235    }
 236
 237    bus->parent_dev = dev;
 238    bus->address_space_mem = pci_get_bus(dev)->address_space_mem;
 239    bus->address_space_io = pci_get_bus(dev)->address_space_io;
 240    bus->map_irq = pxb_map_irq_fn;
 241
 242    PCI_HOST_BRIDGE(ds)->bus = bus;
 243
 244    pxb_register_bus(dev, bus, &local_err);
 245    if (local_err) {
 246        error_propagate(errp, local_err);
 247        goto err_register_bus;
 248    }
 249
 250    qdev_init_nofail(ds);
 251    if (bds) {
 252        qdev_init_nofail(bds);
 253    }
 254
 255    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
 256                               PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
 257    pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
 258
 259    pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
 260    return;
 261
 262err_register_bus:
 263    object_unref(OBJECT(bds));
 264    object_unparent(OBJECT(bus));
 265    object_unref(OBJECT(ds));
 266}
 267
 268static void pxb_dev_realize(PCIDevice *dev, Error **errp)
 269{
 270    if (pci_bus_is_express(pci_get_bus(dev))) {
 271        error_setg(errp, "pxb devices cannot reside on a PCIe bus");
 272        return;
 273    }
 274
 275    pxb_dev_realize_common(dev, false, errp);
 276}
 277
 278static void pxb_dev_exitfn(PCIDevice *pci_dev)
 279{
 280    PXBDev *pxb = convert_to_pxb(pci_dev);
 281
 282    pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 283}
 284
 285static Property pxb_dev_properties[] = {
 286    /* Note: 0 is not a legal PXB bus number. */
 287    DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
 288    DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED),
 289    DEFINE_PROP_END_OF_LIST(),
 290};
 291
 292static void pxb_dev_class_init(ObjectClass *klass, void *data)
 293{
 294    DeviceClass *dc = DEVICE_CLASS(klass);
 295    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 296
 297    k->realize = pxb_dev_realize;
 298    k->exit = pxb_dev_exitfn;
 299    k->vendor_id = PCI_VENDOR_ID_REDHAT;
 300    k->device_id = PCI_DEVICE_ID_REDHAT_PXB;
 301    k->class_id = PCI_CLASS_BRIDGE_HOST;
 302
 303    dc->desc = "PCI Expander Bridge";
 304    dc->props = pxb_dev_properties;
 305    dc->hotpluggable = false;
 306    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 307}
 308
 309static const TypeInfo pxb_dev_info = {
 310    .name          = TYPE_PXB_DEVICE,
 311    .parent        = TYPE_PCI_DEVICE,
 312    .instance_size = sizeof(PXBDev),
 313    .class_init    = pxb_dev_class_init,
 314    .interfaces = (InterfaceInfo[]) {
 315        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
 316        { },
 317    },
 318};
 319
 320static void pxb_pcie_dev_realize(PCIDevice *dev, Error **errp)
 321{
 322    if (!pci_bus_is_express(pci_get_bus(dev))) {
 323        error_setg(errp, "pxb-pcie devices cannot reside on a PCI bus");
 324        return;
 325    }
 326
 327    pxb_dev_realize_common(dev, true, errp);
 328}
 329
 330static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
 331{
 332    DeviceClass *dc = DEVICE_CLASS(klass);
 333    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 334
 335    k->realize = pxb_pcie_dev_realize;
 336    k->exit = pxb_dev_exitfn;
 337    k->vendor_id = PCI_VENDOR_ID_REDHAT;
 338    k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
 339    k->class_id = PCI_CLASS_BRIDGE_HOST;
 340
 341    dc->desc = "PCI Express Expander Bridge";
 342    dc->props = pxb_dev_properties;
 343    dc->hotpluggable = false;
 344    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 345}
 346
 347static const TypeInfo pxb_pcie_dev_info = {
 348    .name          = TYPE_PXB_PCIE_DEVICE,
 349    .parent        = TYPE_PCI_DEVICE,
 350    .instance_size = sizeof(PXBDev),
 351    .class_init    = pxb_pcie_dev_class_init,
 352    .interfaces = (InterfaceInfo[]) {
 353        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
 354        { },
 355    },
 356};
 357
 358static void pxb_register_types(void)
 359{
 360    type_register_static(&pxb_bus_info);
 361    type_register_static(&pxb_pcie_bus_info);
 362    type_register_static(&pxb_host_info);
 363    type_register_static(&pxb_dev_info);
 364    type_register_static(&pxb_pcie_dev_info);
 365}
 366
 367type_init(pxb_register_types)
 368