qemu/hw/ppc/spapr_drc.c
<<
>>
Prefs
   1/*
   2 * QEMU SPAPR Dynamic Reconfiguration Connector Implementation
   3 *
   4 * Copyright IBM Corp. 2014
   5 *
   6 * Authors:
   7 *  Michael Roth      <mdroth@linux.vnet.ibm.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 "hw/ppc/spapr_drc.h"
  14#include "qom/object.h"
  15#include "hw/qdev.h"
  16#include "qapi/visitor.h"
  17#include "qemu/error-report.h"
  18#include "hw/ppc/spapr.h" /* for RTAS return codes */
  19
  20/* #define DEBUG_SPAPR_DRC */
  21
  22#ifdef DEBUG_SPAPR_DRC
  23#define DPRINTF(fmt, ...) \
  24    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  25#define DPRINTFN(fmt, ...) \
  26    do { DPRINTF(fmt, ## __VA_ARGS__); fprintf(stderr, "\n"); } while (0)
  27#else
  28#define DPRINTF(fmt, ...) \
  29    do { } while (0)
  30#define DPRINTFN(fmt, ...) \
  31    do { } while (0)
  32#endif
  33
  34#define DRC_CONTAINER_PATH "/dr-connector"
  35#define DRC_INDEX_TYPE_SHIFT 28
  36#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
  37
  38static sPAPRDRConnectorTypeShift get_type_shift(sPAPRDRConnectorType type)
  39{
  40    uint32_t shift = 0;
  41
  42    /* make sure this isn't SPAPR_DR_CONNECTOR_TYPE_ANY, or some
  43     * other wonky value.
  44     */
  45    g_assert(is_power_of_2(type));
  46
  47    while (type != (1 << shift)) {
  48        shift++;
  49    }
  50    return shift;
  51}
  52
  53static uint32_t get_index(sPAPRDRConnector *drc)
  54{
  55    /* no set format for a drc index: it only needs to be globally
  56     * unique. this is how we encode the DRC type on bare-metal
  57     * however, so might as well do that here
  58     */
  59    return (get_type_shift(drc->type) << DRC_INDEX_TYPE_SHIFT) |
  60            (drc->id & DRC_INDEX_ID_MASK);
  61}
  62
  63static uint32_t set_isolation_state(sPAPRDRConnector *drc,
  64                                    sPAPRDRIsolationState state)
  65{
  66    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
  67
  68    DPRINTFN("drc: %x, set_isolation_state: %x", get_index(drc), state);
  69
  70    if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
  71        /* cannot unisolate a non-existant resource, and, or resources
  72         * which are in an 'UNUSABLE' allocation state. (PAPR 2.7, 13.5.3.5)
  73         */
  74        if (!drc->dev ||
  75            drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
  76            return RTAS_OUT_NO_SUCH_INDICATOR;
  77        }
  78    }
  79
  80    drc->isolation_state = state;
  81
  82    if (drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
  83        /* if we're awaiting release, but still in an unconfigured state,
  84         * it's likely the guest is still in the process of configuring
  85         * the device and is transitioning the devices to an ISOLATED
  86         * state as a part of that process. so we only complete the
  87         * removal when this transition happens for a device in a
  88         * configured state, as suggested by the state diagram from
  89         * PAPR+ 2.7, 13.4
  90         */
  91        if (drc->awaiting_release) {
  92            if (drc->configured) {
  93                DPRINTFN("finalizing device removal");
  94                drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
  95                             drc->detach_cb_opaque, NULL);
  96            } else {
  97                DPRINTFN("deferring device removal on unconfigured device\n");
  98            }
  99        }
 100        drc->configured = false;
 101    }
 102
 103    return RTAS_OUT_SUCCESS;
 104}
 105
 106static uint32_t set_indicator_state(sPAPRDRConnector *drc,
 107                                    sPAPRDRIndicatorState state)
 108{
 109    DPRINTFN("drc: %x, set_indicator_state: %x", get_index(drc), state);
 110    drc->indicator_state = state;
 111    return RTAS_OUT_SUCCESS;
 112}
 113
 114static uint32_t set_allocation_state(sPAPRDRConnector *drc,
 115                                     sPAPRDRAllocationState state)
 116{
 117    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 118
 119    DPRINTFN("drc: %x, set_allocation_state: %x", get_index(drc), state);
 120
 121    if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
 122        /* if there's no resource/device associated with the DRC, there's
 123         * no way for us to put it in an allocation state consistent with
 124         * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should
 125         * result in an RTAS return code of -3 / "no such indicator"
 126         */
 127        if (!drc->dev) {
 128            return RTAS_OUT_NO_SUCH_INDICATOR;
 129        }
 130    }
 131
 132    if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) {
 133        drc->allocation_state = state;
 134        if (drc->awaiting_release &&
 135            drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
 136            DPRINTFN("finalizing device removal");
 137            drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
 138                         drc->detach_cb_opaque, NULL);
 139        }
 140    }
 141    return RTAS_OUT_SUCCESS;
 142}
 143
 144static uint32_t get_type(sPAPRDRConnector *drc)
 145{
 146    return drc->type;
 147}
 148
 149static const char *get_name(sPAPRDRConnector *drc)
 150{
 151    return drc->name;
 152}
 153
 154static const void *get_fdt(sPAPRDRConnector *drc, int *fdt_start_offset)
 155{
 156    if (fdt_start_offset) {
 157        *fdt_start_offset = drc->fdt_start_offset;
 158    }
 159    return drc->fdt;
 160}
 161
 162static void set_configured(sPAPRDRConnector *drc)
 163{
 164    DPRINTFN("drc: %x, set_configured", get_index(drc));
 165
 166    if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
 167        /* guest should be not configuring an isolated device */
 168        DPRINTFN("drc: %x, set_configured: skipping isolated device",
 169                 get_index(drc));
 170        return;
 171    }
 172    drc->configured = true;
 173}
 174
 175/*
 176 * dr-entity-sense sensor value
 177 * returned via get-sensor-state RTAS calls
 178 * as expected by state diagram in PAPR+ 2.7, 13.4
 179 * based on the current allocation/indicator/power states
 180 * for the DR connector.
 181 */
 182static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
 183{
 184    if (drc->dev) {
 185        if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
 186            drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
 187            /* for logical DR, we return a state of UNUSABLE
 188             * iff the allocation state UNUSABLE.
 189             * Otherwise, report the state as USABLE/PRESENT,
 190             * as we would for PCI.
 191             */
 192            *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
 193        } else {
 194            /* this assumes all PCI devices are assigned to
 195             * a 'live insertion' power domain, where QEMU
 196             * manages power state automatically as opposed
 197             * to the guest. present, non-PCI resources are
 198             * unaffected by power state.
 199             */
 200            *state = SPAPR_DR_ENTITY_SENSE_PRESENT;
 201        }
 202    } else {
 203        if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
 204            /* PCI devices, and only PCI devices, use EMPTY
 205             * in cases where we'd otherwise use UNUSABLE
 206             */
 207            *state = SPAPR_DR_ENTITY_SENSE_EMPTY;
 208        } else {
 209            *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
 210        }
 211    }
 212
 213    DPRINTFN("drc: %x, entity_sense: %x", get_index(drc), state);
 214    return RTAS_OUT_SUCCESS;
 215}
 216
 217static void prop_get_index(Object *obj, Visitor *v, void *opaque,
 218                                  const char *name, Error **errp)
 219{
 220    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 221    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 222    uint32_t value = (uint32_t)drck->get_index(drc);
 223    visit_type_uint32(v, &value, name, errp);
 224}
 225
 226static void prop_get_type(Object *obj, Visitor *v, void *opaque,
 227                          const char *name, Error **errp)
 228{
 229    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 230    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 231    uint32_t value = (uint32_t)drck->get_type(drc);
 232    visit_type_uint32(v, &value, name, errp);
 233}
 234
 235static char *prop_get_name(Object *obj, Error **errp)
 236{
 237    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 238    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 239    return g_strdup(drck->get_name(drc));
 240}
 241
 242static void prop_get_entity_sense(Object *obj, Visitor *v, void *opaque,
 243                                  const char *name, Error **errp)
 244{
 245    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 246    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 247    uint32_t value;
 248
 249    drck->entity_sense(drc, &value);
 250    visit_type_uint32(v, &value, name, errp);
 251}
 252
 253static void prop_get_fdt(Object *obj, Visitor *v, void *opaque,
 254                        const char *name, Error **errp)
 255{
 256    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 257    Error *err = NULL;
 258    int fdt_offset_next, fdt_offset, fdt_depth;
 259    void *fdt;
 260
 261    if (!drc->fdt) {
 262        visit_start_struct(v, NULL, NULL, name, 0, &err);
 263        if (!err) {
 264            visit_end_struct(v, &err);
 265        }
 266        error_propagate(errp, err);
 267        return;
 268    }
 269
 270    fdt = drc->fdt;
 271    fdt_offset = drc->fdt_start_offset;
 272    fdt_depth = 0;
 273
 274    do {
 275        const char *name = NULL;
 276        const struct fdt_property *prop = NULL;
 277        int prop_len = 0, name_len = 0;
 278        uint32_t tag;
 279
 280        tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
 281        switch (tag) {
 282        case FDT_BEGIN_NODE:
 283            fdt_depth++;
 284            name = fdt_get_name(fdt, fdt_offset, &name_len);
 285            visit_start_struct(v, NULL, NULL, name, 0, &err);
 286            if (err) {
 287                error_propagate(errp, err);
 288                return;
 289            }
 290            break;
 291        case FDT_END_NODE:
 292            /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
 293            g_assert(fdt_depth > 0);
 294            visit_end_struct(v, &err);
 295            if (err) {
 296                error_propagate(errp, err);
 297                return;
 298            }
 299            fdt_depth--;
 300            break;
 301        case FDT_PROP: {
 302            int i;
 303            prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
 304            name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
 305            visit_start_list(v, name, &err);
 306            if (err) {
 307                error_propagate(errp, err);
 308                return;
 309            }
 310            for (i = 0; i < prop_len; i++) {
 311                visit_type_uint8(v, (uint8_t *)&prop->data[i], NULL, &err);
 312                if (err) {
 313                    error_propagate(errp, err);
 314                    return;
 315                }
 316            }
 317            visit_end_list(v, &err);
 318            if (err) {
 319                error_propagate(errp, err);
 320                return;
 321            }
 322            break;
 323        }
 324        default:
 325            error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
 326        }
 327        fdt_offset = fdt_offset_next;
 328    } while (fdt_depth != 0);
 329}
 330
 331static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
 332                   int fdt_start_offset, bool coldplug, Error **errp)
 333{
 334    DPRINTFN("drc: %x, attach", get_index(drc));
 335
 336    if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
 337        error_setg(errp, "an attached device is still awaiting release");
 338        return;
 339    }
 340    if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
 341        g_assert(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE);
 342    }
 343    g_assert(fdt || coldplug);
 344
 345    /* NOTE: setting initial isolation state to UNISOLATED means we can't
 346     * detach unless guest has a userspace/kernel that moves this state
 347     * back to ISOLATED in response to an unplug event, or this is done
 348     * manually by the admin prior. if we force things while the guest
 349     * may be accessing the device, we can easily crash the guest, so we
 350     * we defer completion of removal in such cases to the reset() hook.
 351     */
 352    if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
 353        drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED;
 354    }
 355    drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE;
 356
 357    drc->dev = d;
 358    drc->fdt = fdt;
 359    drc->fdt_start_offset = fdt_start_offset;
 360    drc->configured = coldplug;
 361
 362    object_property_add_link(OBJECT(drc), "device",
 363                             object_get_typename(OBJECT(drc->dev)),
 364                             (Object **)(&drc->dev),
 365                             NULL, 0, NULL);
 366}
 367
 368static void detach(sPAPRDRConnector *drc, DeviceState *d,
 369                   spapr_drc_detach_cb *detach_cb,
 370                   void *detach_cb_opaque, Error **errp)
 371{
 372    DPRINTFN("drc: %x, detach", get_index(drc));
 373
 374    drc->detach_cb = detach_cb;
 375    drc->detach_cb_opaque = detach_cb_opaque;
 376
 377    if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
 378        DPRINTFN("awaiting transition to isolated state before removal");
 379        drc->awaiting_release = true;
 380        return;
 381    }
 382
 383    if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
 384        drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
 385        DPRINTFN("awaiting transition to unusable state before removal");
 386        drc->awaiting_release = true;
 387        return;
 388    }
 389
 390    drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE;
 391
 392    if (drc->detach_cb) {
 393        drc->detach_cb(drc->dev, drc->detach_cb_opaque);
 394    }
 395
 396    drc->awaiting_release = false;
 397    g_free(drc->fdt);
 398    drc->fdt = NULL;
 399    drc->fdt_start_offset = 0;
 400    object_property_del(OBJECT(drc), "device", NULL);
 401    drc->dev = NULL;
 402    drc->detach_cb = NULL;
 403    drc->detach_cb_opaque = NULL;
 404}
 405
 406static bool release_pending(sPAPRDRConnector *drc)
 407{
 408    return drc->awaiting_release;
 409}
 410
 411static void reset(DeviceState *d)
 412{
 413    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
 414    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 415
 416    DPRINTFN("drc reset: %x", drck->get_index(drc));
 417    /* immediately upon reset we can safely assume DRCs whose devices
 418     * are pending removal can be safely removed, and that they will
 419     * subsequently be left in an ISOLATED state. move the DRC to this
 420     * state in these cases (which will in turn complete any pending
 421     * device removals)
 422     */
 423    if (drc->awaiting_release) {
 424        drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_ISOLATED);
 425        /* generally this should also finalize the removal, but if the device
 426         * hasn't yet been configured we normally defer removal under the
 427         * assumption that this transition is taking place as part of device
 428         * configuration. so check if we're still waiting after this, and
 429         * force removal if we are
 430         */
 431        if (drc->awaiting_release) {
 432            drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
 433                         drc->detach_cb_opaque, NULL);
 434        }
 435
 436        /* non-PCI devices may be awaiting a transition to UNUSABLE */
 437        if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
 438            drc->awaiting_release) {
 439            drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_UNUSABLE);
 440        }
 441    }
 442}
 443
 444static void realize(DeviceState *d, Error **errp)
 445{
 446    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
 447    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 448    Object *root_container;
 449    char link_name[256];
 450    gchar *child_name;
 451    Error *err = NULL;
 452
 453    DPRINTFN("drc realize: %x", drck->get_index(drc));
 454    /* NOTE: we do this as part of realize/unrealize due to the fact
 455     * that the guest will communicate with the DRC via RTAS calls
 456     * referencing the global DRC index. By unlinking the DRC
 457     * from DRC_CONTAINER_PATH/<drc_index> we effectively make it
 458     * inaccessible by the guest, since lookups rely on this path
 459     * existing in the composition tree
 460     */
 461    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
 462    snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc));
 463    child_name = object_get_canonical_path_component(OBJECT(drc));
 464    DPRINTFN("drc child name: %s", child_name);
 465    object_property_add_alias(root_container, link_name,
 466                              drc->owner, child_name, &err);
 467    if (err) {
 468        error_report("%s", error_get_pretty(err));
 469        error_free(err);
 470        object_unref(OBJECT(drc));
 471    }
 472    g_free(child_name);
 473    DPRINTFN("drc realize complete");
 474}
 475
 476static void unrealize(DeviceState *d, Error **errp)
 477{
 478    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
 479    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 480    Object *root_container;
 481    char name[256];
 482    Error *err = NULL;
 483
 484    DPRINTFN("drc unrealize: %x", drck->get_index(drc));
 485    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
 486    snprintf(name, sizeof(name), "%x", drck->get_index(drc));
 487    object_property_del(root_container, name, &err);
 488    if (err) {
 489        error_report("%s", error_get_pretty(err));
 490        error_free(err);
 491        object_unref(OBJECT(drc));
 492    }
 493}
 494
 495sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
 496                                         sPAPRDRConnectorType type,
 497                                         uint32_t id)
 498{
 499    sPAPRDRConnector *drc =
 500        SPAPR_DR_CONNECTOR(object_new(TYPE_SPAPR_DR_CONNECTOR));
 501    char *prop_name;
 502
 503    g_assert(type);
 504
 505    drc->type = type;
 506    drc->id = id;
 507    drc->owner = owner;
 508    prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", get_index(drc));
 509    object_property_add_child(owner, prop_name, OBJECT(drc), NULL);
 510    object_property_set_bool(OBJECT(drc), true, "realized", NULL);
 511    g_free(prop_name);
 512
 513    /* human-readable name for a DRC to encode into the DT
 514     * description. this is mainly only used within a guest in place
 515     * of the unique DRC index.
 516     *
 517     * in the case of VIO/PCI devices, it corresponds to a
 518     * "location code" that maps a logical device/function (DRC index)
 519     * to a physical (or virtual in the case of VIO) location in the
 520     * system by chaining together the "location label" for each
 521     * encapsulating component.
 522     *
 523     * since this is more to do with diagnosing physical hardware
 524     * issues than guest compatibility, we choose location codes/DRC
 525     * names that adhere to the documented format, but avoid encoding
 526     * the entire topology information into the label/code, instead
 527     * just using the location codes based on the labels for the
 528     * endpoints (VIO/PCI adaptor connectors), which is basically
 529     * just "C" followed by an integer ID.
 530     *
 531     * DRC names as documented by PAPR+ v2.7, 13.5.2.4
 532     * location codes as documented by PAPR+ v2.7, 12.3.1.5
 533     */
 534    switch (drc->type) {
 535    case SPAPR_DR_CONNECTOR_TYPE_CPU:
 536        drc->name = g_strdup_printf("CPU %d", id);
 537        break;
 538    case SPAPR_DR_CONNECTOR_TYPE_PHB:
 539        drc->name = g_strdup_printf("PHB %d", id);
 540        break;
 541    case SPAPR_DR_CONNECTOR_TYPE_VIO:
 542    case SPAPR_DR_CONNECTOR_TYPE_PCI:
 543        drc->name = g_strdup_printf("C%d", id);
 544        break;
 545    case SPAPR_DR_CONNECTOR_TYPE_LMB:
 546        drc->name = g_strdup_printf("LMB %d", id);
 547        break;
 548    default:
 549        g_assert(false);
 550    }
 551
 552    /* PCI slot always start in a USABLE state, and stay there */
 553    if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
 554        drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE;
 555    }
 556
 557    return drc;
 558}
 559
 560static void spapr_dr_connector_instance_init(Object *obj)
 561{
 562    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
 563
 564    object_property_add_uint32_ptr(obj, "isolation-state",
 565                                   &drc->isolation_state, NULL);
 566    object_property_add_uint32_ptr(obj, "indicator-state",
 567                                   &drc->indicator_state, NULL);
 568    object_property_add_uint32_ptr(obj, "allocation-state",
 569                                   &drc->allocation_state, NULL);
 570    object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
 571    object_property_add(obj, "index", "uint32", prop_get_index,
 572                        NULL, NULL, NULL, NULL);
 573    object_property_add(obj, "connector_type", "uint32", prop_get_type,
 574                        NULL, NULL, NULL, NULL);
 575    object_property_add_str(obj, "name", prop_get_name, NULL, NULL);
 576    object_property_add(obj, "entity-sense", "uint32", prop_get_entity_sense,
 577                        NULL, NULL, NULL, NULL);
 578    object_property_add(obj, "fdt", "struct", prop_get_fdt,
 579                        NULL, NULL, NULL, NULL);
 580}
 581
 582static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
 583{
 584    DeviceClass *dk = DEVICE_CLASS(k);
 585    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 586
 587    dk->reset = reset;
 588    dk->realize = realize;
 589    dk->unrealize = unrealize;
 590    drck->set_isolation_state = set_isolation_state;
 591    drck->set_indicator_state = set_indicator_state;
 592    drck->set_allocation_state = set_allocation_state;
 593    drck->get_index = get_index;
 594    drck->get_type = get_type;
 595    drck->get_name = get_name;
 596    drck->get_fdt = get_fdt;
 597    drck->set_configured = set_configured;
 598    drck->entity_sense = entity_sense;
 599    drck->attach = attach;
 600    drck->detach = detach;
 601    drck->release_pending = release_pending;
 602    /*
 603     * Reason: it crashes FIXME find and document the real reason
 604     */
 605    dk->cannot_instantiate_with_device_add_yet = true;
 606}
 607
 608static const TypeInfo spapr_dr_connector_info = {
 609    .name          = TYPE_SPAPR_DR_CONNECTOR,
 610    .parent        = TYPE_DEVICE,
 611    .instance_size = sizeof(sPAPRDRConnector),
 612    .instance_init = spapr_dr_connector_instance_init,
 613    .class_size    = sizeof(sPAPRDRConnectorClass),
 614    .class_init    = spapr_dr_connector_class_init,
 615};
 616
 617static void spapr_drc_register_types(void)
 618{
 619    type_register_static(&spapr_dr_connector_info);
 620}
 621
 622type_init(spapr_drc_register_types)
 623
 624/* helper functions for external users */
 625
 626sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index)
 627{
 628    Object *obj;
 629    char name[256];
 630
 631    snprintf(name, sizeof(name), "%s/%x", DRC_CONTAINER_PATH, index);
 632    obj = object_resolve_path(name, NULL);
 633
 634    return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
 635}
 636
 637sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type,
 638                                           uint32_t id)
 639{
 640    return spapr_dr_connector_by_index(
 641            (get_type_shift(type) << DRC_INDEX_TYPE_SHIFT) |
 642            (id & DRC_INDEX_ID_MASK));
 643}
 644
 645/* generate a string the describes the DRC to encode into the
 646 * device tree.
 647 *
 648 * as documented by PAPR+ v2.7, 13.5.2.6 and C.6.1
 649 */
 650static const char *spapr_drc_get_type_str(sPAPRDRConnectorType type)
 651{
 652    switch (type) {
 653    case SPAPR_DR_CONNECTOR_TYPE_CPU:
 654        return "CPU";
 655    case SPAPR_DR_CONNECTOR_TYPE_PHB:
 656        return "PHB";
 657    case SPAPR_DR_CONNECTOR_TYPE_VIO:
 658        return "SLOT";
 659    case SPAPR_DR_CONNECTOR_TYPE_PCI:
 660        return "28";
 661    case SPAPR_DR_CONNECTOR_TYPE_LMB:
 662        return "MEM";
 663    default:
 664        g_assert(false);
 665    }
 666
 667    return NULL;
 668}
 669
 670/**
 671 * spapr_drc_populate_dt
 672 *
 673 * @fdt: libfdt device tree
 674 * @path: path in the DT to generate properties
 675 * @owner: parent Object/DeviceState for which to generate DRC
 676 *         descriptions for
 677 * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding
 678 *   to the types of DRCs to generate entries for
 679 *
 680 * generate OF properties to describe DRC topology/indices to guests
 681 *
 682 * as documented in PAPR+ v2.1, 13.5.2
 683 */
 684int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
 685                          uint32_t drc_type_mask)
 686{
 687    Object *root_container;
 688    ObjectProperty *prop;
 689    ObjectPropertyIterator *iter;
 690    uint32_t drc_count = 0;
 691    GArray *drc_indexes, *drc_power_domains;
 692    GString *drc_names, *drc_types;
 693    int ret;
 694
 695    /* the first entry of each properties is a 32-bit integer encoding
 696     * the number of elements in the array. we won't know this until
 697     * we complete the iteration through all the matching DRCs, but
 698     * reserve the space now and set the offsets accordingly so we
 699     * can fill them in later.
 700     */
 701    drc_indexes = g_array_new(false, true, sizeof(uint32_t));
 702    drc_indexes = g_array_set_size(drc_indexes, 1);
 703    drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
 704    drc_power_domains = g_array_set_size(drc_power_domains, 1);
 705    drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
 706    drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
 707
 708    /* aliases for all DRConnector objects will be rooted in QOM
 709     * composition tree at DRC_CONTAINER_PATH
 710     */
 711    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
 712
 713    iter = object_property_iter_init(root_container);
 714    while ((prop = object_property_iter_next(iter))) {
 715        Object *obj;
 716        sPAPRDRConnector *drc;
 717        sPAPRDRConnectorClass *drck;
 718        uint32_t drc_index, drc_power_domain;
 719
 720        if (!strstart(prop->type, "link<", NULL)) {
 721            continue;
 722        }
 723
 724        obj = object_property_get_link(root_container, prop->name, NULL);
 725        drc = SPAPR_DR_CONNECTOR(obj);
 726        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 727
 728        if (owner && (drc->owner != owner)) {
 729            continue;
 730        }
 731
 732        if ((drc->type & drc_type_mask) == 0) {
 733            continue;
 734        }
 735
 736        drc_count++;
 737
 738        /* ibm,drc-indexes */
 739        drc_index = cpu_to_be32(drck->get_index(drc));
 740        g_array_append_val(drc_indexes, drc_index);
 741
 742        /* ibm,drc-power-domains */
 743        drc_power_domain = cpu_to_be32(-1);
 744        g_array_append_val(drc_power_domains, drc_power_domain);
 745
 746        /* ibm,drc-names */
 747        drc_names = g_string_append(drc_names, drck->get_name(drc));
 748        drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
 749
 750        /* ibm,drc-types */
 751        drc_types = g_string_append(drc_types,
 752                                    spapr_drc_get_type_str(drc->type));
 753        drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
 754    }
 755    object_property_iter_free(iter);
 756
 757    /* now write the drc count into the space we reserved at the
 758     * beginning of the arrays previously
 759     */
 760    *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count);
 761    *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count);
 762    *(uint32_t *)drc_names->str = cpu_to_be32(drc_count);
 763    *(uint32_t *)drc_types->str = cpu_to_be32(drc_count);
 764
 765    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes",
 766                      drc_indexes->data,
 767                      drc_indexes->len * sizeof(uint32_t));
 768    if (ret) {
 769        fprintf(stderr, "Couldn't create ibm,drc-indexes property\n");
 770        goto out;
 771    }
 772
 773    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains",
 774                      drc_power_domains->data,
 775                      drc_power_domains->len * sizeof(uint32_t));
 776    if (ret) {
 777        fprintf(stderr, "Couldn't finalize ibm,drc-power-domains property\n");
 778        goto out;
 779    }
 780
 781    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
 782                      drc_names->str, drc_names->len);
 783    if (ret) {
 784        fprintf(stderr, "Couldn't finalize ibm,drc-names property\n");
 785        goto out;
 786    }
 787
 788    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
 789                      drc_types->str, drc_types->len);
 790    if (ret) {
 791        fprintf(stderr, "Couldn't finalize ibm,drc-types property\n");
 792        goto out;
 793    }
 794
 795out:
 796    g_array_free(drc_indexes, true);
 797    g_array_free(drc_power_domains, true);
 798    g_string_free(drc_names, true);
 799    g_string_free(drc_types, true);
 800
 801    return ret;
 802}
 803