spapr_drc.c 36.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * QEMU SPAPR Dynamic Reconfiguration Connector Implementation
 *
 * Copyright IBM Corp. 2014
 *
 * Authors:
 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

P
Peter Maydell 已提交
13
#include "qemu/osdep.h"
14
#include "qapi/error.h"
15
#include "cpu.h"
16
#include "qemu/cutils.h"
17 18 19 20 21
#include "hw/ppc/spapr_drc.h"
#include "qom/object.h"
#include "hw/qdev.h"
#include "qapi/visitor.h"
#include "qemu/error-report.h"
22
#include "hw/ppc/spapr.h" /* for RTAS return codes */
23
#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
24
#include "trace.h"
25 26 27

#define DRC_CONTAINER_PATH "/dr-connector"
#define DRC_INDEX_TYPE_SHIFT 28
28
#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
29

D
David Gibson 已提交
30 31 32 33 34 35 36
sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    return 1 << drck->typeshift;
}

37
uint32_t spapr_drc_index(sPAPRDRConnector *drc)
38
{
D
David Gibson 已提交
39 40
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

41 42 43 44
    /* no set format for a drc index: it only needs to be globally
     * unique. this is how we encode the DRC type on bare-metal
     * however, so might as well do that here
     */
D
David Gibson 已提交
45 46
    return (drck->typeshift << DRC_INDEX_TYPE_SHIFT)
        | (drc->id & DRC_INDEX_ID_MASK);
47 48
}

49
static uint32_t drc_isolate_physical(sPAPRDRConnector *drc)
50
{
51 52 53 54 55 56 57 58 59 60 61 62
    switch (drc->state) {
    case SPAPR_DRC_STATE_PHYSICAL_POWERON:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
        break; /* see below */
    case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
        return RTAS_OUT_PARAM_ERROR; /* not allowed */
    default:
        g_assert_not_reached();
    }

    drc->state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
63

64
    if (drc->unplug_requested) {
65
        uint32_t drc_index = spapr_drc_index(drc);
66 67
        trace_spapr_drc_set_isolation_state_finalizing(drc_index);
        spapr_drc_detach(drc);
68
    }
69 70 71 72 73 74

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_unisolate_physical(sPAPRDRConnector *drc)
{
75 76 77 78 79 80 81 82 83 84
    switch (drc->state) {
    case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
    case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_PHYSICAL_POWERON:
        break; /* see below */
    default:
        g_assert_not_reached();
    }

85 86 87 88 89 90 91 92
    /* cannot unisolate a non-existent resource, and, or resources
     * which are in an 'UNUSABLE' allocation state. (PAPR 2.7,
     * 13.5.3.5)
     */
    if (!drc->dev) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }

93
    drc->state = SPAPR_DRC_STATE_PHYSICAL_UNISOLATE;
94 95
    drc->ccs_offset = drc->fdt_start_offset;
    drc->ccs_depth = 0;
96 97 98 99 100 101

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
{
102 103 104 105 106 107 108 109 110 111 112 113
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
        return RTAS_OUT_PARAM_ERROR; /* not allowed */
    default:
        g_assert_not_reached();
    }

B
Bharata B Rao 已提交
114 115 116 117 118 119 120 121 122 123
    /*
     * Fail any requests to ISOLATE the LMB DRC if this LMB doesn't
     * belong to a DIMM device that is marked for removal.
     *
     * Currently the guest userspace tool drmgr that drives the memory
     * hotplug/unplug will just try to remove a set of 'removable' LMBs
     * in response to a hot unplug request that is based on drc-count.
     * If the LMB being removed doesn't belong to a DIMM device that is
     * actually being unplugged, fail the isolation request here.
     */
124
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
125
        && !drc->unplug_requested) {
126
        return RTAS_OUT_HW_ERROR;
B
Bharata B Rao 已提交
127 128
    }

129
    drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
130

131 132 133 134 135 136 137 138
    /* if we're awaiting release, but still in an unconfigured state,
     * it's likely the guest is still in the process of configuring
     * the device and is transitioning the devices to an ISOLATED
     * state as a part of that process. so we only complete the
     * removal when this transition happens for a device in a
     * configured state, as suggested by the state diagram from PAPR+
     * 2.7, 13.4
     */
