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