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