139
    if (drc->unplug_requested) {
140
        uint32_t drc_index = spapr_drc_index(drc);
141 142
        trace_spapr_drc_set_isolation_state_finalizing(drc_index);
        spapr_drc_detach(drc);
143
    }
144 145 146 147 148
    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_unisolate_logical(sPAPRDRConnector *drc)
{
149 150 151 152 153 154 155 156 157 158
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
    default:
        g_assert_not_reached();
159 160
    }

161 162
    /* Move to AVAILABLE state should have ensured device was present */
    g_assert(drc->dev);
163

164
    drc->state = SPAPR_DRC_STATE_LOGICAL_UNISOLATE;
165 166 167
    drc->ccs_offset = drc->fdt_start_offset;
    drc->ccs_depth = 0;

168
    return RTAS_OUT_SUCCESS;
169 170
}

171
static uint32_t drc_set_usable(sPAPRDRConnector *drc)
172
{
173 174 175 176 177 178 179 180 181 182 183
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        break; /* see below */
    default:
        g_assert_not_reached();
    }

184 185 186 187 188 189 190 191
    /* if there's no resource/device associated with the DRC, there's
     * no way for us to put it in an allocation state consistent with
     * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should
     * result in an RTAS return code of -3 / "no such indicator"
     */
    if (!drc->dev) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }
192
    if (drc->unplug_requested) {
193 194
        /* Don't allow the guest to move a device away from UNUSABLE
         * state when we want to unplug it */
195
        return RTAS_OUT_NO_SUCH_INDICATOR;
196 197
    }

198
    drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
199 200 201 202 203 204

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
{
205 206 207 208 209 210 211 212 213 214 215 216 217
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
    default:
        g_assert_not_reached();
    }

    drc->state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
218
    if (drc->unplug_requested) {
219 220
        uint32_t drc_index = spapr_drc_index(drc);
        trace_spapr_drc_set_allocation_state_finalizing(drc_index);
221
        spapr_drc_detach(drc);
222
    }
223

224
    return RTAS_OUT_SUCCESS;
225 226
}

D
David Gibson 已提交
227
static const char *spapr_drc_name(sPAPRDRConnector *drc)
228
{
D
David Gibson 已提交
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    /* human-readable name for a DRC to encode into the DT
     * description. this is mainly only used within a guest in place
     * of the unique DRC index.
     *
     * in the case of VIO/PCI devices, it corresponds to a "location
     * code" that maps a logical device/function (DRC index) to a
     * physical (or virtual in the case of VIO) location in the system
     * by chaining together the "location label" for each
     * encapsulating component.
     *
     * since this is more to do with diagnosing physical hardware
     * issues than guest compatibility, we choose location codes/DRC
     * names that adhere to the documented format, but avoid encoding
     * the entire topology information into the label/code, instead
     * just using the location codes based on the labels for the
     * endpoints (VIO/PCI adaptor connectors), which is basically just
     * "C" followed by an integer ID.
     *
     * DRC names as documented by PAPR+ v2.7, 13.5.2.4
     * location codes as documented by PAPR+ v2.7, 12.3.1.5
     */
    return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id);
253 254 255 256 257 258 259 260 261
}

/*
 * dr-entity-sense sensor value
 * returned via get-sensor-state RTAS calls
 * as expected by state diagram in PAPR+ 2.7, 13.4
 * based on the current allocation/indicator/power states
 * for the DR connector.
 */
262
static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc)
263
{
264 265 266 267 268 269 270 271 272 273 274
    /* this assumes all PCI devices are assigned to a 'live insertion'
     * power domain, where QEMU manages power state automatically as
     * opposed to the guest. present, non-PCI resources are unaffected
     * by power state.
     */
    return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT
        : SPAPR_DR_ENTITY_SENSE_EMPTY;
}

static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc)
{
275 276
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
277
        return SPAPR_DR_ENTITY_SENSE_UNUSABLE;
278 279 280 281 282 283 284
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        g_assert(drc->dev);
        return SPAPR_DR_ENTITY_SENSE_PRESENT;
    default:
        g_assert_not_reached();
285 286 287
    }
}

288 289
static void prop_get_index(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
290 291
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
292
    uint32_t value = spapr_drc_index(drc);
293
    visit_type_uint32(v, name, &value, errp);
294 295
}

296 297
static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
298 299
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
300
    QNull *null = NULL;
301
    Error *err = NULL;
