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