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