302 303 304 305
    int fdt_offset_next, fdt_offset, fdt_depth;
    void *fdt;

    if (!drc->fdt) {
306 307
        visit_type_null(v, NULL, &null, errp);
        QDECREF(null);
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
        return;
    }

    fdt = drc->fdt;
    fdt_offset = drc->fdt_start_offset;
    fdt_depth = 0;

    do {
        const char *name = NULL;
        const struct fdt_property *prop = NULL;
        int prop_len = 0, name_len = 0;
        uint32_t tag;

        tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
        switch (tag) {
        case FDT_BEGIN_NODE:
            fdt_depth++;
            name = fdt_get_name(fdt, fdt_offset, &name_len);
326
            visit_start_struct(v, name, NULL, 0, &err);
327 328 329 330
            if (err) {
                error_propagate(errp, err);
                return;
            }
331 332 333 334
            break;
        case FDT_END_NODE:
            /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
            g_assert(fdt_depth > 0);
335
            visit_check_struct(v, &err);
E
Eric Blake 已提交
336
            visit_end_struct(v, NULL);
337 338 339 340
            if (err) {
                error_propagate(errp, err);
                return;
            }
341 342 343 344 345 346
            fdt_depth--;
            break;
        case FDT_PROP: {
            int i;
            prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
            name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
347
            visit_start_list(v, name, NULL, 0, &err);
348 349 350 351
            if (err) {
                error_propagate(errp, err);
                return;
            }
352
            for (i = 0; i < prop_len; i++) {
353
                visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err);
354 355 356 357 358
                if (err) {
                    error_propagate(errp, err);
                    return;
                }
            }
359
            visit_check_list(v, &err);
E
Eric Blake 已提交
360
            visit_end_list(v, NULL);
361 362 363 364
            if (err) {
                error_propagate(errp, err);
                return;
            }
365 366 367 368 369 370 371 372 373
            break;
        }
        default:
            error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
        }
        fdt_offset = fdt_offset_next;
    } while (fdt_depth != 0);
}

374
void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
375
                      int fdt_start_offset, Error **errp)
376
{
377
    trace_spapr_drc_attach(spapr_drc_index(drc));
378

379
    if (drc->dev) {
380 381 382
        error_setg(errp, "an attached device is still awaiting release");
        return;
    }
383 384
    g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
             || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
385
    g_assert(fdt);
386 387 388 389 390 391 392 393 394 395 396

    drc->dev = d;
    drc->fdt = fdt;
    drc->fdt_start_offset = fdt_start_offset;

    object_property_add_link(OBJECT(drc), "device",
                             object_get_typename(OBJECT(drc->dev)),
                             (Object **)(&drc->dev),
                             NULL, 0, NULL);
}

397
static void spapr_drc_release(sPAPRDRConnector *drc)
398
{
D
David Gibson 已提交
399 400 401
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    drck->release(drc->dev);
402

403
    drc->unplug_requested = false;
404 405 406
    g_free(drc->fdt);
    drc->fdt = NULL;
    drc->fdt_start_offset = 0;
407
    object_property_del(OBJECT(drc), "device", &error_abort);
408 409 410
    drc->dev = NULL;
}

411
void spapr_drc_detach(sPAPRDRConnector *drc)
412
{
413 414
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

415 416
    trace_spapr_drc_detach(spapr_drc_index(drc));

417
    g_assert(drc->dev);
418

419
    drc->unplug_requested = true;
420

421 422
    if (drc->state != drck->empty_state) {
        trace_spapr_drc_awaiting_quiesce(spapr_drc_index(drc));
423 424 425 426 427 428
        return;
    }

    spapr_drc_release(drc);
}

429
void spapr_drc_reset(sPAPRDRConnector *drc)
430
{
431 432
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

433
    trace_spapr_drc_reset(spapr_drc_index(drc));
434

435
    /* immediately upon reset we can safely assume DRCs whose devices
436
     * are pending removal can be safely removed.
437
     */
438
    if (drc->unplug_requested) {
439 440 441 442
        spapr_drc_release(drc);
    }

    if (drc->dev) {
443 444
        /* A device present at reset is ready to go, same as coldplugged */
        drc->state = drck->ready_state;
445
    } else {
446
        drc->state = drck->empty_state;
447
    }
448 449 450

    drc->ccs_offset = -1;
    drc->ccs_depth = -1;
451 452
}

