spapr_drc.c 39.5 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 50
static uint32_t set_isolation_state(sPAPRDRConnector *drc,
                                    sPAPRDRIsolationState state)
51 52 53
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

54
    trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);
55

56 57 58 59 60 61 62 63 64 65
    /* if the guest is configuring a device attached to this DRC, we
     * should reset the configuration state at this point since it may
     * no longer be reliable (guest released device and needs to start
     * over, or unplug occurred so the FDT is no longer valid)
     */
    if (state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
        g_free(drc->ccs);
        drc->ccs = NULL;
    }

66
    if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
S
Stefan Weil 已提交
67
        /* cannot unisolate a non-existent resource, and, or resources
68 69 70 71 72 73 74 75
         * which are in an 'UNUSABLE' allocation state. (PAPR 2.7, 13.5.3.5)
         */
        if (!drc->dev ||
            drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
            return RTAS_OUT_NO_SUCH_INDICATOR;
        }
    }

B
Bharata B Rao 已提交
76 77 78 79 80 81 82 83 84 85
    /*
     * 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.
     */
D
David Gibson 已提交
86
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB) {
B
Bharata B Rao 已提交
87 88 89 90 91 92
        if ((state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
             !drc->awaiting_release) {
            return RTAS_OUT_HW_ERROR;
        }
    }

93 94 95 96 97 98 99 100 101 102 103 104
    drc->isolation_state = state;

    if (drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
        /* 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
         */
        if (drc->awaiting_release) {
105
            uint32_t drc_index = spapr_drc_index(drc);
106
            if (drc->configured) {
107
                trace_spapr_drc_set_isolation_state_finalizing(drc_index);
108
                drck->detach(drc, DEVICE(drc->dev), NULL);
109
            } else {
110
                trace_spapr_drc_set_isolation_state_deferring(drc_index);
111 112 113 114 115
            }
        }
        drc->configured = false;
    }

116
    return RTAS_OUT_SUCCESS;
117 118
}

119 120
static uint32_t set_indicator_state(sPAPRDRConnector *drc,
                                    sPAPRDRIndicatorState state)
121
{
122
    trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state);
123
    drc->indicator_state = state;
124
    return RTAS_OUT_SUCCESS;
125 126
}

127 128
static uint32_t set_allocation_state(sPAPRDRConnector *drc,
                                     sPAPRDRAllocationState state)
129 130 131
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

132
    trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);
133

134 135 136 137 138 139 140 141 142
    if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
        /* 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;
        }
143 144 145 146 147 148 149 150 151 152 153
        if (drc->awaiting_release && drc->awaiting_allocation) {
            /* kernel is acknowledging a previous hotplug event
             * while we are already removing it.
             * it's safe to ignore awaiting_allocation here since we know the
             * situation is predicated on the guest either already having done
             * so (boot-time hotplug), or never being able to acquire in the
             * first place (hotplug followed by immediate unplug).
             */
            drc->awaiting_allocation_skippable = true;
            return RTAS_OUT_NO_SUCH_INDICATOR;
        }
154 155
    }

D
David Gibson 已提交
156
    if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) {
157 158 159
        drc->allocation_state = state;
        if (drc->awaiting_release &&
            drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
160 161
            uint32_t drc_index = spapr_drc_index(drc);
            trace_spapr_drc_set_allocation_state_finalizing(drc_index);
162
            drck->detach(drc, DEVICE(drc->dev), NULL);
163 164
        } else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
            drc->awaiting_allocation = false;
165 166
        }
    }
167
    return RTAS_OUT_SUCCESS;
168 169 170 171 172 173 174
}

static const char *get_name(sPAPRDRConnector *drc)
{
    return drc->name;
}

175 176 177 178 179 180
/* has the guest been notified of device attachment? */
static void set_signalled(sPAPRDRConnector *drc)
{
    drc->signalled = true;
}

181 182 183 184 185 186 187
/*
 * 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.
 */
