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