qemu/hw/pci-host/versatile.c
<<
>>
Prefs
   1/*
   2 * ARM Versatile/PB PCI host controller
   3 *
   4 * Copyright (c) 2006-2009 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the LGPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "hw/sysbus.h"
  12#include "hw/pci/pci.h"
  13#include "hw/pci/pci_bus.h"
  14#include "hw/pci/pci_host.h"
  15#include "qemu/log.h"
  16
  17/* Old and buggy versions of QEMU used the wrong mapping from
  18 * PCI IRQs to system interrupt lines. Unfortunately the Linux
  19 * kernel also had the corresponding bug in setting up interrupts
  20 * (so older kernels work on QEMU and not on real hardware).
  21 * We automatically detect these broken kernels and flip back
  22 * to the broken irq mapping by spotting guest writes to the
  23 * PCI_INTERRUPT_LINE register to see where the guest thinks
  24 * interrupts are going to be routed. So we start in state
  25 * ASSUME_OK on reset, and transition to either BROKEN or
  26 * FORCE_OK at the first write to an INTERRUPT_LINE register for
  27 * a slot where broken and correct interrupt mapping would differ.
  28 * Once in either BROKEN or FORCE_OK we never transition again;
  29 * this allows a newer kernel to use the INTERRUPT_LINE
  30 * registers arbitrarily once it has indicated that it isn't
  31 * broken in its init code somewhere.
  32 *
  33 * Unfortunately we have to cope with multiple different
  34 * variants on the broken kernel behaviour:
  35 *  phase I (before kernel commit 1bc39ac5d) kernels assume old
  36 *   QEMU behaviour, so they use IRQ 27 for all slots
  37 *  phase II (1bc39ac5d and later, but before e3e92a7be6) kernels
  38 *   swizzle IRQs between slots, but do it wrongly, so they
  39 *   work only for every fourth PCI card, and only if (like old
  40 *   QEMU) the PCI host device is at slot 0 rather than where
  41 *   the h/w actually puts it
  42 *  phase III (e3e92a7be6 and later) kernels still swizzle IRQs between
  43 *   slots wrongly, but add a fixed offset of 64 to everything
  44 *   they write to PCI_INTERRUPT_LINE.
  45 *
  46 * We live in hope of a mythical phase IV kernel which might
  47 * actually behave in ways that work on the hardware. Such a
  48 * kernel should probably start off by writing some value neither
  49 * 27 nor 91 to slot zero's PCI_INTERRUPT_LINE register to
  50 * disable the autodetection. After that it can do what it likes.
  51 *
  52 * Slot % 4 | hw | I  | II | III
  53 * -------------------------------
  54 *   0      | 29 | 27 | 27 | 91
  55 *   1      | 30 | 27 | 28 | 92
  56 *   2      | 27 | 27 | 29 | 93
  57 *   3      | 28 | 27 | 30 | 94
  58 *
  59 * Since our autodetection is not perfect we also provide a
  60 * property so the user can make us start in BROKEN or FORCE_OK
  61 * on reset if they know they have a bad or good kernel.
  62 */
  63enum {
  64    PCI_VPB_IRQMAP_ASSUME_OK,
  65    PCI_VPB_IRQMAP_BROKEN,
  66    PCI_VPB_IRQMAP_FORCE_OK,
  67};
  68
  69typedef struct {
  70    PCIHostState parent_obj;
  71
  72    qemu_irq irq[4];
  73    MemoryRegion controlregs;
  74    MemoryRegion mem_config;
  75    MemoryRegion mem_config2;
  76    /* Containers representing the PCI address spaces */
  77    MemoryRegion pci_io_space;
  78    MemoryRegion pci_mem_space;
  79    /* Alias regions into PCI address spaces which we expose as sysbus regions.
  80     * The offsets into pci_mem_space are controlled by the imap registers.
  81     */
  82    MemoryRegion pci_io_window;
  83    MemoryRegion pci_mem_window[3];
  84    PCIBus pci_bus;
  85    PCIDevice pci_dev;
  86
  87    /* Constant for life of device: */
  88    int realview;
  89    uint32_t mem_win_size[3];
  90    uint8_t irq_mapping_prop;
  91
  92    /* Variable state: */
  93    uint32_t imap[3];
  94    uint32_t smap[3];
  95    uint32_t selfid;
  96    uint32_t flags;
  97    uint8_t irq_mapping;
  98} PCIVPBState;
  99
 100static void pci_vpb_update_window(PCIVPBState *s, int i)
 101{
 102    /* Adjust the offset of the alias region we use for
 103     * the memory window i to account for a change in the
 104     * value of the corresponding IMAP register.
 105     * Note that the semantics of the IMAP register differ
 106     * for realview and versatile variants of the controller.
 107     */
 108    hwaddr offset;
 109    if (s->realview) {
 110        /* Top bits of register (masked according to window size) provide
 111         * top bits of PCI address.
 112         */
 113        offset = s->imap[i] & ~(s->mem_win_size[i] - 1);
 114    } else {
 115        /* Bottom 4 bits of register provide top 4 bits of PCI address */
 116        offset = s->imap[i] << 28;
 117    }
 118    memory_region_set_alias_offset(&s->pci_mem_window[i], offset);
 119}
 120
 121static void pci_vpb_update_all_windows(PCIVPBState *s)
 122{
 123    /* Update all alias windows based on the current register state */
 124    int i;
 125
 126    for (i = 0; i < 3; i++) {
 127        pci_vpb_update_window(s, i);
 128    }
 129}
 130
 131static int pci_vpb_post_load(void *opaque, int version_id)
 132{
 133    PCIVPBState *s = opaque;
 134    pci_vpb_update_all_windows(s);
 135    return 0;
 136}
 137
 138static const VMStateDescription pci_vpb_vmstate = {
 139    .name = "versatile-pci",
 140    .version_id = 1,
 141    .minimum_version_id = 1,
 142    .post_load = pci_vpb_post_load,
 143    .fields = (VMStateField[]) {
 144        VMSTATE_UINT32_ARRAY(imap, PCIVPBState, 3),
 145        VMSTATE_UINT32_ARRAY(smap, PCIVPBState, 3),
 146        VMSTATE_UINT32(selfid, PCIVPBState),
 147        VMSTATE_UINT32(flags, PCIVPBState),
 148        VMSTATE_UINT8(irq_mapping, PCIVPBState),
 149        VMSTATE_END_OF_LIST()
 150    }
 151};
 152
 153#define TYPE_VERSATILE_PCI "versatile_pci"
 154#define PCI_VPB(obj) \
 155    OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI)
 156
 157#define TYPE_VERSATILE_PCI_HOST "versatile_pci_host"
 158#define PCI_VPB_HOST(obj) \
 159    OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCIHOST)
 160
 161typedef enum {
 162    PCI_IMAP0 = 0x0,
 163    PCI_IMAP1 = 0x4,
 164    PCI_IMAP2 = 0x8,
 165    PCI_SELFID = 0xc,
 166    PCI_FLAGS = 0x10,
 167    PCI_SMAP0 = 0x14,
 168    PCI_SMAP1 = 0x18,
 169    PCI_SMAP2 = 0x1c,
 170} PCIVPBControlRegs;
 171
 172static void pci_vpb_reg_write(void *opaque, hwaddr addr,
 173                              uint64_t val, unsigned size)
 174{
 175    PCIVPBState *s = opaque;
 176
 177    switch (addr) {
 178    case PCI_IMAP0:
 179    case PCI_IMAP1:
 180    case PCI_IMAP2:
 181    {
 182        int win = (addr - PCI_IMAP0) >> 2;
 183        s->imap[win] = val;
 184        pci_vpb_update_window(s, win);
 185        break;
 186    }
 187    case PCI_SELFID:
 188        s->selfid = val;
 189        break;
 190    case PCI_FLAGS:
 191        s->flags = val;
 192        break;
 193    case PCI_SMAP0:
 194    case PCI_SMAP1:
 195    case PCI_SMAP2:
 196    {
 197        int win = (addr - PCI_SMAP0) >> 2;
 198        s->smap[win] = val;
 199        break;
 200    }
 201    default:
 202        qemu_log_mask(LOG_GUEST_ERROR,
 203                      "pci_vpb_reg_write: Bad offset %x\n", (int)addr);
 204        break;
 205    }
 206}
 207
 208static uint64_t pci_vpb_reg_read(void *opaque, hwaddr addr,
 209                                 unsigned size)
 210{
 211    PCIVPBState *s = opaque;
 212
 213    switch (addr) {
 214    case PCI_IMAP0:
 215    case PCI_IMAP1:
 216    case PCI_IMAP2:
 217    {
 218        int win = (addr - PCI_IMAP0) >> 2;
 219        return s->imap[win];
 220    }
 221    case PCI_SELFID:
 222        return s->selfid;
 223    case PCI_FLAGS:
 224        return s->flags;
 225    case PCI_SMAP0:
 226    case PCI_SMAP1:
 227    case PCI_SMAP2:
 228    {
 229        int win = (addr - PCI_SMAP0) >> 2;
 230        return s->smap[win];
 231    }
 232    default:
 233        qemu_log_mask(LOG_GUEST_ERROR,
 234                      "pci_vpb_reg_read: Bad offset %x\n", (int)addr);
 235        return 0;
 236    }
 237}
 238
 239static const MemoryRegionOps pci_vpb_reg_ops = {
 240    .read = pci_vpb_reg_read,
 241    .write = pci_vpb_reg_write,
 242    .endianness = DEVICE_NATIVE_ENDIAN,
 243    .valid = {
 244        .min_access_size = 4,
 245        .max_access_size = 4,
 246    },
 247};
 248
 249static int pci_vpb_broken_irq(int slot, int irq)
 250{
 251    /* Determine whether this IRQ value for this slot represents a
 252     * known broken Linux kernel behaviour for this slot.
 253     * Return one of the PCI_VPB_IRQMAP_ constants:
 254     *   BROKEN : if this definitely looks like a broken kernel
 255     *   FORCE_OK : if this definitely looks good
 256     *   ASSUME_OK : if we can't tell
 257     */
 258    slot %= PCI_NUM_PINS;
 259
 260    if (irq == 27) {
 261        if (slot == 2) {
 262            /* Might be a Phase I kernel, or might be a fixed kernel,
 263             * since slot 2 is where we expect this IRQ.
 264             */
 265            return PCI_VPB_IRQMAP_ASSUME_OK;
 266        }
 267        /* Phase I kernel */
 268        return PCI_VPB_IRQMAP_BROKEN;
 269    }
 270    if (irq == slot + 27) {
 271        /* Phase II kernel */
 272        return PCI_VPB_IRQMAP_BROKEN;
 273    }
 274    if (irq == slot + 27 + 64) {
 275        /* Phase III kernel */
 276        return PCI_VPB_IRQMAP_BROKEN;
 277    }
 278    /* Anything else must be a fixed kernel, possibly using an
 279     * arbitrary irq map.
 280     */
 281    return PCI_VPB_IRQMAP_FORCE_OK;
 282}
 283
 284static void pci_vpb_config_write(void *opaque, hwaddr addr,
 285                                 uint64_t val, unsigned size)
 286{
 287    PCIVPBState *s = opaque;
 288    if (!s->realview && (addr & 0xff) == PCI_INTERRUPT_LINE
 289        && s->irq_mapping == PCI_VPB_IRQMAP_ASSUME_OK) {
 290        uint8_t devfn = addr >> 8;
 291        s->irq_mapping = pci_vpb_broken_irq(PCI_SLOT(devfn), val);
 292    }
 293    pci_data_write(&s->pci_bus, addr, val, size);
 294}
 295
 296static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr,
 297                                    unsigned size)
 298{
 299    PCIVPBState *s = opaque;
 300    uint32_t val;
 301    val = pci_data_read(&s->pci_bus, addr, size);
 302    return val;
 303}
 304
 305static const MemoryRegionOps pci_vpb_config_ops = {
 306    .read = pci_vpb_config_read,
 307    .write = pci_vpb_config_write,
 308    .endianness = DEVICE_NATIVE_ENDIAN,
 309};
 310
 311static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
 312{
 313    PCIVPBState *s = container_of(pci_get_bus(d), PCIVPBState, pci_bus);
 314
 315    if (s->irq_mapping == PCI_VPB_IRQMAP_BROKEN) {
 316        /* Legacy broken IRQ mapping for compatibility with old and
 317         * buggy Linux guests
 318         */
 319        return irq_num;
 320    }
 321
 322    /* Slot to IRQ mapping for RealView Platform Baseboard 926 backplane
 323     *      name    slot    IntA    IntB    IntC    IntD
 324     *      A       31      IRQ28   IRQ29   IRQ30   IRQ27
 325     *      B       30      IRQ27   IRQ28   IRQ29   IRQ30
 326     *      C       29      IRQ30   IRQ27   IRQ28   IRQ29
 327     * Slot C is for the host bridge; A and B the peripherals.
 328     * Our output irqs 0..3 correspond to the baseboard's 27..30.
 329     *
 330     * This mapping function takes account of an oddity in the PB926
 331     * board wiring, where the FPGA's P_nINTA input is connected to
 332     * the INTB connection on the board PCI edge connector, P_nINTB
 333     * is connected to INTC, and so on, so everything is one number
 334     * further round from where you might expect.
 335     */
 336    return pci_swizzle_map_irq_fn(d, irq_num + 2);
 337}
 338
 339static int pci_vpb_rv_map_irq(PCIDevice *d, int irq_num)
 340{
 341    /* Slot to IRQ mapping for RealView EB and PB1176 backplane
 342     *      name    slot    IntA    IntB    IntC    IntD
 343     *      A       31      IRQ50   IRQ51   IRQ48   IRQ49
 344     *      B       30      IRQ49   IRQ50   IRQ51   IRQ48
 345     *      C       29      IRQ48   IRQ49   IRQ50   IRQ51
 346     * Slot C is for the host bridge; A and B the peripherals.
 347     * Our output irqs 0..3 correspond to the baseboard's 48..51.
 348     *
 349     * The PB1176 and EB boards don't have the PB926 wiring oddity
 350     * described above; P_nINTA connects to INTA, P_nINTB to INTB
 351     * and so on, which is why this mapping function is different.
 352     */
 353    return pci_swizzle_map_irq_fn(d, irq_num + 3);
 354}
 355
 356static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
 357{
 358    qemu_irq *pic = opaque;
 359
 360    qemu_set_irq(pic[irq_num], level);
 361}
 362
 363static void pci_vpb_reset(DeviceState *d)
 364{
 365    PCIVPBState *s = PCI_VPB(d);
 366
 367    s->imap[0] = 0;
 368    s->imap[1] = 0;
 369    s->imap[2] = 0;
 370    s->smap[0] = 0;
 371    s->smap[1] = 0;
 372    s->smap[2] = 0;
 373    s->selfid = 0;
 374    s->flags = 0;
 375    s->irq_mapping = s->irq_mapping_prop;
 376
 377    pci_vpb_update_all_windows(s);
 378}
 379
 380static void pci_vpb_init(Object *obj)
 381{
 382    PCIVPBState *s = PCI_VPB(obj);
 383
 384    /* Window sizes for VersatilePB; realview_pci's init will override */
 385    s->mem_win_size[0] = 0x0c000000;
 386    s->mem_win_size[1] = 0x10000000;
 387    s->mem_win_size[2] = 0x10000000;
 388}
 389
 390static void pci_vpb_realize(DeviceState *dev, Error **errp)
 391{
 392    PCIVPBState *s = PCI_VPB(dev);
 393    PCIHostState *h = PCI_HOST_BRIDGE(dev);
 394    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 395    pci_map_irq_fn mapfn;
 396    int i;
 397
 398    memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32);
 399    memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32);
 400
 401    pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci",
 402                             &s->pci_mem_space, &s->pci_io_space,
 403                             PCI_DEVFN(11, 0), TYPE_PCI_BUS);
 404    h->bus = &s->pci_bus;
 405
 406    object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST);
 407    qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
 408
 409    for (i = 0; i < 4; i++) {
 410        sysbus_init_irq(sbd, &s->irq[i]);
 411    }
 412
 413    if (s->realview) {
 414        mapfn = pci_vpb_rv_map_irq;
 415    } else {
 416        mapfn = pci_vpb_map_irq;
 417    }
 418
 419    pci_bus_irqs(&s->pci_bus, pci_vpb_set_irq, mapfn, s->irq, 4);
 420
 421    /* Our memory regions are:
 422     * 0 : our control registers
 423     * 1 : PCI self config window
 424     * 2 : PCI config window
 425     * 3 : PCI IO window
 426     * 4..6 : PCI memory windows
 427     */
 428    memory_region_init_io(&s->controlregs, OBJECT(s), &pci_vpb_reg_ops, s,
 429                          "pci-vpb-regs", 0x1000);
 430    sysbus_init_mmio(sbd, &s->controlregs);
 431    memory_region_init_io(&s->mem_config, OBJECT(s), &pci_vpb_config_ops, s,
 432                          "pci-vpb-selfconfig", 0x1000000);
 433    sysbus_init_mmio(sbd, &s->mem_config);
 434    memory_region_init_io(&s->mem_config2, OBJECT(s), &pci_vpb_config_ops, s,
 435                          "pci-vpb-config", 0x1000000);
 436    sysbus_init_mmio(sbd, &s->mem_config2);
 437
 438    /* The window into I/O space is always into a fixed base address;
 439     * its size is the same for both realview and versatile.
 440     */
 441    memory_region_init_alias(&s->pci_io_window, OBJECT(s), "pci-vbp-io-window",
 442                             &s->pci_io_space, 0, 0x100000);
 443
 444    sysbus_init_mmio(sbd, &s->pci_io_space);
 445
 446    /* Create the alias regions corresponding to our three windows onto
 447     * PCI memory space. The sizes vary from board to board; the base
 448     * offsets are guest controllable via the IMAP registers.
 449     */
 450    for (i = 0; i < 3; i++) {
 451        memory_region_init_alias(&s->pci_mem_window[i], OBJECT(s), "pci-vbp-window",
 452                                 &s->pci_mem_space, 0, s->mem_win_size[i]);
 453        sysbus_init_mmio(sbd, &s->pci_mem_window[i]);
 454    }
 455
 456    /* TODO Remove once realize propagates to child devices. */
 457    object_property_set_bool(OBJECT(&s->pci_bus), true, "realized", errp);
 458    object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
 459}
 460
 461static void versatile_pci_host_realize(PCIDevice *d, Error **errp)
 462{
 463    pci_set_word(d->config + PCI_STATUS,
 464                 PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
 465    pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
 466}
 467
 468static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
 469{
 470    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 471    DeviceClass *dc = DEVICE_CLASS(klass);
 472
 473    k->realize = versatile_pci_host_realize;
 474    k->vendor_id = PCI_VENDOR_ID_XILINX;
 475    k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
 476    k->class_id = PCI_CLASS_PROCESSOR_CO;
 477    /*
 478     * PCI-facing part of the host bridge, not usable without the
 479     * host-facing part, which can't be device_add'ed, yet.
 480     */
 481    dc->user_creatable = false;
 482}
 483
 484static const TypeInfo versatile_pci_host_info = {
 485    .name          = TYPE_VERSATILE_PCI_HOST,
 486    .parent        = TYPE_PCI_DEVICE,
 487    .instance_size = sizeof(PCIDevice),
 488    .class_init    = versatile_pci_host_class_init,
 489    .interfaces = (InterfaceInfo[]) {
 490        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
 491        { },
 492    },
 493};
 494
 495static Property pci_vpb_properties[] = {
 496    DEFINE_PROP_UINT8("broken-irq-mapping", PCIVPBState, irq_mapping_prop,
 497                      PCI_VPB_IRQMAP_ASSUME_OK),
 498    DEFINE_PROP_END_OF_LIST()
 499};
 500
 501static void pci_vpb_class_init(ObjectClass *klass, void *data)
 502{
 503    DeviceClass *dc = DEVICE_CLASS(klass);
 504
 505    dc->realize = pci_vpb_realize;
 506    dc->reset = pci_vpb_reset;
 507    dc->vmsd = &pci_vpb_vmstate;
 508    dc->props = pci_vpb_properties;
 509}
 510
 511static const TypeInfo pci_vpb_info = {
 512    .name          = TYPE_VERSATILE_PCI,
 513    .parent        = TYPE_PCI_HOST_BRIDGE,
 514    .instance_size = sizeof(PCIVPBState),
 515    .instance_init = pci_vpb_init,
 516    .class_init    = pci_vpb_class_init,
 517};
 518
 519static void pci_realview_init(Object *obj)
 520{
 521    PCIVPBState *s = PCI_VPB(obj);
 522
 523    s->realview = 1;
 524    /* The PCI window sizes are different on Realview boards */
 525    s->mem_win_size[0] = 0x01000000;
 526    s->mem_win_size[1] = 0x04000000;
 527    s->mem_win_size[2] = 0x08000000;
 528}
 529
 530static const TypeInfo pci_realview_info = {
 531    .name          = "realview_pci",
 532    .parent        = TYPE_VERSATILE_PCI,
 533    .instance_init = pci_realview_init,
 534};
 535
 536static void versatile_pci_register_types(void)
 537{
 538    type_register_static(&pci_vpb_info);
 539    type_register_static(&pci_realview_info);
 540    type_register_static(&versatile_pci_host_info);
 541}
 542
 543type_init(versatile_pci_register_types)
 544