188
static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc)
189
{
190 191 192 193 194 195 196 197 198 199 200 201 202 203
    /* 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)
{
    if (drc->dev
        && (drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE)) {
        return SPAPR_DR_ENTITY_SENSE_PRESENT;
204
    } else {
205
        return SPAPR_DR_ENTITY_SENSE_UNUSABLE;
206 207 208
    }
}

209 210
static void prop_get_index(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
211 212
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
213
    uint32_t value = spapr_drc_index(drc);
214
    visit_type_uint32(v, name, &value, errp);
215 216 217 218 219 220 221 222 223
}

static char *prop_get_name(Object *obj, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
    return g_strdup(drck->get_name(drc));
}

224 225
static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
226 227
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
228
    Error *err = NULL;
229 230 231 232
    int fdt_offset_next, fdt_offset, fdt_depth;
    void *fdt;

    if (!drc->fdt) {
233
        visit_type_null(v, NULL, errp);
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
        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);
252
            visit_start_struct(v, name, NULL, 0, &err);
253 254 255 256
            if (err) {
                error_propagate(errp, err);
                return;
            }
257 258 259 260
            break;
        case FDT_END_NODE:
            /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
            g_assert(fdt_depth > 0);
261
            visit_check_struct(v, &err);
E
Eric Blake 已提交
262
            visit_end_struct(v, NULL);
263 264 265 266
            if (err) {
                error_propagate(errp, err);
                return;
            }
267 268 269 270 271 272
            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));
273
            visit_start_list(v, name, NULL, 0, &err);
274 275 276 277
            if (err) {
                error_propagate(errp, err);
                return;
            }
278
            for (i = 0; i < prop_len; i++) {
279
                visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err);
280 281 282 283 284
                if (err) {
                    error_propagate(errp, err);
                    return;
                }
            }
285
            visit_check_list(v, &err);
E
Eric Blake 已提交
286
            visit_end_list(v, NULL);
287 288 289 290
            if (err) {
                error_propagate(errp, err);
                return;
            }
291 292 293 294 295 296 297 298 299 300 301 302
            break;
        }
        default:
            error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
        }
        fdt_offset = fdt_offset_next;
    } while (fdt_depth != 0);
}

static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
                   int fdt_start_offset, bool coldplug, Error **errp)
{
303
    trace_spapr_drc_attach(spapr_drc_index(drc));
304 305 306 307 308

    if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
        error_setg(errp, "an attached device is still awaiting release");
        return;
    }
D
David Gibson 已提交
309
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
310 311 312 313 314 315 316 317 318 319 320
        g_assert(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE);
    }
    g_assert(fdt || coldplug);

    /* NOTE: setting initial isolation state to UNISOLATED means we can't
     * detach unless guest has a userspace/kernel that moves this state
     * back to ISOLATED in response to an unplug event, or this is done
     * manually by the admin prior. if we force things while the guest
     * may be accessing the device, we can easily crash the guest, so we
     * we defer completion of removal in such cases to the reset() hook.
     */
D
David Gibson 已提交
321
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
322 323 324 325 326 327 328
        drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED;
    }
    drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE;

    drc->dev = d;
    drc->fdt = fdt;
    drc->fdt_start_offset = fdt_start_offset;
329
    drc->configured = coldplug;
330 331 332 333 334 335 336 337 338
    /* 'logical' DR resources such as memory/cpus are in some cases treated
     * as a pool of resources from which the guest is free to choose from
     * based on only a count. for resources that can be assigned in this
     * fashion, we must assume the resource is signalled immediately
     * since a single hotplug request might make an arbitrary number of
     * such attached resources available to the guest, as opposed to
     * 'physical' DR resources such as PCI where each device/resource is
     * signalled individually.
     */
D
David Gibson 已提交
339
    drc->signalled = (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI)
340
                     ? true : coldplug;
341

D
David Gibson 已提交
342
    if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) {
343 344 345
        drc->awaiting_allocation = true;
    }

346 347 348 349 350 351
    object_property_add_link(OBJECT(drc), "device",
                             object_get_typename(OBJECT(drc->dev)),
                             (Object **)(&drc->dev),
                             NULL, 0, NULL);
}