453 454 455 456 457
static void drc_reset(void *opaque)
{
    spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque));
}

458 459 460 461
static bool spapr_drc_needed(void *opaque)
{
    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
462
    sPAPRDREntitySense value = drck->dr_entity_sense(drc);
463 464 465 466 467 468 469

    /* If no dev is plugged in there is no need to migrate the DRC state */
    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
        return false;
    }

    /*
470 471 472 473
     * We need to migrate the state if it's not equal to the expected
     * long-term state, which is the same as the coldplugged initial
     * state */
    return (drc->state != drck->ready_state);
474 475 476 477 478 479 480 481
}

static const VMStateDescription vmstate_spapr_drc = {
    .name = "spapr_drc",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = spapr_drc_needed,
    .fields  = (VMStateField []) {
482
        VMSTATE_UINT32(state, sPAPRDRConnector),
483 484 485 486
        VMSTATE_END_OF_LIST()
    }
};

487 488 489 490 491 492 493 494
static void realize(DeviceState *d, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
    Object *root_container;
    char link_name[256];
    gchar *child_name;
    Error *err = NULL;

495
    trace_spapr_drc_realize(spapr_drc_index(drc));
496 497 498 499 500 501 502 503
    /* NOTE: we do this as part of realize/unrealize due to the fact
     * that the guest will communicate with the DRC via RTAS calls
     * referencing the global DRC index. By unlinking the DRC
     * from DRC_CONTAINER_PATH/<drc_index> we effectively make it
     * inaccessible by the guest, since lookups rely on this path
     * existing in the composition tree
     */
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
504
    snprintf(link_name, sizeof(link_name), "%x", spapr_drc_index(drc));
505
    child_name = object_get_canonical_path_component(OBJECT(drc));
506
    trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
507 508
    object_property_add_alias(root_container, link_name,
                              drc->owner, child_name, &err);
G
Greg Kurz 已提交
509
    g_free(child_name);
510
    if (err) {
G
Greg Kurz 已提交
511 512
        error_propagate(errp, err);
        return;
513
    }
514
    vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
515
                     drc);
D
David Gibson 已提交
516
    qemu_register_reset(drc_reset, drc);
517
    trace_spapr_drc_realize_complete(spapr_drc_index(drc));
518 519 520 521 522 523 524 525
}

static void unrealize(DeviceState *d, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
    Object *root_container;
    char name[256];

526
    trace_spapr_drc_unrealize(spapr_drc_index(drc));
G
Greg Kurz 已提交
527 528
    qemu_unregister_reset(drc_reset, drc);
    vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
529
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
530
    snprintf(name, sizeof(name), "%x", spapr_drc_index(drc));
G
Greg Kurz 已提交
531
    object_property_del(root_container, name, errp);
532 533
}

D
David Gibson 已提交
534
sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
535 536
                                         uint32_t id)
{
D
David Gibson 已提交
537
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
538
    char *prop_name;
539 540 541

    drc->id = id;
    drc->owner = owner;
542 543
    prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
                                spapr_drc_index(drc));
544
    object_property_add_child(owner, prop_name, OBJECT(drc), NULL);
545
    object_property_set_bool(OBJECT(drc), true, "realized", NULL);
546
    g_free(prop_name);
547 548 549 550 551 552 553

    return drc;
}

static void spapr_dr_connector_instance_init(Object *obj)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
554
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
555 556 557 558 559 560

    object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
    object_property_add(obj, "index", "uint32", prop_get_index,
                        NULL, NULL, NULL, NULL);
    object_property_add(obj, "fdt", "struct", prop_get_fdt,
                        NULL, NULL, NULL, NULL);
561
    drc->state = drck->empty_state;
562 563 564 565 566 567 568 569
}

static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
{
    DeviceClass *dk = DEVICE_CLASS(k);

    dk->realize = realize;
    dk->unrealize = unrealize;
570 571 572
    /*
     * Reason: it crashes FIXME find and document the real reason
     */
573
    dk->user_creatable = false;
574 575
}

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
static bool drc_physical_needed(void *opaque)
{
    sPAPRDRCPhysical *drcp = (sPAPRDRCPhysical *)opaque;
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(drcp);

    if ((drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_ACTIVE))
        || (!drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_INACTIVE))) {
        return false;
    }
    return true;
}

