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