352
static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
353
{
354
    trace_spapr_drc_detach(spapr_drc_index(drc));
355

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
    /* if we've signalled device presence to the guest, or if the guest
     * has gone ahead and configured the device (via manually-executed
     * device add via drmgr in guest, namely), we need to wait
     * for the guest to quiesce the device before completing detach.
     * Otherwise, we can assume the guest hasn't seen it and complete the
     * detach immediately. Note that there is a small race window
     * just before, or during, configuration, which is this context
     * refers mainly to fetching the device tree via RTAS.
     * During this window the device access will be arbitrated by
     * associated DRC, which will simply fail the RTAS calls as invalid.
     * This is recoverable within guest and current implementations of
     * drmgr should be able to cope.
     */
    if (!drc->signalled && !drc->configured) {
        /* if the guest hasn't seen the device we can't rely on it to
         * set it back to an isolated state via RTAS, so do it here manually
         */
        drc->isolation_state = SPAPR_DR_ISOLATION_STATE_ISOLATED;
    }

376
    if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
377
        trace_spapr_drc_awaiting_isolated(spapr_drc_index(drc));
378 379 380 381
        drc->awaiting_release = true;
        return;
    }

D
David Gibson 已提交
382
    if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI &&
383
        drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
384
        trace_spapr_drc_awaiting_unusable(spapr_drc_index(drc));
385 386 387 388
        drc->awaiting_release = true;
        return;
    }

389
    if (drc->awaiting_allocation) {
390 391
        if (!drc->awaiting_allocation_skippable) {
            drc->awaiting_release = true;
392
            trace_spapr_drc_awaiting_allocation(spapr_drc_index(drc));
393 394
            return;
        }
395 396
    }

397 398
    drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE;

D
David Gibson 已提交
399 400
    /* Calling release callbacks based on spapr_drc_type(drc). */
    switch (spapr_drc_type(drc)) {
401 402 403 404 405 406 407 408 409 410 411 412 413
    case SPAPR_DR_CONNECTOR_TYPE_CPU:
        spapr_core_release(drc->dev);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_PCI:
        spapr_phb_remove_pci_device_cb(drc->dev);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_LMB:
        spapr_lmb_release(drc->dev);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_PHB:
    case SPAPR_DR_CONNECTOR_TYPE_VIO:
    default:
        g_assert(false);
414 415 416
    }

    drc->awaiting_release = false;
417
    drc->awaiting_allocation_skippable = false;
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    g_free(drc->fdt);
    drc->fdt = NULL;
    drc->fdt_start_offset = 0;
    object_property_del(OBJECT(drc), "device", NULL);
    drc->dev = NULL;
}

static bool release_pending(sPAPRDRConnector *drc)
{
    return drc->awaiting_release;
}

static void reset(DeviceState *d)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

435
    trace_spapr_drc_reset(spapr_drc_index(drc));
436 437 438 439

    g_free(drc->ccs);
    drc->ccs = NULL;

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    /* immediately upon reset we can safely assume DRCs whose devices
     * are pending removal can be safely removed, and that they will
     * subsequently be left in an ISOLATED state. move the DRC to this
     * state in these cases (which will in turn complete any pending
     * device removals)
     */
    if (drc->awaiting_release) {
        drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_ISOLATED);
        /* generally this should also finalize the removal, but if the device
         * hasn't yet been configured we normally defer removal under the
         * assumption that this transition is taking place as part of device
         * configuration. so check if we're still waiting after this, and
         * force removal if we are
         */
        if (drc->awaiting_release) {
455
            drck->detach(drc, DEVICE(drc->dev), NULL);
456 457 458
        }

        /* non-PCI devices may be awaiting a transition to UNUSABLE */
D
David Gibson 已提交
459
        if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI &&
460 461 462 463
            drc->awaiting_release) {
            drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_UNUSABLE);
        }
    }
464

465
    if (drck->dr_entity_sense(drc) == SPAPR_DR_ENTITY_SENSE_PRESENT) {
466 467
        drck->set_signalled(drc);
    }
468 469
}

