virtio-gpu: check max_outputs only
[qemu/ar7.git] / hw / ppc / spapr_rtas.c
blob43e2c684fda8dbb4eda33bf0f380110709202a59
1 /*
2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
4 * Hypercall based emulated RTAS
6 * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
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"
37 #include "hw/ppc/spapr.h"
38 #include "hw/ppc/spapr_vio.h"
39 #include "qapi-event.h"
40 #include "hw/boards.h"
42 #include <libfdt.h>
43 #include "hw/ppc/spapr_drc.h"
44 #include "qemu/cutils.h"
46 /* #define DEBUG_SPAPR */
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
56 static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPRMachineState *spapr,
57 uint32_t drc_index)
59 sPAPRConfigureConnectorState *ccs = NULL;
61 QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) {
62 if (ccs->drc_index == drc_index) {
63 break;
67 return ccs;
70 static void spapr_ccs_add(sPAPRMachineState *spapr,
71 sPAPRConfigureConnectorState *ccs)
73 g_assert(!spapr_ccs_find(spapr, ccs->drc_index));
74 QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next);
77 static void spapr_ccs_remove(sPAPRMachineState *spapr,
78 sPAPRConfigureConnectorState *ccs)
80 QTAILQ_REMOVE(&spapr->ccs_list, ccs, next);
81 g_free(ccs);
84 void spapr_ccs_reset_hook(void *opaque)
86 sPAPRMachineState *spapr = opaque;
87 sPAPRConfigureConnectorState *ccs, *ccs_tmp;
89 QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) {
90 spapr_ccs_remove(spapr, ccs);
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)
99 uint8_t c = rtas_ld(args, 0);
100 VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
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);
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)
114 if (nargs != 2 || nret != 1) {
115 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
116 return;
118 qemu_system_shutdown_request();
119 cpu_stop_current();
120 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
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)
128 if (nargs != 0 || nret != 1) {
129 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
130 return;
132 qemu_system_reset_request();
133 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
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)
142 target_ulong id;
143 PowerPCCPU *cpu;
145 if (nargs != 1 || nret != 2) {
146 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
147 return;
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);
159 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
160 return;
163 /* Didn't find a matching cpu */
164 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
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)
172 target_ulong id, start, r3;
173 PowerPCCPU *cpu;
175 if (nargs != 3 || nret != 1) {
176 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
177 return;
180 id = rtas_ld(args, 0);
181 start = rtas_ld(args, 1);
182 r3 = rtas_ld(args, 2);
184 cpu = ppc_get_vcpu_by_dt_id(id);
185 if (cpu != NULL) {
186 CPUState *cs = CPU(cpu);
187 CPUPPCState *env = &cpu->env;
189 if (!cs->halted) {
190 rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
191 return;
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);
199 env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
200 env->nip = start;
201 env->gpr[3] = r3;
202 cs->halted = 0;
204 qemu_cpu_kick(cs);
206 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
207 return;
210 /* Didn't find a matching cpu */
211 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
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)
219 CPUState *cs = CPU(cpu);
220 CPUPPCState *env = &cpu->env;
222 cs->halted = 1;
223 qemu_cpu_kick(cs);
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.
233 env->msr = 0;
236 static inline int sysparm_st(target_ulong addr, target_ulong len,
237 const void *val, uint16_t vallen)
239 hwaddr phys = ppc64_phys_to_real(addr);
241 if (len < 2) {
242 return RTAS_OUT_SYSPARM_PARAM_ERROR;
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;
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)
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;
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;
274 case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
275 uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
277 ret = sysparm_st(buffer, length, &param_val, sizeof(param_val));
278 break;
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;
287 rtas_st(rets, 0, ret);
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)
296 target_ulong parameter = rtas_ld(args, 0);
297 target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
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;
307 rtas_st(rets, 0, ret);
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)
316 target_ulong ret = 0;
318 qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
320 rtas_st(rets, 0, ret);
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)
328 int32_t power_domain;
330 if (nargs != 2 || nret != 2) {
331 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
332 return;
335 /* we currently only use a single, "live insert" powerdomain for
336 * hotplugged/dlpar'd resources, so the power is always live/full (100)
338 power_domain = rtas_ld(args, 0);
339 if (power_domain != -1) {
340 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
341 return;
344 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
345 rtas_st(rets, 1, 100);
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)
353 int32_t power_domain;
355 if (nargs != 1 || nret != 2) {
356 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
357 return;
360 /* we currently only use a single, "live insert" powerdomain for
361 * hotplugged/dlpar'd resources, so the power is always live/full (100)
363 power_domain = rtas_ld(args, 0);
364 if (power_domain != -1) {
365 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
366 return;
369 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
370 rtas_st(rets, 1, 100);
373 static bool sensor_type_is_dr(uint32_t sensor_type)
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;
382 return false;
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)
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;
397 if (nargs != 3 || nret != 1) {
398 ret = RTAS_OUT_PARAM_ERROR;
399 goto out;
402 sensor_type = rtas_ld(args, 0);
403 sensor_index = rtas_ld(args, 1);
404 sensor_state = rtas_ld(args, 2);
406 if (!sensor_type_is_dr(sensor_type)) {
407 goto out_unimplemented;
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;
418 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
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)
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);
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;
447 out:
448 rtas_st(rets, 0, ret);
449 return;
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);
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)
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;
470 if (nargs != 2 || nret != 2) {
471 ret = RTAS_OUT_PARAM_ERROR;
472 goto out;
475 sensor_type = rtas_ld(args, 0);
476 sensor_index = rtas_ld(args, 1);
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;
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;
493 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
494 ret = drck->entity_sense(drc, &sensor_state);
496 out:
497 rtas_st(rets, 0, ret);
498 rtas_st(rets, 1, sensor_state);
501 /* configure-connector work area offsets, int32_t units for field
502 * indexes, bytes for field offset/len values.
504 * as documented by PAPR+ v2.7, 13.5.3.5
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
513 static void configure_connector_st(target_ulong addr, target_ulong offset,
514 const void *buf, size_t len)
516 cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
517 buf, MIN(len, CC_WA_LEN - offset));
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)
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;
536 if (nargs != 2 || nret != 1) {
537 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
538 return;
541 wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
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;
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;
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);
569 do {
570 uint32_t tag;
571 const char *name;
572 const struct fdt_property *prop;
573 int fdt_offset_next, prop_len;
575 tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next);
577 switch (tag) {
578 case FDT_BEGIN_NODE:
579 ccs->fdt_depth++;
580 name = fdt_get_name(fdt, ccs->fdt_offset, NULL);
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
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;
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));
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);
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
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;
628 if (ccs) {
629 ccs->fdt_offset = fdt_offset_next;
631 } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
633 rc = resp;
634 out:
635 rtas_st(rets, 0, rc);
638 static struct rtas_call {
639 const char *name;
640 spapr_rtas_fn fn;
641 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
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)
647 if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
648 struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
650 if (call->fn) {
651 call->fn(cpu, spapr, token, nargs, args, nret, rets);
652 return H_SUCCESS;
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;
665 hcall_dprintf("Unknown RTAS token 0x%x\n", token);
666 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
667 return H_PARAMETER;
670 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
672 assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
674 token -= RTAS_TOKEN_BASE;
676 assert(!rtas_table[token].name);
678 rtas_table[token].name = name;
679 rtas_table[token].fn = fn;
682 int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
683 hwaddr rtas_size)
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);
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;
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;
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;
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;
724 for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
725 struct rtas_call *call = &rtas_table[i];
727 if (!call->name) {
728 continue;
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;
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;
753 return 0;
756 static void core_rtas_register_types(void)
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);
787 type_init(core_rtas_register_types)