static const VMStateDescription vmstate_spapr_drc_physical = {
    .name = "spapr_drc/physical",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = drc_physical_needed,
    .fields  = (VMStateField []) {
        VMSTATE_UINT32(dr_indicator, sPAPRDRCPhysical),
        VMSTATE_END_OF_LIST()
    }
};

static void drc_physical_reset(void *opaque)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(opaque);
    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(drc);

    if (drc->dev) {
        drcp->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE;
    } else {
        drcp->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE;
    }
}

static void realize_physical(DeviceState *d, Error **errp)
{
    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
    Error *local_err = NULL;

    realize(d, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    vmstate_register(DEVICE(drcp), spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)),
                     &vmstate_spapr_drc_physical, drcp);
    qemu_register_reset(drc_physical_reset, drcp);
}

627 628
static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
{
629
    DeviceClass *dk = DEVICE_CLASS(k);
630 631
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

632
    dk->realize = realize_physical;
633
    drck->dr_entity_sense = physical_entity_sense;
634 635
    drck->isolate = drc_isolate_physical;
    drck->unisolate = drc_unisolate_physical;
636 637
    drck->ready_state = SPAPR_DRC_STATE_PHYSICAL_CONFIGURED;
    drck->empty_state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
638 639 640 641 642 643 644
}

static void spapr_drc_logical_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->dr_entity_sense = logical_entity_sense;
645 646
    drck->isolate = drc_isolate_logical;
    drck->unisolate = drc_unisolate_logical;
647 648
    drck->ready_state = SPAPR_DRC_STATE_LOGICAL_CONFIGURED;
    drck->empty_state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
649 650
}

D
David Gibson 已提交
651 652 653 654 655
static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
656
    drck->typename = "CPU";
D
David Gibson 已提交
657
    drck->drc_name_prefix = "CPU ";
D
David Gibson 已提交
658
    drck->release = spapr_core_release;
D
David Gibson 已提交
659 660 661 662 663 664 665
}

static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
666
    drck->typename = "28";
D
David Gibson 已提交
667
    drck->drc_name_prefix = "C";
D
David Gibson 已提交
668
    drck->release = spapr_phb_remove_pci_device_cb;
D
David Gibson 已提交
669 670 671 672 673 674 675
}

static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
676
    drck->typename = "MEM";
D
David Gibson 已提交
677
    drck->drc_name_prefix = "LMB ";
D
David Gibson 已提交
678
    drck->release = spapr_lmb_release;
D
David Gibson 已提交
679 680
}

681 682 683 684 685 686 687
static const TypeInfo spapr_dr_connector_info = {
    .name          = TYPE_SPAPR_DR_CONNECTOR,
    .parent        = TYPE_DEVICE,
    .instance_size = sizeof(sPAPRDRConnector),
    .instance_init = spapr_dr_connector_instance_init,
    .class_size    = sizeof(sPAPRDRConnectorClass),
    .class_init    = spapr_dr_connector_class_init,
D
David Gibson 已提交
688 689 690 691 692 693
    .abstract      = true,
};

static const TypeInfo spapr_drc_physical_info = {
    .name          = TYPE_SPAPR_DRC_PHYSICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
694
    .instance_size = sizeof(sPAPRDRCPhysical),
695
    .class_init    = spapr_drc_physical_class_init,
D
David Gibson 已提交
696 697 698 699 700 701
    .abstract      = true,
};

static const TypeInfo spapr_drc_logical_info = {
    .name          = TYPE_SPAPR_DRC_LOGICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
702
    .class_init    = spapr_drc_logical_class_init,
D
David Gibson 已提交
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
    .abstract      = true,
};

static const TypeInfo spapr_drc_cpu_info = {
    .name          = TYPE_SPAPR_DRC_CPU,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .class_init    = spapr_drc_cpu_class_init,
};

static const TypeInfo spapr_drc_pci_info = {
    .name          = TYPE_SPAPR_DRC_PCI,
    .parent        = TYPE_SPAPR_DRC_PHYSICAL,
    .class_init    = spapr_drc_pci_class_init,
};

static const TypeInfo spapr_drc_lmb_info = {
    .name          = TYPE_SPAPR_DRC_LMB,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .class_init    = spapr_drc_lmb_class_init,
722 723 724 725
};

/* helper functions for external users */