470 471 472 473 474
static bool spapr_drc_needed(void *opaque)
{
    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
    bool rc = false;
475
    sPAPRDREntitySense value = drck->dr_entity_sense(drc);
476 477 478 479 480 481 482 483 484 485

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

    /*
     * If there is dev plugged in, we need to migrate the DRC state when
     * it is different from cold-plugged state
     */
D
David Gibson 已提交
486
    switch (spapr_drc_type(drc)) {
487 488 489
    case SPAPR_DR_CONNECTOR_TYPE_PCI:
    case SPAPR_DR_CONNECTOR_TYPE_CPU:
    case SPAPR_DR_CONNECTOR_TYPE_LMB:
490 491
        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
492 493 494 495 496
               drc->configured && drc->signalled && !drc->awaiting_release);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_PHB:
    case SPAPR_DR_CONNECTOR_TYPE_VIO:
    default:
497
        g_assert_not_reached();
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
    }
    return rc;
}

static const VMStateDescription vmstate_spapr_drc = {
    .name = "spapr_drc",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = spapr_drc_needed,
    .fields  = (VMStateField []) {
        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
        VMSTATE_BOOL(configured, sPAPRDRConnector),
        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
        VMSTATE_BOOL(awaiting_allocation, sPAPRDRConnector),
        VMSTATE_BOOL(signalled, sPAPRDRConnector),
        VMSTATE_END_OF_LIST()
    }
};

519 520 521 522 523 524 525 526
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;

527
    trace_spapr_drc_realize(spapr_drc_index(drc));
528 529 530 531 532 533 534 535
    /* 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);
536
    snprintf(link_name, sizeof(link_name), "%x", spapr_drc_index(drc));
537
    child_name = object_get_canonical_path_component(OBJECT(drc));
538
    trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
539 540 541
    object_property_add_alias(root_container, link_name,
                              drc->owner, child_name, &err);
    if (err) {
542
        error_report_err(err);
543 544
        object_unref(OBJECT(drc));
    }
G
Gonglei 已提交
545
    g_free(child_name);
546
    vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
547
                     drc);
548
    trace_spapr_drc_realize_complete(spapr_drc_index(drc));
549 550 551 552 553 554 555 556 557
}

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

558
    trace_spapr_drc_unrealize(spapr_drc_index(drc));
559
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
560
    snprintf(name, sizeof(name), "%x", spapr_drc_index(drc));
561 562
    object_property_del(root_container, name, &err);
    if (err) {
563
        error_report_err(err);
564 565 566 567
        object_unref(OBJECT(drc));
    }
}

D
David Gibson 已提交
568
sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
569 570
                                         uint32_t id)
{
D
David Gibson 已提交
571
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
572
    char *prop_name;
573 574 575

    drc->id = id;
    drc->owner = owner;
576 577
    prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
                                spapr_drc_index(drc));
578
    object_property_add_child(owner, prop_name, OBJECT(drc), NULL);
579
    object_property_set_bool(OBJECT(drc), true, "realized", NULL);
580
    g_free(prop_name);
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

    /* 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
     */
D
David Gibson 已提交
603
    switch (spapr_drc_type(drc)) {
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
    case SPAPR_DR_CONNECTOR_TYPE_CPU:
        drc->name = g_strdup_printf("CPU %d", id);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_PHB:
        drc->name = g_strdup_printf("PHB %d", id);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_VIO:
    case SPAPR_DR_CONNECTOR_TYPE_PCI:
        drc->name = g_strdup_printf("C%d", id);
        break;
    case SPAPR_DR_CONNECTOR_TYPE_LMB:
        drc->name = g_strdup_printf("LMB %d", id);
        break;
    default:
        g_assert(false);
    }

    /* PCI slot always start in a USABLE state, and stay there */
D
David Gibson 已提交
622
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE;
    }

    return drc;
}

static void spapr_dr_connector_instance_init(Object *obj)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);

    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_str(obj, "name", prop_get_name, NULL, NULL);
    object_property_add(obj, "fdt", "struct", prop_get_fdt,
                        NULL, NULL, NULL, NULL);
}

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

    dk->reset = reset;
    dk->realize = realize;
    dk->unrealize = unrealize;
    drck->set_isolation_state = set_isolation_state;
    drck->set_indicator_state = set_indicator_state;
    drck->set_allocation_state = set_allocation_state;
    drck->get_name = get_name;
    drck->attach = attach;
    drck->detach = detach;
    drck->release_pending = release_pending;
