1 /* 2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 3 * 4 * Hypercall based emulated RTAS 5 * 6 * Copyright (c) 2010-2011 David Gibson, IBM Corporation. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 * 26 */ 27 #include "cpu.h" 28 #include "sysemu/sysemu.h" 29 #include "sysemu/char.h" 30 #include "hw/qdev.h" 31 #include "sysemu/device_tree.h" 32 33 #include "hw/ppc/spapr.h" 34 #include "hw/ppc/spapr_vio.h" 35 #include "qapi-event.h" 36 37 #include <libfdt.h> 38 #include "hw/ppc/spapr_drc.h" 39 40 /* #define DEBUG_SPAPR */ 41 42 #ifdef DEBUG_SPAPR 43 #define DPRINTF(fmt, ...) \ 44 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 45 #else 46 #define DPRINTF(fmt, ...) \ 47 do { } while (0) 48 #endif 49 50 static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPREnvironment *spapr, 51 uint32_t drc_index) 52 { 53 sPAPRConfigureConnectorState *ccs = NULL; 54 55 QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) { 56 if (ccs->drc_index == drc_index) { 57 break; 58 } 59 } 60 61 return ccs; 62 } 63 64 static void spapr_ccs_add(sPAPREnvironment *spapr, 65 sPAPRConfigureConnectorState *ccs) 66 { 67 g_assert(!spapr_ccs_find(spapr, ccs->drc_index)); 68 QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next); 69 } 70 71 static void spapr_ccs_remove(sPAPREnvironment *spapr, 72 sPAPRConfigureConnectorState *ccs) 73 { 74 QTAILQ_REMOVE(&spapr->ccs_list, ccs, next); 75 g_free(ccs); 76 } 77 78 void spapr_ccs_reset_hook(void *opaque) 79 { 80 sPAPREnvironment *spapr = opaque; 81 sPAPRConfigureConnectorState *ccs, *ccs_tmp; 82 83 QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) { 84 spapr_ccs_remove(spapr, ccs); 85 } 86 } 87 88 static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr, 89 uint32_t token, uint32_t nargs, 90 target_ulong args, 91 uint32_t nret, target_ulong rets) 92 { 93 uint8_t c = rtas_ld(args, 0); 94 VIOsPAPRDevice *sdev = vty_lookup(spapr, 0); 95 96 if (!sdev) { 97 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 98 } else { 99 vty_putchars(sdev, &c, sizeof(c)); 100 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 101 } 102 } 103 104 static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr, 105 uint32_t token, uint32_t nargs, target_ulong args, 106 uint32_t nret, target_ulong rets) 107 { 108 if (nargs != 2 || nret != 1) { 109 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 110 return; 111 } 112 qemu_system_shutdown_request(); 113 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 114 } 115 116 static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr, 117 uint32_t token, uint32_t nargs, 118 target_ulong args, 119 uint32_t nret, target_ulong rets) 120 { 121 if (nargs != 0 || nret != 1) { 122 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 123 return; 124 } 125 qemu_system_reset_request(); 126 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 127 } 128 129 static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_, 130 sPAPREnvironment *spapr, 131 uint32_t token, uint32_t nargs, 132 target_ulong args, 133 uint32_t nret, target_ulong rets) 134 { 135 target_ulong id; 136 PowerPCCPU *cpu; 137 138 if (nargs != 1 || nret != 2) { 139 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 140 return; 141 } 142 143 id = rtas_ld(args, 0); 144 cpu = ppc_get_vcpu_by_dt_id(id); 145 if (cpu != NULL) { 146 if (CPU(cpu)->halted) { 147 rtas_st(rets, 1, 0); 148 } else { 149 rtas_st(rets, 1, 2); 150 } 151 152 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 153 return; 154 } 155 156 /* Didn't find a matching cpu */ 157 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 158 } 159 160 static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr, 161 uint32_t token, uint32_t nargs, 162 target_ulong args, 163 uint32_t nret, target_ulong rets) 164 { 165 target_ulong id, start, r3; 166 PowerPCCPU *cpu; 167 168 if (nargs != 3 || nret != 1) { 169 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 170 return; 171 } 172 173 id = rtas_ld(args, 0); 174 start = rtas_ld(args, 1); 175 r3 = rtas_ld(args, 2); 176 177 cpu = ppc_get_vcpu_by_dt_id(id); 178 if (cpu != NULL) { 179 CPUState *cs = CPU(cpu); 180 CPUPPCState *env = &cpu->env; 181 182 if (!cs->halted) { 183 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 184 return; 185 } 186 187 /* This will make sure qemu state is up to date with kvm, and 188 * mark it dirty so our changes get flushed back before the 189 * new cpu enters */ 190 kvm_cpu_synchronize_state(cs); 191 192 env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME); 193 env->nip = start; 194 env->gpr[3] = r3; 195 cs->halted = 0; 196 197 qemu_cpu_kick(cs); 198 199 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 200 return; 201 } 202 203 /* Didn't find a matching cpu */ 204 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 205 } 206 207 static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr, 208 uint32_t token, uint32_t nargs, 209 target_ulong args, 210 uint32_t nret, target_ulong rets) 211 { 212 CPUState *cs = CPU(cpu); 213 CPUPPCState *env = &cpu->env; 214 215 cs->halted = 1; 216 cpu_exit(cs); 217 /* 218 * While stopping a CPU, the guest calls H_CPPR which 219 * effectively disables interrupts on XICS level. 220 * However decrementer interrupts in TCG can still 221 * wake the CPU up so here we disable interrupts in MSR 222 * as well. 223 * As rtas_start_cpu() resets the whole MSR anyway, there is 224 * no need to bother with specific bits, we just clear it. 225 */ 226 env->msr = 0; 227 } 228 229 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu, 230 sPAPREnvironment *spapr, 231 uint32_t token, uint32_t nargs, 232 target_ulong args, 233 uint32_t nret, target_ulong rets) 234 { 235 target_ulong parameter = rtas_ld(args, 0); 236 target_ulong buffer = rtas_ld(args, 1); 237 target_ulong length = rtas_ld(args, 2); 238 target_ulong ret = RTAS_OUT_SUCCESS; 239 240 switch (parameter) { 241 case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: { 242 char *param_val = g_strdup_printf("MaxEntCap=%d,MaxPlatProcs=%d", 243 max_cpus, smp_cpus); 244 rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val)); 245 g_free(param_val); 246 break; 247 } 248 case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: { 249 uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED; 250 251 rtas_st_buffer(buffer, length, ¶m_val, sizeof(param_val)); 252 break; 253 } 254 case RTAS_SYSPARM_UUID: 255 rtas_st_buffer(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0)); 256 break; 257 default: 258 ret = RTAS_OUT_NOT_SUPPORTED; 259 } 260 261 rtas_st(rets, 0, ret); 262 } 263 264 static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu, 265 sPAPREnvironment *spapr, 266 uint32_t token, uint32_t nargs, 267 target_ulong args, 268 uint32_t nret, target_ulong rets) 269 { 270 target_ulong parameter = rtas_ld(args, 0); 271 target_ulong ret = RTAS_OUT_NOT_SUPPORTED; 272 273 switch (parameter) { 274 case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: 275 case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: 276 case RTAS_SYSPARM_UUID: 277 ret = RTAS_OUT_NOT_AUTHORIZED; 278 break; 279 } 280 281 rtas_st(rets, 0, ret); 282 } 283 284 static void rtas_ibm_os_term(PowerPCCPU *cpu, 285 sPAPREnvironment *spapr, 286 uint32_t token, uint32_t nargs, 287 target_ulong args, 288 uint32_t nret, target_ulong rets) 289 { 290 target_ulong ret = 0; 291 292 qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort); 293 294 rtas_st(rets, 0, ret); 295 } 296 297 static void rtas_set_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr, 298 uint32_t token, uint32_t nargs, 299 target_ulong args, uint32_t nret, 300 target_ulong rets) 301 { 302 int32_t power_domain; 303 304 if (nargs != 2 || nret != 2) { 305 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 306 return; 307 } 308 309 /* we currently only use a single, "live insert" powerdomain for 310 * hotplugged/dlpar'd resources, so the power is always live/full (100) 311 */ 312 power_domain = rtas_ld(args, 0); 313 if (power_domain != -1) { 314 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); 315 return; 316 } 317 318 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 319 rtas_st(rets, 1, 100); 320 } 321 322 static void rtas_get_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr, 323 uint32_t token, uint32_t nargs, 324 target_ulong args, uint32_t nret, 325 target_ulong rets) 326 { 327 int32_t power_domain; 328 329 if (nargs != 1 || nret != 2) { 330 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 331 return; 332 } 333 334 /* we currently only use a single, "live insert" powerdomain for 335 * hotplugged/dlpar'd resources, so the power is always live/full (100) 336 */ 337 power_domain = rtas_ld(args, 0); 338 if (power_domain != -1) { 339 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); 340 return; 341 } 342 343 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 344 rtas_st(rets, 1, 100); 345 } 346 347 static bool sensor_type_is_dr(uint32_t sensor_type) 348 { 349 switch (sensor_type) { 350 case RTAS_SENSOR_TYPE_ISOLATION_STATE: 351 case RTAS_SENSOR_TYPE_DR: 352 case RTAS_SENSOR_TYPE_ALLOCATION_STATE: 353 return true; 354 } 355 356 return false; 357 } 358 359 static void rtas_set_indicator(PowerPCCPU *cpu, sPAPREnvironment *spapr, 360 uint32_t token, uint32_t nargs, 361 target_ulong args, uint32_t nret, 362 target_ulong rets) 363 { 364 uint32_t sensor_type; 365 uint32_t sensor_index; 366 uint32_t sensor_state; 367 sPAPRDRConnector *drc; 368 sPAPRDRConnectorClass *drck; 369 370 if (nargs != 3 || nret != 1) { 371 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 372 return; 373 } 374 375 sensor_type = rtas_ld(args, 0); 376 sensor_index = rtas_ld(args, 1); 377 sensor_state = rtas_ld(args, 2); 378 379 if (!sensor_type_is_dr(sensor_type)) { 380 goto out_unimplemented; 381 } 382 383 /* if this is a DR sensor we can assume sensor_index == drc_index */ 384 drc = spapr_dr_connector_by_index(sensor_index); 385 if (!drc) { 386 DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n", 387 sensor_index); 388 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 389 return; 390 } 391 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 392 393 switch (sensor_type) { 394 case RTAS_SENSOR_TYPE_ISOLATION_STATE: 395 /* if the guest is configuring a device attached to this 396 * DRC, we should reset the configuration state at this 397 * point since it may no longer be reliable (guest released 398 * device and needs to start over, or unplug occurred so 399 * the FDT is no longer valid) 400 */ 401 if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { 402 sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr, 403 sensor_index); 404 if (ccs) { 405 spapr_ccs_remove(spapr, ccs); 406 } 407 } 408 drck->set_isolation_state(drc, sensor_state); 409 break; 410 case RTAS_SENSOR_TYPE_DR: 411 drck->set_indicator_state(drc, sensor_state); 412 break; 413 case RTAS_SENSOR_TYPE_ALLOCATION_STATE: 414 drck->set_allocation_state(drc, sensor_state); 415 break; 416 default: 417 goto out_unimplemented; 418 } 419 420 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 421 return; 422 423 out_unimplemented: 424 /* currently only DR-related sensors are implemented */ 425 DPRINTF("rtas_set_indicator: sensor/indicator not implemented: %d\n", 426 sensor_type); 427 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); 428 } 429 430 static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPREnvironment *spapr, 431 uint32_t token, uint32_t nargs, 432 target_ulong args, uint32_t nret, 433 target_ulong rets) 434 { 435 uint32_t sensor_type; 436 uint32_t sensor_index; 437 sPAPRDRConnector *drc; 438 sPAPRDRConnectorClass *drck; 439 uint32_t entity_sense; 440 441 if (nargs != 2 || nret != 2) { 442 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 443 return; 444 } 445 446 sensor_type = rtas_ld(args, 0); 447 sensor_index = rtas_ld(args, 1); 448 449 if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) { 450 /* currently only DR-related sensors are implemented */ 451 DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n", 452 sensor_type); 453 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); 454 return; 455 } 456 457 drc = spapr_dr_connector_by_index(sensor_index); 458 if (!drc) { 459 DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n", 460 sensor_index); 461 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 462 return; 463 } 464 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 465 entity_sense = drck->entity_sense(drc); 466 467 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 468 rtas_st(rets, 1, entity_sense); 469 } 470 471 /* configure-connector work area offsets, int32_t units for field 472 * indexes, bytes for field offset/len values. 473 * 474 * as documented by PAPR+ v2.7, 13.5.3.5 475 */ 476 #define CC_IDX_NODE_NAME_OFFSET 2 477 #define CC_IDX_PROP_NAME_OFFSET 2 478 #define CC_IDX_PROP_LEN 3 479 #define CC_IDX_PROP_DATA_OFFSET 4 480 #define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4) 481 #define CC_WA_LEN 4096 482 483 static void rtas_ibm_configure_connector(PowerPCCPU *cpu, 484 sPAPREnvironment *spapr, 485 uint32_t token, uint32_t nargs, 486 target_ulong args, uint32_t nret, 487 target_ulong rets) 488 { 489 uint64_t wa_addr; 490 uint64_t wa_offset; 491 uint32_t drc_index; 492 sPAPRDRConnector *drc; 493 sPAPRDRConnectorClass *drck; 494 sPAPRConfigureConnectorState *ccs; 495 sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE; 496 int rc; 497 const void *fdt; 498 499 if (nargs != 2 || nret != 1) { 500 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 501 return; 502 } 503 504 wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0); 505 506 drc_index = rtas_ld(wa_addr, 0); 507 drc = spapr_dr_connector_by_index(drc_index); 508 if (!drc) { 509 DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n", 510 drc_index); 511 rc = RTAS_OUT_PARAM_ERROR; 512 goto out; 513 } 514 515 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 516 fdt = drck->get_fdt(drc, NULL); 517 518 ccs = spapr_ccs_find(spapr, drc_index); 519 if (!ccs) { 520 ccs = g_new0(sPAPRConfigureConnectorState, 1); 521 (void)drck->get_fdt(drc, &ccs->fdt_offset); 522 ccs->drc_index = drc_index; 523 spapr_ccs_add(spapr, ccs); 524 } 525 526 do { 527 uint32_t tag; 528 const char *name; 529 const struct fdt_property *prop; 530 int fdt_offset_next, prop_len; 531 532 tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next); 533 534 switch (tag) { 535 case FDT_BEGIN_NODE: 536 ccs->fdt_depth++; 537 name = fdt_get_name(fdt, ccs->fdt_offset, NULL); 538 539 /* provide the name of the next OF node */ 540 wa_offset = CC_VAL_DATA_OFFSET; 541 rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset); 542 rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset, 543 (uint8_t *)name, strlen(name) + 1); 544 resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD; 545 break; 546 case FDT_END_NODE: 547 ccs->fdt_depth--; 548 if (ccs->fdt_depth == 0) { 549 /* done sending the device tree, don't need to track 550 * the state anymore 551 */ 552 drck->set_configured(drc); 553 spapr_ccs_remove(spapr, ccs); 554 ccs = NULL; 555 resp = SPAPR_DR_CC_RESPONSE_SUCCESS; 556 } else { 557 resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT; 558 } 559 break; 560 case FDT_PROP: 561 prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset, 562 &prop_len); 563 name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); 564 565 /* provide the name of the next OF property */ 566 wa_offset = CC_VAL_DATA_OFFSET; 567 rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset); 568 rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset, 569 (uint8_t *)name, strlen(name) + 1); 570 571 /* provide the length and value of the OF property. data gets 572 * placed immediately after NULL terminator of the OF property's 573 * name string 574 */ 575 wa_offset += strlen(name) + 1, 576 rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len); 577 rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset); 578 rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset, 579 (uint8_t *)((struct fdt_property *)prop)->data, 580 prop_len); 581 resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY; 582 break; 583 case FDT_END: 584 resp = SPAPR_DR_CC_RESPONSE_ERROR; 585 default: 586 /* keep seeking for an actionable tag */ 587 break; 588 } 589 if (ccs) { 590 ccs->fdt_offset = fdt_offset_next; 591 } 592 } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE); 593 594 rc = resp; 595 out: 596 rtas_st(rets, 0, rc); 597 } 598 599 static struct rtas_call { 600 const char *name; 601 spapr_rtas_fn fn; 602 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE]; 603 604 target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr, 605 uint32_t token, uint32_t nargs, target_ulong args, 606 uint32_t nret, target_ulong rets) 607 { 608 if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) { 609 struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE); 610 611 if (call->fn) { 612 call->fn(cpu, spapr, token, nargs, args, nret, rets); 613 return H_SUCCESS; 614 } 615 } 616 617 /* HACK: Some Linux early debug code uses RTAS display-character, 618 * but assumes the token value is 0xa (which it is on some real 619 * machines) without looking it up in the device tree. This 620 * special case makes this work */ 621 if (token == 0xa) { 622 rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets); 623 return H_SUCCESS; 624 } 625 626 hcall_dprintf("Unknown RTAS token 0x%x\n", token); 627 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 628 return H_PARAMETER; 629 } 630 631 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn) 632 { 633 if (!((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX))) { 634 fprintf(stderr, "RTAS invalid token 0x%x\n", token); 635 exit(1); 636 } 637 638 token -= RTAS_TOKEN_BASE; 639 if (rtas_table[token].name) { 640 fprintf(stderr, "RTAS call \"%s\" is registered already as 0x%x\n", 641 rtas_table[token].name, token); 642 exit(1); 643 } 644 645 rtas_table[token].name = name; 646 rtas_table[token].fn = fn; 647 } 648 649 int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, 650 hwaddr rtas_size) 651 { 652 int ret; 653 int i; 654 655 ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size); 656 if (ret < 0) { 657 fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n", 658 fdt_strerror(ret)); 659 return ret; 660 } 661 662 ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base", 663 rtas_addr); 664 if (ret < 0) { 665 fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n", 666 fdt_strerror(ret)); 667 return ret; 668 } 669 670 ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry", 671 rtas_addr); 672 if (ret < 0) { 673 fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n", 674 fdt_strerror(ret)); 675 return ret; 676 } 677 678 ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size", 679 rtas_size); 680 if (ret < 0) { 681 fprintf(stderr, "Couldn't add rtas-size property: %s\n", 682 fdt_strerror(ret)); 683 return ret; 684 } 685 686 for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) { 687 struct rtas_call *call = &rtas_table[i]; 688 689 if (!call->name) { 690 continue; 691 } 692 693 ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name, 694 i + RTAS_TOKEN_BASE); 695 if (ret < 0) { 696 fprintf(stderr, "Couldn't add rtas token for %s: %s\n", 697 call->name, fdt_strerror(ret)); 698 return ret; 699 } 700 701 } 702 return 0; 703 } 704 705 static void core_rtas_register_types(void) 706 { 707 spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character", 708 rtas_display_character); 709 spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off); 710 spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot", 711 rtas_system_reboot); 712 spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state", 713 rtas_query_cpu_stopped_state); 714 spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu); 715 spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self); 716 spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER, 717 "ibm,get-system-parameter", 718 rtas_ibm_get_system_parameter); 719 spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER, 720 "ibm,set-system-parameter", 721 rtas_ibm_set_system_parameter); 722 spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term", 723 rtas_ibm_os_term); 724 spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level", 725 rtas_set_power_level); 726 spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level", 727 rtas_get_power_level); 728 spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator", 729 rtas_set_indicator); 730 spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state", 731 rtas_get_sensor_state); 732 spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector", 733 rtas_ibm_configure_connector); 734 } 735 736 type_init(core_rtas_register_types) 737