726
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
727 728 729 730 731 732 733 734 735 736
{
    Object *obj;
    char name[256];

    snprintf(name, sizeof(name), "%s/%x", DRC_CONTAINER_PATH, index);
    obj = object_resolve_path(name, NULL);

    return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
}

737
sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
738
{
739 740 741 742 743
    sPAPRDRConnectorClass *drck
        = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));

    return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
                              | (id & DRC_INDEX_ID_MASK));
744
}
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764

/**
 * spapr_drc_populate_dt
 *
 * @fdt: libfdt device tree
 * @path: path in the DT to generate properties
 * @owner: parent Object/DeviceState for which to generate DRC
 *         descriptions for
 * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding
 *   to the types of DRCs to generate entries for
 *
 * generate OF properties to describe DRC topology/indices to guests
 *
 * as documented in PAPR+ v2.1, 13.5.2
 */
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
                          uint32_t drc_type_mask)
{
    Object *root_container;
    ObjectProperty *prop;
765
    ObjectPropertyIterator iter;
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
    uint32_t drc_count = 0;
    GArray *drc_indexes, *drc_power_domains;
    GString *drc_names, *drc_types;
    int ret;

    /* the first entry of each properties is a 32-bit integer encoding
     * the number of elements in the array. we won't know this until
     * we complete the iteration through all the matching DRCs, but
     * reserve the space now and set the offsets accordingly so we
     * can fill them in later.
     */
    drc_indexes = g_array_new(false, true, sizeof(uint32_t));
    drc_indexes = g_array_set_size(drc_indexes, 1);
    drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
    drc_power_domains = g_array_set_size(drc_power_domains, 1);
    drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
    drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));

    /* aliases for all DRConnector objects will be rooted in QOM
     * composition tree at DRC_CONTAINER_PATH
     */
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);

789 790
    object_property_iter_init(&iter, root_container);
    while ((prop = object_property_iter_next(&iter))) {
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
        Object *obj;
        sPAPRDRConnector *drc;
        sPAPRDRConnectorClass *drck;
        uint32_t drc_index, drc_power_domain;

        if (!strstart(prop->type, "link<", NULL)) {
            continue;
        }

        obj = object_property_get_link(root_container, prop->name, NULL);
        drc = SPAPR_DR_CONNECTOR(obj);
        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

        if (owner && (drc->owner != owner)) {
            continue;
        }

D
David Gibson 已提交
808
        if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
809 810 811 812 813 814
            continue;
        }

        drc_count++;

        /* ibm,drc-indexes */
815
        drc_index = cpu_to_be32(spapr_drc_index(drc));
816 817 818 819 820 821 822
        g_array_append_val(drc_indexes, drc_index);

        /* ibm,drc-power-domains */
        drc_power_domain = cpu_to_be32(-1);
        g_array_append_val(drc_power_domains, drc_power_domain);

        /* ibm,drc-names */
D
David Gibson 已提交
823
        drc_names = g_string_append(drc_names, spapr_drc_name(drc));
824 825 826
        drc_names = g_string_insert_len(drc_names, -1, "\0", 1);

        /* ibm,drc-types */
827
        drc_types = g_string_append(drc_types, drck->typename);
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
        drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
    }

    /* now write the drc count into the space we reserved at the
     * beginning of the arrays previously
     */
    *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count);
    *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count);
    *(uint32_t *)drc_names->str = cpu_to_be32(drc_count);
    *(uint32_t *)drc_types->str = cpu_to_be32(drc_count);

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes",
                      drc_indexes->data,
                      drc_indexes->len * sizeof(uint32_t));
    if (ret) {
843
        error_report("Couldn't create ibm,drc-indexes property");
844 845 846 847 848 849 850
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains",
                      drc_power_domains->data,
                      drc_power_domains->len * sizeof(uint32_t));
    if (ret) {
851
        error_report("Couldn't finalize ibm,drc-power-domains property");
852 853 854 855 856 857
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
                      drc_names->str, drc_names->len);
    if (ret) {
858
        error_report("Couldn't finalize ibm,drc-names property");
859 860 861 862 863 864
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
                      drc_types->str, drc_types->len);
    if (ret) {
865
        error_report("Couldn't finalize ibm,drc-types property");
866 867 868 869 870 871 872 873 874 875 876
        goto out;
    }