656
    drck->set_signalled = set_signalled;
657 658 659
    /*
     * Reason: it crashes FIXME find and document the real reason
     */
660
    dk->user_creatable = false;
661 662
}

663 664 665 666 667 668 669 670 671 672 673 674 675 676
static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->dr_entity_sense = physical_entity_sense;
}

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;
}

D
David Gibson 已提交
677 678 679 680 681
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;
682
    drck->typename = "CPU";
D
David Gibson 已提交
683 684 685 686 687 688 689
}

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;
690
    drck->typename = "28";
D
David Gibson 已提交
691 692 693 694 695 696 697
}

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;
698
    drck->typename = "MEM";
D
David Gibson 已提交
699 700
}

701 702 703 704 705 706 707
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 已提交
708 709 710 711 712 713 714
    .abstract      = true,
};

static const TypeInfo spapr_drc_physical_info = {
    .name          = TYPE_SPAPR_DRC_PHYSICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
    .instance_size = sizeof(sPAPRDRConnector),
715
    .class_init    = spapr_drc_physical_class_init,
D
David Gibson 已提交
716 717 718 719 720 721 722
    .abstract      = true,
};

static const TypeInfo spapr_drc_logical_info = {
    .name          = TYPE_SPAPR_DRC_LOGICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
    .instance_size = sizeof(sPAPRDRConnector),
723
    .class_init    = spapr_drc_logical_class_init,
D
David Gibson 已提交
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
    .abstract      = true,
};

static const TypeInfo spapr_drc_cpu_info = {
    .name          = TYPE_SPAPR_DRC_CPU,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .instance_size = sizeof(sPAPRDRConnector),
    .class_init    = spapr_drc_cpu_class_init,
};

static const TypeInfo spapr_drc_pci_info = {
    .name          = TYPE_SPAPR_DRC_PCI,
    .parent        = TYPE_SPAPR_DRC_PHYSICAL,
    .instance_size = sizeof(sPAPRDRConnector),
    .class_init    = spapr_drc_pci_class_init,
};

static const TypeInfo spapr_drc_lmb_info = {
    .name          = TYPE_SPAPR_DRC_LMB,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .instance_size = sizeof(sPAPRDRConnector),
    .class_init    = spapr_drc_lmb_class_init,
746 747 748 749
};

/* helper functions for external users */

750
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
751 752 753 754 755 756 757 758 759 760
{
    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);
}

761
sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
762
{
763 764 765 766 767
    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));
768
}
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788

/**
 * 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;
789
    ObjectPropertyIterator iter;
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
    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);

813 814
    object_property_iter_init(&iter, root_container);
    while ((prop = object_property_iter_next(&iter))) {
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
        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 已提交
832
        if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
833 834 835 836 837 838
            continue;
        }

        drc_count++;

        /* ibm,drc-indexes */
839
        drc_index = cpu_to_be32(spapr_drc_index(drc));
840 841 842 843 844 845 846 847 848 849 850
        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 */
        drc_names = g_string_append(drc_names, drck->get_name(drc));
        drc_names = g_string_insert_len(drc_names, -1, "\0", 1);

        /* ibm,drc-types */
851
        drc_types = g_string_append(drc_types, drck->typename);
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
        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) {
867
        error_report("Couldn't create ibm,drc-indexes property");
868 869 870 871 872 873 874
        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) {
875
        error_report("Couldn't finalize ibm,drc-power-domains property");
876 877 878 879 880 881
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
                      drc_names->str, drc_names->len);
    if (ret) {
882
        error_report("Couldn't finalize ibm,drc-names property");
883 884 885 886 887 888
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
                      drc_types->str, drc_types->len);
    if (ret) {
889
        error_report("Couldn't finalize ibm,drc-types property");
890 891 892 893 894 895 896 897 898 899 900
        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;
}
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943

/*
 * RTAS calls
 */

