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