out:
    g_array_free(drc_indexes, true);
    g_array_free(drc_power_domains, true);
    g_string_free(drc_names, true);
    g_string_free(drc_types, true);

    return ret;
}
877 878 879 880 881

/*
 * RTAS calls
 */

882
static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)
883
{
884 885 886 887
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
    sPAPRDRConnectorClass *drck;

    if (!drc) {
888
        return RTAS_OUT_NO_SUCH_INDICATOR;
889 890
    }

891 892
    trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);

893
    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
894 895 896 897 898 899 900 901 902 903 904

    switch (state) {
    case SPAPR_DR_ISOLATION_STATE_ISOLATED:
        return drck->isolate(drc);

    case SPAPR_DR_ISOLATION_STATE_UNISOLATED:
        return drck->unisolate(drc);

    default:
        return RTAS_OUT_PARAM_ERROR;
    }
905 906
}

907
static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state)
908
{
909
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
910

911 912
    if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_LOGICAL)) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
913 914
    }

915 916 917 918 919 920 921 922 923 924 925 926
    trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);

    switch (state) {
    case SPAPR_DR_ALLOCATION_STATE_USABLE:
        return drc_set_usable(drc);

    case SPAPR_DR_ALLOCATION_STATE_UNUSABLE:
        return drc_set_unusable(drc);

    default:
        return RTAS_OUT_PARAM_ERROR;
    }
927
}
928

929
static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state)
930 931
{
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
932

933 934 935 936 937 938 939 940
    if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_PHYSICAL)) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }
    if ((state != SPAPR_DR_INDICATOR_INACTIVE)
        && (state != SPAPR_DR_INDICATOR_ACTIVE)
        && (state != SPAPR_DR_INDICATOR_IDENTIFY)
        && (state != SPAPR_DR_INDICATOR_ACTION)) {
        return RTAS_OUT_PARAM_ERROR; /* bad state parameter */
941 942
    }

943
    trace_spapr_drc_set_dr_indicator(idx, state);
944
    SPAPR_DRC_PHYSICAL(drc)->dr_indicator = state;
945
    return RTAS_OUT_SUCCESS;
946 947 948 949 950 951 952 953 954 955 956
}

static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                               uint32_t token,
                               uint32_t nargs, target_ulong args,
                               uint32_t nret, target_ulong rets)
{
    uint32_t type, idx, state;
    uint32_t ret = RTAS_OUT_SUCCESS;

    if (nargs != 3 || nret != 1) {
957 958 959 960
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

961 962 963 964 965
    type = rtas_ld(args, 0);
    idx = rtas_ld(args, 1);
    state = rtas_ld(args, 2);

    switch (type) {
966
    case RTAS_SENSOR_TYPE_ISOLATION_STATE:
967
        ret = rtas_set_isolation_state(idx, state);
968 969
        break;
    case RTAS_SENSOR_TYPE_DR:
970
        ret = rtas_set_dr_indicator(idx, state);
971 972
        break;
    case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
973
        ret = rtas_set_allocation_state(idx, state);
974 975
        break;
    default:
976
        ret = RTAS_OUT_NOT_SUPPORTED;
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
    }

out:
    rtas_st(rets, 0, ret);
}

static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args, uint32_t nret,
                                  target_ulong rets)
{
    uint32_t sensor_type;
    uint32_t sensor_index;
    uint32_t sensor_state = 0;
    sPAPRDRConnector *drc;
    sPAPRDRConnectorClass *drck;
    uint32_t ret = RTAS_OUT_SUCCESS;

    if (nargs != 2 || nret != 2) {
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

    sensor_type = rtas_ld(args, 0);
    sensor_index = rtas_ld(args, 1);

    if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
        /* currently only DR-related sensors are implemented */
        trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
                                                        sensor_type);
        ret = RTAS_OUT_NOT_SUPPORTED;
        goto out;
    }

1011
    drc = spapr_drc_by_index(sensor_index);
1012 1013 1014 1015 1016 1017
    if (!drc) {
        trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }
    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
1018
    sensor_state = drck->dr_entity_sense(drc);
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053

out:
    rtas_st(rets, 0, ret);
    rtas_st(rets, 1, sensor_state);
}

/* configure-connector work area offsets, int32_t units for field
 * indexes, bytes for field offset/len values.
 *
 * as documented by PAPR+ v2.7, 13.5.3.5
 */