static bool sensor_type_is_dr(uint32_t sensor_type)
{
    switch (sensor_type) {
    case RTAS_SENSOR_TYPE_ISOLATION_STATE:
    case RTAS_SENSOR_TYPE_DR:
    case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
        return true;
    }

    return false;
}

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 sensor_type;
    uint32_t sensor_index;
    uint32_t sensor_state;
    uint32_t ret = RTAS_OUT_SUCCESS;
    sPAPRDRConnector *drc;
    sPAPRDRConnectorClass *drck;

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

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

    if (!sensor_type_is_dr(sensor_type)) {
        goto out_unimplemented;
    }

    /* if this is a DR sensor we can assume sensor_index == drc_index */
944
    drc = spapr_drc_by_index(sensor_index);
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 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
    if (!drc) {
        trace_spapr_rtas_set_indicator_invalid(sensor_index);
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }
    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    switch (sensor_type) {
    case RTAS_SENSOR_TYPE_ISOLATION_STATE:
        ret = drck->set_isolation_state(drc, sensor_state);
        break;
    case RTAS_SENSOR_TYPE_DR:
        ret = drck->set_indicator_state(drc, sensor_state);
        break;
    case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
        ret = drck->set_allocation_state(drc, sensor_state);
        break;
    default:
        goto out_unimplemented;
    }

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

out_unimplemented:
    /* currently only DR-related sensors are implemented */
    trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type);
    rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
}

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;
    }

1004
    drc = spapr_drc_by_index(sensor_index);
1005 1006 1007 1008 1009 1010
    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);
1011
    sensor_state = drck->dr_entity_sense(drc);
1012 1013 1014 1015 1016 1017 1018 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 1054 1055 1056 1057 1058

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;
    sPAPRConfigureConnectorState *ccs;
    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);
1059
    drc = spapr_drc_by_index(drc_index);
1060 1061 1062 1063 1064 1065
    if (!drc) {
        trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
        rc = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

D
David Gibson 已提交
1066
    if (!drc->fdt) {
1067 1068 1069 1070 1071
        trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index);
        rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
        goto out;
    }

1072
    ccs = drc->ccs;
1073 1074
    if (!ccs) {
        ccs = g_new0(sPAPRConfigureConnectorState, 1);
D
David Gibson 已提交
1075
        ccs->fdt_offset = drc->fdt_start_offset;
1076
        drc->ccs = ccs;
1077 1078 1079 1080 1081 1082 1083 1084
    }

    do {
        uint32_t tag;
        const char *name;
        const struct fdt_property *prop;
        int fdt_offset_next, prop_len;

D
David Gibson 已提交
1085
        tag = fdt_next_tag(drc->fdt, ccs->fdt_offset, &fdt_offset_next);
1086 1087 1088 1089

        switch (tag) {
        case FDT_BEGIN_NODE:
            ccs->fdt_depth++;
D
David Gibson 已提交
1090
            name = fdt_get_name(drc->fdt, ccs->fdt_offset, NULL);
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100

            /* 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:
            ccs->fdt_depth--;
            if (ccs->fdt_depth == 0) {
1101
                sPAPRDRIsolationState state = drc->isolation_state;
1102
                uint32_t drc_index = spapr_drc_index(drc);
1103 1104 1105
                /* done sending the device tree, don't need to track
                 * the state anymore
                 */
1106
                trace_spapr_drc_set_configured(drc_index);
1107 1108 1109 1110
                if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
                    drc->configured = true;
                } else {
                    /* guest should be not configuring an isolated device */
1111
                    trace_spapr_drc_set_configured_skipping(drc_index);
1112
                }
1113 1114
                g_free(ccs);
                drc->ccs = NULL;
1115 1116 1117 1118 1119 1120 1121
                ccs = NULL;
                resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
            } else {
                resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
            }
            break;
        case FDT_PROP:
D
David Gibson 已提交
1122
            prop = fdt_get_property_by_offset(drc->fdt, ccs->fdt_offset,
1123
                                              &prop_len);
D
David Gibson 已提交
1124
            name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

            /* 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;
        }
        if (ccs) {
            ccs->fdt_offset = fdt_offset_next;
        }
    } 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 已提交
1160 1161 1162 1163 1164
    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);
1165 1166 1167 1168 1169 1170 1171 1172 1173

    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)