qemu/hw/ppc/spapr_vio.c
<<
>>
Prefs
   1/*
   2 * QEMU sPAPR VIO code
   3 *
   4 * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
   5 * Based on the s390 virtio bus code:
   6 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
   7 *
   8 * This library is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU Lesser General Public
  10 * License as published by the Free Software Foundation; either
  11 * version 2 of the License, or (at your option) any later version.
  12 *
  13 * This library is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 * Lesser General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU Lesser General Public
  19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include "qemu/osdep.h"
  23#include "qemu/error-report.h"
  24#include "qapi/error.h"
  25#include "qapi/visitor.h"
  26#include "hw/hw.h"
  27#include "qemu/log.h"
  28#include "sysemu/sysemu.h"
  29#include "hw/boards.h"
  30#include "hw/loader.h"
  31#include "elf.h"
  32#include "hw/sysbus.h"
  33#include "sysemu/kvm.h"
  34#include "sysemu/device_tree.h"
  35#include "kvm_ppc.h"
  36#include "sysemu/qtest.h"
  37
  38#include "hw/ppc/spapr.h"
  39#include "hw/ppc/spapr_vio.h"
  40#include "hw/ppc/fdt.h"
  41#include "trace.h"
  42
  43#include <libfdt.h>
  44
  45#define SPAPR_VIO_REG_BASE 0x71000000
  46
  47static void spapr_vio_get_irq(Object *obj, Visitor *v, const char *name,
  48                              void *opaque, Error **errp)
  49{
  50    Property *prop = opaque;
  51    uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
  52
  53    visit_type_uint32(v, name, ptr, errp);
  54}
  55
  56static void spapr_vio_set_irq(Object *obj, Visitor *v, const char *name,
  57                              void *opaque, Error **errp)
  58{
  59    Property *prop = opaque;
  60    uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
  61
  62    if (!qtest_enabled()) {
  63        warn_report(TYPE_VIO_SPAPR_DEVICE " '%s' property is deprecated", name);
  64    }
  65    visit_type_uint32(v, name, ptr, errp);
  66}
  67
  68static const PropertyInfo spapr_vio_irq_propinfo = {
  69    .name = "irq",
  70    .get = spapr_vio_get_irq,
  71    .set = spapr_vio_set_irq,
  72};
  73
  74static Property spapr_vio_props[] = {
  75    DEFINE_PROP("irq", VIOsPAPRDevice, irq, spapr_vio_irq_propinfo, uint32_t),
  76    DEFINE_PROP_END_OF_LIST(),
  77};
  78
  79static char *spapr_vio_get_dev_name(DeviceState *qdev)
  80{
  81    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
  82    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  83
  84    /* Device tree style name device@reg */
  85    return g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
  86}
  87
  88static void spapr_vio_bus_class_init(ObjectClass *klass, void *data)
  89{
  90    BusClass *k = BUS_CLASS(klass);
  91
  92    k->get_dev_path = spapr_vio_get_dev_name;
  93    k->get_fw_dev_path = spapr_vio_get_dev_name;
  94}
  95
  96static const TypeInfo spapr_vio_bus_info = {
  97    .name = TYPE_SPAPR_VIO_BUS,
  98    .parent = TYPE_BUS,
  99    .class_init = spapr_vio_bus_class_init,
 100    .instance_size = sizeof(VIOsPAPRBus),
 101};
 102
 103VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
 104{
 105    BusChild *kid;
 106    VIOsPAPRDevice *dev = NULL;
 107
 108    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 109        dev = (VIOsPAPRDevice *)kid->child;
 110        if (dev->reg == reg) {
 111            return dev;
 112        }
 113    }
 114
 115    return NULL;
 116}
 117
 118static int vio_make_devnode(VIOsPAPRDevice *dev,
 119                            void *fdt)
 120{
 121    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 122    int vdevice_off, node_off, ret;
 123    char *dt_name;
 124
 125    vdevice_off = fdt_path_offset(fdt, "/vdevice");
 126    if (vdevice_off < 0) {
 127        return vdevice_off;
 128    }
 129
 130    dt_name = spapr_vio_get_dev_name(DEVICE(dev));
 131    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
 132    g_free(dt_name);
 133    if (node_off < 0) {
 134        return node_off;
 135    }
 136
 137    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
 138    if (ret < 0) {
 139        return ret;
 140    }
 141
 142    if (pc->dt_type) {
 143        ret = fdt_setprop_string(fdt, node_off, "device_type",
 144                                 pc->dt_type);
 145        if (ret < 0) {
 146            return ret;
 147        }
 148    }
 149
 150    if (pc->dt_compatible) {
 151        ret = fdt_setprop_string(fdt, node_off, "compatible",
 152                                 pc->dt_compatible);
 153        if (ret < 0) {
 154            return ret;
 155        }
 156    }
 157
 158    if (dev->irq) {
 159        uint32_t ints_prop[2];
 160
 161        spapr_dt_xics_irq(ints_prop, dev->irq, false);
 162        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
 163                          sizeof(ints_prop));
 164        if (ret < 0) {
 165            return ret;
 166        }
 167    }
 168
 169    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->tcet);
 170    if (ret < 0) {
 171        return ret;
 172    }
 173
 174    if (pc->devnode) {
 175        ret = (pc->devnode)(dev, fdt, node_off);
 176        if (ret < 0) {
 177            return ret;
 178        }
 179    }
 180
 181    return node_off;
 182}
 183
 184/*
 185 * CRQ handling
 186 */
 187static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 188                              target_ulong opcode, target_ulong *args)
 189{
 190    target_ulong reg = args[0];
 191    target_ulong queue_addr = args[1];
 192    target_ulong queue_len = args[2];
 193    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 194
 195    if (!dev) {
 196        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
 197        return H_PARAMETER;
 198    }
 199
 200    /* We can't grok a queue size bigger than 256M for now */
 201    if (queue_len < 0x1000 || queue_len > 0x10000000) {
 202        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
 203                      ")\n", queue_len);
 204        return H_PARAMETER;
 205    }
 206
 207    /* Check queue alignment */
 208    if (queue_addr & 0xfff) {
 209        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
 210        return H_PARAMETER;
 211    }
 212
 213    /* Check if device supports CRQs */
 214    if (!dev->crq.SendFunc) {
 215        hcall_dprintf("Device does not support CRQ\n");
 216        return H_NOT_FOUND;
 217    }
 218
 219    /* Already a queue ? */
 220    if (dev->crq.qsize) {
 221        hcall_dprintf("CRQ already registered\n");
 222        return H_RESOURCE;
 223    }
 224    dev->crq.qladdr = queue_addr;
 225    dev->crq.qsize = queue_len;
 226    dev->crq.qnext = 0;
 227
 228    trace_spapr_vio_h_reg_crq(reg, queue_addr, queue_len);
 229    return H_SUCCESS;
 230}
 231
 232static target_ulong free_crq(VIOsPAPRDevice *dev)
 233{
 234    dev->crq.qladdr = 0;
 235    dev->crq.qsize = 0;
 236    dev->crq.qnext = 0;
 237
 238    trace_spapr_vio_free_crq(dev->reg);
 239
 240    return H_SUCCESS;
 241}
 242
 243static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 244                               target_ulong opcode, target_ulong *args)
 245{
 246    target_ulong reg = args[0];
 247    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 248
 249    if (!dev) {
 250        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
 251        return H_PARAMETER;
 252    }
 253
 254    return free_crq(dev);
 255}
 256
 257static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 258                               target_ulong opcode, target_ulong *args)
 259{
 260    target_ulong reg = args[0];
 261    target_ulong msg_hi = args[1];
 262    target_ulong msg_lo = args[2];
 263    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 264    uint64_t crq_mangle[2];
 265
 266    if (!dev) {
 267        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
 268        return H_PARAMETER;
 269    }
 270    crq_mangle[0] = cpu_to_be64(msg_hi);
 271    crq_mangle[1] = cpu_to_be64(msg_lo);
 272
 273    if (dev->crq.SendFunc) {
 274        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
 275    }
 276
 277    return H_HARDWARE;
 278}
 279
 280static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 281                                 target_ulong opcode, target_ulong *args)
 282{
 283    target_ulong reg = args[0];
 284    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 285
 286    if (!dev) {
 287        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
 288        return H_PARAMETER;
 289    }
 290
 291    return 0;
 292}
 293
 294/* Returns negative error, 0 success, or positive: queue full */
 295int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
 296{
 297    int rc;
 298    uint8_t byte;
 299
 300    if (!dev->crq.qsize) {
 301        error_report("spapr_vio_send_creq on uninitialized queue");
 302        return -1;
 303    }
 304
 305    /* Maybe do a fast path for KVM just writing to the pages */
 306    rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
 307    if (rc) {
 308        return rc;
 309    }
 310    if (byte != 0) {
 311        return 1;
 312    }
 313
 314    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
 315                             &crq[8], 8);
 316    if (rc) {
 317        return rc;
 318    }
 319
 320    kvmppc_eieio();
 321
 322    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
 323    if (rc) {
 324        return rc;
 325    }
 326
 327    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
 328
 329    if (dev->signal_state & 1) {
 330        qemu_irq_pulse(spapr_vio_qirq(dev));
 331    }
 332
 333    return 0;
 334}
 335
 336/* "quiesce" handling */
 337
 338static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
 339{
 340    if (dev->tcet) {
 341        device_reset(DEVICE(dev->tcet));
 342    }
 343    free_crq(dev);
 344}
 345
 346void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass)
 347{
 348    if (!dev->tcet) {
 349        return;
 350    }
 351
 352    memory_region_set_enabled(&dev->mrbypass, bypass);
 353    memory_region_set_enabled(spapr_tce_get_iommu(dev->tcet), !bypass);
 354
 355    dev->tcet->bypass = bypass;
 356}
 357
 358static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 359                                uint32_t token,
 360                                uint32_t nargs, target_ulong args,
 361                                uint32_t nret, target_ulong rets)
 362{
 363    VIOsPAPRBus *bus = spapr->vio_bus;
 364    VIOsPAPRDevice *dev;
 365    uint32_t unit, enable;
 366
 367    if (nargs != 2) {
 368        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 369        return;
 370    }
 371    unit = rtas_ld(args, 0);
 372    enable = rtas_ld(args, 1);
 373    dev = spapr_vio_find_by_reg(bus, unit);
 374    if (!dev) {
 375        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 376        return;
 377    }
 378
 379    if (!dev->tcet) {
 380        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 381        return;
 382    }
 383
 384    spapr_vio_set_bypass(dev, !!enable);
 385
 386    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 387}
 388
 389static void rtas_quiesce(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 390                         uint32_t token,
 391                         uint32_t nargs, target_ulong args,
 392                         uint32_t nret, target_ulong rets)
 393{
 394    VIOsPAPRBus *bus = spapr->vio_bus;
 395    BusChild *kid;
 396    VIOsPAPRDevice *dev = NULL;
 397
 398    if (nargs != 0) {
 399        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 400        return;
 401    }
 402
 403    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 404        dev = (VIOsPAPRDevice *)kid->child;
 405        spapr_vio_quiesce_one(dev);
 406    }
 407
 408    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 409}
 410
 411static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
 412{
 413    VIOsPAPRBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
 414    BusChild *kid;
 415    VIOsPAPRDevice *other;
 416
 417    /*
 418     * Check for a device other than the given one which is already
 419     * using the requested address. We have to open code this because
 420     * the given dev might already be in the list.
 421     */
 422    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 423        other = VIO_SPAPR_DEVICE(kid->child);
 424
 425        if (other != dev && other->reg == dev->reg) {
 426            return other;
 427        }
 428    }
 429
 430    return 0;
 431}
 432
 433static void spapr_vio_busdev_reset(DeviceState *qdev)
 434{
 435    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
 436    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 437
 438    /* Shut down the request queue and TCEs if necessary */
 439    spapr_vio_quiesce_one(dev);
 440
 441    dev->signal_state = 0;
 442
 443    spapr_vio_set_bypass(dev, false);
 444    if (pc->reset) {
 445        pc->reset(dev);
 446    }
 447}
 448
 449/*
 450 * The register property of a VIO device is defined in livirt using
 451 * 0x1000 as a base register number plus a 0x1000 increment. For the
 452 * VIO tty device, the base number is changed to 0x30000000. QEMU uses
 453 * a base register number of 0x71000000 and then a simple increment.
 454 *
 455 * The formula below tries to compute a unique index number from the
 456 * register value that will be used to define the IRQ number of the
 457 * VIO device.
 458 *
 459 * A maximum of 256 VIO devices is covered. Collisions are possible
 460 * but they will be detected when the IRQ is claimed.
 461 */
 462static inline uint32_t spapr_vio_reg_to_irq(uint32_t reg)
 463{
 464    uint32_t irq;
 465
 466    if (reg >= SPAPR_VIO_REG_BASE) {
 467        /*
 468         * VIO device register values when allocated by QEMU. For
 469         * these, we simply mask the high bits to fit the overall
 470         * range: [0x00 - 0xff].
 471         *
 472         * The nvram VIO device (reg=0x71000000) is a static device of
 473         * the pseries machine and so is always allocated by QEMU. Its
 474         * IRQ number is 0x0.
 475         */
 476        irq = reg & 0xff;
 477
 478    } else if (reg >= 0x30000000) {
 479        /*
 480         * VIO tty devices register values, when allocated by livirt,
 481         * are mapped in range [0xf0 - 0xff], gives us a maximum of 16
 482         * vtys.
 483         */
 484        irq = 0xf0 | ((reg >> 12) & 0xf);
 485
 486    } else {
 487        /*
 488         * Other VIO devices register values, when allocated by
 489         * livirt, should be mapped in range [0x00 - 0xef]. Conflicts
 490         * will be detected when IRQ is claimed.
 491         */
 492        irq = (reg >> 12) & 0xff;
 493    }
 494
 495    return SPAPR_IRQ_VIO | irq;
 496}
 497
 498static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
 499{
 500    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
 501    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
 502    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 503    char *id;
 504    Error *local_err = NULL;
 505
 506    if (dev->reg != -1) {
 507        /*
 508         * Explicitly assigned address, just verify that no-one else
 509         * is using it.  other mechanism). We have to open code this
 510         * rather than using spapr_vio_find_by_reg() because sdev
 511         * itself is already in the list.
 512         */
 513        VIOsPAPRDevice *other = reg_conflict(dev);
 514
 515        if (other) {
 516            error_setg(errp, "%s and %s devices conflict at address %#x",
 517                       object_get_typename(OBJECT(qdev)),
 518                       object_get_typename(OBJECT(&other->qdev)),
 519                       dev->reg);
 520            return;
 521        }
 522    } else {
 523        /* Need to assign an address */
 524        VIOsPAPRBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
 525
 526        do {
 527            dev->reg = bus->next_reg++;
 528        } while (reg_conflict(dev));
 529    }
 530
 531    /* Don't overwrite ids assigned on the command line */
 532    if (!dev->qdev.id) {
 533        id = spapr_vio_get_dev_name(DEVICE(dev));
 534        dev->qdev.id = id;
 535    }
 536
 537    if (!dev->irq) {
 538        dev->irq = spapr_vio_reg_to_irq(dev->reg);
 539
 540        if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
 541            dev->irq = spapr_irq_findone(spapr, &local_err);
 542            if (local_err) {
 543                error_propagate(errp, local_err);
 544                return;
 545            }
 546        }
 547    }
 548
 549    spapr_irq_claim(spapr, dev->irq, false, &local_err);
 550    if (local_err) {
 551        error_propagate(errp, local_err);
 552        return;
 553    }
 554
 555    if (pc->rtce_window_size) {
 556        uint32_t liobn = SPAPR_VIO_LIOBN(dev->reg);
 557
 558        memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root",
 559                           ram_size);
 560        memory_region_init_alias(&dev->mrbypass, OBJECT(dev),
 561                                 "iommu-spapr-bypass", get_system_memory(),
 562                                 0, ram_size);
 563        memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1);
 564        address_space_init(&dev->as, &dev->mrroot, qdev->id);
 565
 566        dev->tcet = spapr_tce_new_table(qdev, liobn);
 567        spapr_tce_table_enable(dev->tcet, SPAPR_TCE_PAGE_SHIFT, 0,
 568                               pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT);
 569        dev->tcet->vdev = dev;
 570        memory_region_add_subregion_overlap(&dev->mrroot, 0,
 571                                            spapr_tce_get_iommu(dev->tcet), 2);
 572    }
 573
 574    pc->realize(dev, errp);
 575}
 576
 577static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 578                                 target_ulong opcode,
 579                                 target_ulong *args)
 580{
 581    target_ulong reg = args[0];
 582    target_ulong mode = args[1];
 583    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 584    VIOsPAPRDeviceClass *pc;
 585
 586    if (!dev) {
 587        return H_PARAMETER;
 588    }
 589
 590    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 591
 592    if (mode & ~pc->signal_mask) {
 593        return H_PARAMETER;
 594    }
 595
 596    dev->signal_state = mode;
 597
 598    return H_SUCCESS;
 599}
 600
 601VIOsPAPRBus *spapr_vio_bus_init(void)
 602{
 603    VIOsPAPRBus *bus;
 604    BusState *qbus;
 605    DeviceState *dev;
 606
 607    /* Create bridge device */
 608    dev = qdev_create(NULL, TYPE_SPAPR_VIO_BRIDGE);
 609    qdev_init_nofail(dev);
 610
 611    /* Create bus on bridge device */
 612    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
 613    bus = SPAPR_VIO_BUS(qbus);
 614    bus->next_reg = SPAPR_VIO_REG_BASE;
 615
 616    /* hcall-vio */
 617    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
 618
 619    /* hcall-crq */
 620    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
 621    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
 622    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
 623    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
 624
 625    /* RTAS calls */
 626    spapr_rtas_register(RTAS_IBM_SET_TCE_BYPASS, "ibm,set-tce-bypass",
 627                        rtas_set_tce_bypass);
 628    spapr_rtas_register(RTAS_QUIESCE, "quiesce", rtas_quiesce);
 629
 630    return bus;
 631}
 632
 633static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
 634{
 635    DeviceClass *dc = DEVICE_CLASS(klass);
 636
 637    dc->fw_name = "vdevice";
 638}
 639
 640static const TypeInfo spapr_vio_bridge_info = {
 641    .name          = TYPE_SPAPR_VIO_BRIDGE,
 642    .parent        = TYPE_SYS_BUS_DEVICE,
 643    .class_init    = spapr_vio_bridge_class_init,
 644};
 645
 646const VMStateDescription vmstate_spapr_vio = {
 647    .name = "spapr_vio",
 648    .version_id = 1,
 649    .minimum_version_id = 1,
 650    .fields = (VMStateField[]) {
 651        /* Sanity check */
 652        VMSTATE_UINT32_EQUAL(reg, VIOsPAPRDevice, NULL),
 653        VMSTATE_UINT32_EQUAL(irq, VIOsPAPRDevice, NULL),
 654
 655        /* General VIO device state */
 656        VMSTATE_UINT64(signal_state, VIOsPAPRDevice),
 657        VMSTATE_UINT64(crq.qladdr, VIOsPAPRDevice),
 658        VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice),
 659        VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice),
 660
 661        VMSTATE_END_OF_LIST()
 662    },
 663};
 664
 665static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
 666{
 667    DeviceClass *k = DEVICE_CLASS(klass);
 668    k->realize = spapr_vio_busdev_realize;
 669    k->reset = spapr_vio_busdev_reset;
 670    k->bus_type = TYPE_SPAPR_VIO_BUS;
 671    k->props = spapr_vio_props;
 672}
 673
 674static const TypeInfo spapr_vio_type_info = {
 675    .name = TYPE_VIO_SPAPR_DEVICE,
 676    .parent = TYPE_DEVICE,
 677    .instance_size = sizeof(VIOsPAPRDevice),
 678    .abstract = true,
 679    .class_size = sizeof(VIOsPAPRDeviceClass),
 680    .class_init = vio_spapr_device_class_init,
 681};
 682
 683static void spapr_vio_register_types(void)
 684{
 685    type_register_static(&spapr_vio_bus_info);
 686    type_register_static(&spapr_vio_bridge_info);
 687    type_register_static(&spapr_vio_type_info);
 688}
 689
 690type_init(spapr_vio_register_types)
 691
 692static int compare_reg(const void *p1, const void *p2)
 693{
 694    VIOsPAPRDevice const *dev1, *dev2;
 695
 696    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
 697    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
 698
 699    if (dev1->reg < dev2->reg) {
 700        return -1;
 701    }
 702    if (dev1->reg == dev2->reg) {
 703        return 0;
 704    }
 705
 706    /* dev1->reg > dev2->reg */
 707    return 1;
 708}
 709
 710void spapr_dt_vdevice(VIOsPAPRBus *bus, void *fdt)
 711{
 712    DeviceState *qdev, **qdevs;
 713    BusChild *kid;
 714    int i, num, ret = 0;
 715    int node;
 716
 717    _FDT(node = fdt_add_subnode(fdt, 0, "vdevice"));
 718
 719    _FDT(fdt_setprop_string(fdt, node, "device_type", "vdevice"));
 720    _FDT(fdt_setprop_string(fdt, node, "compatible", "IBM,vdevice"));
 721    _FDT(fdt_setprop_cell(fdt, node, "#address-cells", 1));
 722    _FDT(fdt_setprop_cell(fdt, node, "#size-cells", 0));
 723    _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
 724    _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));
 725
 726    /* Count qdevs on the bus list */
 727    num = 0;
 728    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 729        num++;
 730    }
 731
 732    /* Copy out into an array of pointers */
 733    qdevs = g_malloc(sizeof(qdev) * num);
 734    num = 0;
 735    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 736        qdevs[num++] = kid->child;
 737    }
 738
 739    /* Sort the array */
 740    qsort(qdevs, num, sizeof(qdev), compare_reg);
 741
 742    /* Hack alert. Give the devices to libfdt in reverse order, we happen
 743     * to know that will mean they are in forward order in the tree. */
 744    for (i = num - 1; i >= 0; i--) {
 745        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
 746        VIOsPAPRDeviceClass *vdc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 747
 748        ret = vio_make_devnode(dev, fdt);
 749        if (ret < 0) {
 750            error_report("Couldn't create device node /vdevice/%s@%"PRIx32,
 751                         vdc->dt_name, dev->reg);
 752            exit(1);
 753        }
 754    }
 755
 756    g_free(qdevs);
 757}
 758
 759gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus)
 760{
 761    VIOsPAPRDevice *dev;
 762    char *name, *path;
 763
 764    dev = spapr_vty_get_default(bus);
 765    if (!dev) {
 766        return NULL;
 767    }
 768
 769    name = spapr_vio_get_dev_name(DEVICE(dev));
 770    path = g_strdup_printf("/vdevice/%s", name);
 771
 772    g_free(name);
 773    return path;
 774}
 775