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