#define CC_IDX_NODE_NAME_OFFSET 2
#define CC_IDX_PROP_NAME_OFFSET 2
#define CC_IDX_PROP_LEN 3
#define CC_IDX_PROP_DATA_OFFSET 4
#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
#define CC_WA_LEN 4096

static void configure_connector_st(target_ulong addr, target_ulong offset,
                                   const void *buf, size_t len)
{
    cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
                              buf, MIN(len, CC_WA_LEN - offset));
}

static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
                                         sPAPRMachineState *spapr,
                                         uint32_t token, uint32_t nargs,
                                         target_ulong args, uint32_t nret,
                                         target_ulong rets)
{
    uint64_t wa_addr;
    uint64_t wa_offset;
    uint32_t drc_index;
    sPAPRDRConnector *drc;
1054
    sPAPRDRConnectorClass *drck;
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
    sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
    int rc;

    if (nargs != 2 || nret != 1) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);

    drc_index = rtas_ld(wa_addr, 0);
1066
    drc = spapr_drc_by_index(drc_index);
1067 1068 1069 1070 1071 1072
    if (!drc) {
        trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
        rc = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

1073 1074 1075
    if ((drc->state != SPAPR_DRC_STATE_LOGICAL_UNISOLATE)
        && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)) {
        /* Need to unisolate the device before configuring */
1076 1077 1078 1079
        rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
        goto out;
    }

1080 1081 1082 1083
    g_assert(drc->fdt);

    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

1084 1085 1086 1087 1088 1089
    do {
        uint32_t tag;
        const char *name;
        const struct fdt_property *prop;
        int fdt_offset_next, prop_len;

1090
        tag = fdt_next_tag(drc->fdt, drc->ccs_offset, &fdt_offset_next);
1091 1092 1093

        switch (tag) {
        case FDT_BEGIN_NODE:
1094 1095
            drc->ccs_depth++;
            name = fdt_get_name(drc->fdt, drc->ccs_offset, NULL);
1096 1097 1098 1099 1100 1101 1102 1103

            /* provide the name of the next OF node */
            wa_offset = CC_VAL_DATA_OFFSET;
            rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
            resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
            break;
        case FDT_END_NODE:
1104 1105
            drc->ccs_depth--;
            if (drc->ccs_depth == 0) {
1106
                uint32_t drc_index = spapr_drc_index(drc);
1107 1108

                /* done sending the device tree, move to configured state */
1109
                trace_spapr_drc_set_configured(drc_index);
1110
                drc->state = drck->ready_state;
1111 1112
                drc->ccs_offset = -1;
                drc->ccs_depth = -1;
1113 1114 1115 1116 1117 1118
                resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
            } else {
                resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
            }
            break;
        case FDT_PROP:
1119
            prop = fdt_get_property_by_offset(drc->fdt, drc->ccs_offset,
1120
                                              &prop_len);
D
David Gibson 已提交
1121
            name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143

            /* provide the name of the next OF property */
            wa_offset = CC_VAL_DATA_OFFSET;
            rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);

            /* provide the length and value of the OF property. data gets
             * placed immediately after NULL terminator of the OF property's
             * name string
             */
            wa_offset += strlen(name) + 1,
            rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
            rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
            resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
            break;
        case FDT_END:
            resp = SPAPR_DR_CC_RESPONSE_ERROR;
        default:
            /* keep seeking for an actionable tag */
            break;
        }
1144 1145
        if (drc->ccs_offset >= 0) {
            drc->ccs_offset = fdt_offset_next;
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
        }
    } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);

    rc = resp;
out:
    rtas_st(rets, 0, rc);
}

static void spapr_drc_register_types(void)
{
    type_register_static(&spapr_dr_connector_info);
D
David Gibson 已提交
1157 1158 1159 1160 1161
    type_register_static(&spapr_drc_physical_info);
    type_register_static(&spapr_drc_logical_info);
    type_register_static(&spapr_drc_cpu_info);
    type_register_static(&spapr_drc_pci_info);
    type_register_static(&spapr_drc_lmb_info);
1162 1163 1164 1165 1166 1167 1168 1169 1170

    spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
                        rtas_set_indicator);
    spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
                        rtas_get_sensor_state);
    spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
                        rtas_ibm_configure_connector);
}
type_init(spapr_drc_register_types)