xref: /qemu/hw/ppc/spapr_rtas.c (revision 46503c2bc047bfe8c26440e17298fcbc59d7bbbe)
139ac8455SDavid Gibson /*
239ac8455SDavid Gibson  * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
339ac8455SDavid Gibson  *
439ac8455SDavid Gibson  * Hypercall based emulated RTAS
539ac8455SDavid Gibson  *
639ac8455SDavid Gibson  * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
739ac8455SDavid Gibson  *
839ac8455SDavid Gibson  * Permission is hereby granted, free of charge, to any person obtaining a copy
939ac8455SDavid Gibson  * of this software and associated documentation files (the "Software"), to deal
1039ac8455SDavid Gibson  * in the Software without restriction, including without limitation the rights
1139ac8455SDavid Gibson  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1239ac8455SDavid Gibson  * copies of the Software, and to permit persons to whom the Software is
1339ac8455SDavid Gibson  * furnished to do so, subject to the following conditions:
1439ac8455SDavid Gibson  *
1539ac8455SDavid Gibson  * The above copyright notice and this permission notice shall be included in
1639ac8455SDavid Gibson  * all copies or substantial portions of the Software.
1739ac8455SDavid Gibson  *
1839ac8455SDavid Gibson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1939ac8455SDavid Gibson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2039ac8455SDavid Gibson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2139ac8455SDavid Gibson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2239ac8455SDavid Gibson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2339ac8455SDavid Gibson  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2439ac8455SDavid Gibson  * THE SOFTWARE.
2539ac8455SDavid Gibson  *
2639ac8455SDavid Gibson  */
2739ac8455SDavid Gibson #include "cpu.h"
289c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
29dccfcd0eSPaolo Bonzini #include "sysemu/char.h"
3039ac8455SDavid Gibson #include "hw/qdev.h"
319c17d615SPaolo Bonzini #include "sysemu/device_tree.h"
3239ac8455SDavid Gibson 
330d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h"
340d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h"
35e010ad8fSWenchao Xia #include "qapi-event.h"
3639ac8455SDavid Gibson 
3739ac8455SDavid Gibson #include <libfdt.h>
388c8639dfSMike Day #include "hw/ppc/spapr_drc.h"
398c8639dfSMike Day 
408c8639dfSMike Day /* #define DEBUG_SPAPR */
418c8639dfSMike Day 
428c8639dfSMike Day #ifdef DEBUG_SPAPR
438c8639dfSMike Day #define DPRINTF(fmt, ...) \
448c8639dfSMike Day     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
458c8639dfSMike Day #else
468c8639dfSMike Day #define DPRINTF(fmt, ...) \
478c8639dfSMike Day     do { } while (0)
488c8639dfSMike Day #endif
498c8639dfSMike Day 
50*46503c2bSMichael Roth static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPREnvironment *spapr,
51*46503c2bSMichael Roth                                                     uint32_t drc_index)
52*46503c2bSMichael Roth {
53*46503c2bSMichael Roth     sPAPRConfigureConnectorState *ccs = NULL;
54*46503c2bSMichael Roth 
55*46503c2bSMichael Roth     QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) {
56*46503c2bSMichael Roth         if (ccs->drc_index == drc_index) {
57*46503c2bSMichael Roth             break;
58*46503c2bSMichael Roth         }
59*46503c2bSMichael Roth     }
60*46503c2bSMichael Roth 
61*46503c2bSMichael Roth     return ccs;
62*46503c2bSMichael Roth }
63*46503c2bSMichael Roth 
64*46503c2bSMichael Roth static void spapr_ccs_add(sPAPREnvironment *spapr,
65*46503c2bSMichael Roth                           sPAPRConfigureConnectorState *ccs)
66*46503c2bSMichael Roth {
67*46503c2bSMichael Roth     g_assert(!spapr_ccs_find(spapr, ccs->drc_index));
68*46503c2bSMichael Roth     QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next);
69*46503c2bSMichael Roth }
70*46503c2bSMichael Roth 
71*46503c2bSMichael Roth static void spapr_ccs_remove(sPAPREnvironment *spapr,
72*46503c2bSMichael Roth                              sPAPRConfigureConnectorState *ccs)
73*46503c2bSMichael Roth {
74*46503c2bSMichael Roth     QTAILQ_REMOVE(&spapr->ccs_list, ccs, next);
75*46503c2bSMichael Roth     g_free(ccs);
76*46503c2bSMichael Roth }
77*46503c2bSMichael Roth 
78*46503c2bSMichael Roth void spapr_ccs_reset_hook(void *opaque)
79*46503c2bSMichael Roth {
80*46503c2bSMichael Roth     sPAPREnvironment *spapr = opaque;
81*46503c2bSMichael Roth     sPAPRConfigureConnectorState *ccs, *ccs_tmp;
82*46503c2bSMichael Roth 
83*46503c2bSMichael Roth     QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) {
84*46503c2bSMichael Roth         spapr_ccs_remove(spapr, ccs);
85*46503c2bSMichael Roth     }
86*46503c2bSMichael Roth }
8739ac8455SDavid Gibson 
88210b580bSAnthony Liguori static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
89821303f5SDavid Gibson                                    uint32_t token, uint32_t nargs,
90821303f5SDavid Gibson                                    target_ulong args,
91821303f5SDavid Gibson                                    uint32_t nret, target_ulong rets)
92821303f5SDavid Gibson {
93821303f5SDavid Gibson     uint8_t c = rtas_ld(args, 0);
945f2e2ba2SDavid Gibson     VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
95821303f5SDavid Gibson 
96821303f5SDavid Gibson     if (!sdev) {
97a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
98821303f5SDavid Gibson     } else {
99821303f5SDavid Gibson         vty_putchars(sdev, &c, sizeof(c));
100a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
101821303f5SDavid Gibson     }
102821303f5SDavid Gibson }
103821303f5SDavid Gibson 
104210b580bSAnthony Liguori static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
105821303f5SDavid Gibson                            uint32_t token, uint32_t nargs, target_ulong args,
106821303f5SDavid Gibson                            uint32_t nret, target_ulong rets)
107821303f5SDavid Gibson {
108821303f5SDavid Gibson     if (nargs != 2 || nret != 1) {
109a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
110821303f5SDavid Gibson         return;
111821303f5SDavid Gibson     }
112821303f5SDavid Gibson     qemu_system_shutdown_request();
113a64d325dSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
114821303f5SDavid Gibson }
115821303f5SDavid Gibson 
116210b580bSAnthony Liguori static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr,
117c821a43cSDavid Gibson                                uint32_t token, uint32_t nargs,
118c821a43cSDavid Gibson                                target_ulong args,
119c821a43cSDavid Gibson                                uint32_t nret, target_ulong rets)
120c821a43cSDavid Gibson {
121c821a43cSDavid Gibson     if (nargs != 0 || nret != 1) {
122a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
123c821a43cSDavid Gibson         return;
124c821a43cSDavid Gibson     }
125c821a43cSDavid Gibson     qemu_system_reset_request();
126a64d325dSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
127c821a43cSDavid Gibson }
128c821a43cSDavid Gibson 
129210b580bSAnthony Liguori static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
130210b580bSAnthony Liguori                                          sPAPREnvironment *spapr,
131a9f8ad8fSDavid Gibson                                          uint32_t token, uint32_t nargs,
132a9f8ad8fSDavid Gibson                                          target_ulong args,
133a9f8ad8fSDavid Gibson                                          uint32_t nret, target_ulong rets)
134a9f8ad8fSDavid Gibson {
135a9f8ad8fSDavid Gibson     target_ulong id;
1360f20ba62SAlexey Kardashevskiy     PowerPCCPU *cpu;
137a9f8ad8fSDavid Gibson 
138a9f8ad8fSDavid Gibson     if (nargs != 1 || nret != 2) {
139a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
140a9f8ad8fSDavid Gibson         return;
141a9f8ad8fSDavid Gibson     }
142a9f8ad8fSDavid Gibson 
143a9f8ad8fSDavid Gibson     id = rtas_ld(args, 0);
1440f20ba62SAlexey Kardashevskiy     cpu = ppc_get_vcpu_by_dt_id(id);
14505318a85SAndreas Färber     if (cpu != NULL) {
1460f20ba62SAlexey Kardashevskiy         if (CPU(cpu)->halted) {
147a9f8ad8fSDavid Gibson             rtas_st(rets, 1, 0);
148a9f8ad8fSDavid Gibson         } else {
149a9f8ad8fSDavid Gibson             rtas_st(rets, 1, 2);
150a9f8ad8fSDavid Gibson         }
151a9f8ad8fSDavid Gibson 
152a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
153a9f8ad8fSDavid Gibson         return;
154a9f8ad8fSDavid Gibson     }
155a9f8ad8fSDavid Gibson 
156a9f8ad8fSDavid Gibson     /* Didn't find a matching cpu */
157a64d325dSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
158a9f8ad8fSDavid Gibson }
159a9f8ad8fSDavid Gibson 
160210b580bSAnthony Liguori static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
161a9f8ad8fSDavid Gibson                            uint32_t token, uint32_t nargs,
162a9f8ad8fSDavid Gibson                            target_ulong args,
163a9f8ad8fSDavid Gibson                            uint32_t nret, target_ulong rets)
164a9f8ad8fSDavid Gibson {
165a9f8ad8fSDavid Gibson     target_ulong id, start, r3;
1660f20ba62SAlexey Kardashevskiy     PowerPCCPU *cpu;
167a9f8ad8fSDavid Gibson 
168a9f8ad8fSDavid Gibson     if (nargs != 3 || nret != 1) {
169a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
170a9f8ad8fSDavid Gibson         return;
171a9f8ad8fSDavid Gibson     }
172a9f8ad8fSDavid Gibson 
173a9f8ad8fSDavid Gibson     id = rtas_ld(args, 0);
174a9f8ad8fSDavid Gibson     start = rtas_ld(args, 1);
175a9f8ad8fSDavid Gibson     r3 = rtas_ld(args, 2);
176a9f8ad8fSDavid Gibson 
1770f20ba62SAlexey Kardashevskiy     cpu = ppc_get_vcpu_by_dt_id(id);
1780f20ba62SAlexey Kardashevskiy     if (cpu != NULL) {
1790f20ba62SAlexey Kardashevskiy         CPUState *cs = CPU(cpu);
180c67e216bSAndreas Färber         CPUPPCState *env = &cpu->env;
181c08d7424SAndreas Färber 
182c67e216bSAndreas Färber         if (!cs->halted) {
183a64d325dSAlexey Kardashevskiy             rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
184a9f8ad8fSDavid Gibson             return;
185a9f8ad8fSDavid Gibson         }
186a9f8ad8fSDavid Gibson 
187048706d9SDavid Gibson         /* This will make sure qemu state is up to date with kvm, and
188048706d9SDavid Gibson          * mark it dirty so our changes get flushed back before the
189048706d9SDavid Gibson          * new cpu enters */
190dd1750d7SAndreas Färber         kvm_cpu_synchronize_state(cs);
191048706d9SDavid Gibson 
192a9f8ad8fSDavid Gibson         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
193a9f8ad8fSDavid Gibson         env->nip = start;
194a9f8ad8fSDavid Gibson         env->gpr[3] = r3;
195c67e216bSAndreas Färber         cs->halted = 0;
196a9f8ad8fSDavid Gibson 
197c67e216bSAndreas Färber         qemu_cpu_kick(cs);
198a9f8ad8fSDavid Gibson 
199a64d325dSAlexey Kardashevskiy         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
200a9f8ad8fSDavid Gibson         return;
201a9f8ad8fSDavid Gibson     }
202a9f8ad8fSDavid Gibson 
203a9f8ad8fSDavid Gibson     /* Didn't find a matching cpu */
204a64d325dSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
205a9f8ad8fSDavid Gibson }
206a9f8ad8fSDavid Gibson 
20759760f2dSAlexey Kardashevskiy static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr,
20859760f2dSAlexey Kardashevskiy                            uint32_t token, uint32_t nargs,
20959760f2dSAlexey Kardashevskiy                            target_ulong args,
21059760f2dSAlexey Kardashevskiy                            uint32_t nret, target_ulong rets)
21159760f2dSAlexey Kardashevskiy {
21259760f2dSAlexey Kardashevskiy     CPUState *cs = CPU(cpu);
21359760f2dSAlexey Kardashevskiy     CPUPPCState *env = &cpu->env;
21459760f2dSAlexey Kardashevskiy 
21559760f2dSAlexey Kardashevskiy     cs->halted = 1;
21659760f2dSAlexey Kardashevskiy     cpu_exit(cs);
21759760f2dSAlexey Kardashevskiy     /*
21859760f2dSAlexey Kardashevskiy      * While stopping a CPU, the guest calls H_CPPR which
21959760f2dSAlexey Kardashevskiy      * effectively disables interrupts on XICS level.
22059760f2dSAlexey Kardashevskiy      * However decrementer interrupts in TCG can still
22159760f2dSAlexey Kardashevskiy      * wake the CPU up so here we disable interrupts in MSR
22259760f2dSAlexey Kardashevskiy      * as well.
22359760f2dSAlexey Kardashevskiy      * As rtas_start_cpu() resets the whole MSR anyway, there is
22459760f2dSAlexey Kardashevskiy      * no need to bother with specific bits, we just clear it.
22559760f2dSAlexey Kardashevskiy      */
22659760f2dSAlexey Kardashevskiy     env->msr = 0;
22759760f2dSAlexey Kardashevskiy }
22859760f2dSAlexey Kardashevskiy 
2293ada6b11SAlexey Kardashevskiy static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
2303ada6b11SAlexey Kardashevskiy                                           sPAPREnvironment *spapr,
2313ada6b11SAlexey Kardashevskiy                                           uint32_t token, uint32_t nargs,
2323ada6b11SAlexey Kardashevskiy                                           target_ulong args,
2333ada6b11SAlexey Kardashevskiy                                           uint32_t nret, target_ulong rets)
2343ada6b11SAlexey Kardashevskiy {
2353ada6b11SAlexey Kardashevskiy     target_ulong parameter = rtas_ld(args, 0);
2363ada6b11SAlexey Kardashevskiy     target_ulong buffer = rtas_ld(args, 1);
2373ada6b11SAlexey Kardashevskiy     target_ulong length = rtas_ld(args, 2);
2383052d951SSam bobroff     target_ulong ret = RTAS_OUT_SUCCESS;
2393ada6b11SAlexey Kardashevskiy 
2403ada6b11SAlexey Kardashevskiy     switch (parameter) {
2413b50d897SSam bobroff     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
2423b50d897SSam bobroff         char *param_val = g_strdup_printf("MaxEntCap=%d,MaxPlatProcs=%d",
2433b50d897SSam bobroff                                           max_cpus, smp_cpus);
2443b50d897SSam bobroff         rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val));
2453b50d897SSam bobroff         g_free(param_val);
2463b50d897SSam bobroff         break;
2473b50d897SSam bobroff     }
2483052d951SSam bobroff     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
2493052d951SSam bobroff         uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
2503052d951SSam bobroff 
2513052d951SSam bobroff         rtas_st_buffer(buffer, length, &param_val, sizeof(param_val));
2523ada6b11SAlexey Kardashevskiy         break;
2533ada6b11SAlexey Kardashevskiy     }
254b907d7b0SSam bobroff     case RTAS_SYSPARM_UUID:
255b907d7b0SSam bobroff         rtas_st_buffer(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0));
256b907d7b0SSam bobroff         break;
2573052d951SSam bobroff     default:
2583052d951SSam bobroff         ret = RTAS_OUT_NOT_SUPPORTED;
2593052d951SSam bobroff     }
2603ada6b11SAlexey Kardashevskiy 
2613ada6b11SAlexey Kardashevskiy     rtas_st(rets, 0, ret);
2623ada6b11SAlexey Kardashevskiy }
2633ada6b11SAlexey Kardashevskiy 
2643ada6b11SAlexey Kardashevskiy static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
2653ada6b11SAlexey Kardashevskiy                                           sPAPREnvironment *spapr,
2663ada6b11SAlexey Kardashevskiy                                           uint32_t token, uint32_t nargs,
2673ada6b11SAlexey Kardashevskiy                                           target_ulong args,
2683ada6b11SAlexey Kardashevskiy                                           uint32_t nret, target_ulong rets)
2693ada6b11SAlexey Kardashevskiy {
2703ada6b11SAlexey Kardashevskiy     target_ulong parameter = rtas_ld(args, 0);
2713ada6b11SAlexey Kardashevskiy     target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
2723ada6b11SAlexey Kardashevskiy 
2733ada6b11SAlexey Kardashevskiy     switch (parameter) {
2743b50d897SSam bobroff     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS:
2753052d951SSam bobroff     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE:
276b907d7b0SSam bobroff     case RTAS_SYSPARM_UUID:
2773ada6b11SAlexey Kardashevskiy         ret = RTAS_OUT_NOT_AUTHORIZED;
2783ada6b11SAlexey Kardashevskiy         break;
2793ada6b11SAlexey Kardashevskiy     }
2803ada6b11SAlexey Kardashevskiy 
2813ada6b11SAlexey Kardashevskiy     rtas_st(rets, 0, ret);
2823ada6b11SAlexey Kardashevskiy }
2833ada6b11SAlexey Kardashevskiy 
2842e14072fSNikunj A Dadhania static void rtas_ibm_os_term(PowerPCCPU *cpu,
2852e14072fSNikunj A Dadhania                             sPAPREnvironment *spapr,
2862e14072fSNikunj A Dadhania                             uint32_t token, uint32_t nargs,
2872e14072fSNikunj A Dadhania                             target_ulong args,
2882e14072fSNikunj A Dadhania                             uint32_t nret, target_ulong rets)
2892e14072fSNikunj A Dadhania {
2902e14072fSNikunj A Dadhania     target_ulong ret = 0;
2912e14072fSNikunj A Dadhania 
2922e14072fSNikunj A Dadhania     qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
2932e14072fSNikunj A Dadhania 
2942e14072fSNikunj A Dadhania     rtas_st(rets, 0, ret);
2952e14072fSNikunj A Dadhania }
2962e14072fSNikunj A Dadhania 
297094d2058SNathan Fontenot static void rtas_set_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr,
298094d2058SNathan Fontenot                                  uint32_t token, uint32_t nargs,
299094d2058SNathan Fontenot                                  target_ulong args, uint32_t nret,
300094d2058SNathan Fontenot                                  target_ulong rets)
301094d2058SNathan Fontenot {
302094d2058SNathan Fontenot     int32_t power_domain;
303094d2058SNathan Fontenot 
304094d2058SNathan Fontenot     if (nargs != 2 || nret != 2) {
305094d2058SNathan Fontenot         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
306094d2058SNathan Fontenot         return;
307094d2058SNathan Fontenot     }
308094d2058SNathan Fontenot 
309094d2058SNathan Fontenot     /* we currently only use a single, "live insert" powerdomain for
310094d2058SNathan Fontenot      * hotplugged/dlpar'd resources, so the power is always live/full (100)
311094d2058SNathan Fontenot      */
312094d2058SNathan Fontenot     power_domain = rtas_ld(args, 0);
313094d2058SNathan Fontenot     if (power_domain != -1) {
314094d2058SNathan Fontenot         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
315094d2058SNathan Fontenot         return;
316094d2058SNathan Fontenot     }
317094d2058SNathan Fontenot 
318094d2058SNathan Fontenot     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
319094d2058SNathan Fontenot     rtas_st(rets, 1, 100);
320094d2058SNathan Fontenot }
321094d2058SNathan Fontenot 
322094d2058SNathan Fontenot static void rtas_get_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr,
323094d2058SNathan Fontenot                                   uint32_t token, uint32_t nargs,
324094d2058SNathan Fontenot                                   target_ulong args, uint32_t nret,
325094d2058SNathan Fontenot                                   target_ulong rets)
326094d2058SNathan Fontenot {
327094d2058SNathan Fontenot     int32_t power_domain;
328094d2058SNathan Fontenot 
329094d2058SNathan Fontenot     if (nargs != 1 || nret != 2) {
330094d2058SNathan Fontenot         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
331094d2058SNathan Fontenot         return;
332094d2058SNathan Fontenot     }
333094d2058SNathan Fontenot 
334094d2058SNathan Fontenot     /* we currently only use a single, "live insert" powerdomain for
335094d2058SNathan Fontenot      * hotplugged/dlpar'd resources, so the power is always live/full (100)
336094d2058SNathan Fontenot      */
337094d2058SNathan Fontenot     power_domain = rtas_ld(args, 0);
338094d2058SNathan Fontenot     if (power_domain != -1) {
339094d2058SNathan Fontenot         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
340094d2058SNathan Fontenot         return;
341094d2058SNathan Fontenot     }
342094d2058SNathan Fontenot 
343094d2058SNathan Fontenot     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
344094d2058SNathan Fontenot     rtas_st(rets, 1, 100);
345094d2058SNathan Fontenot }
346094d2058SNathan Fontenot 
3478c8639dfSMike Day static bool sensor_type_is_dr(uint32_t sensor_type)
3488c8639dfSMike Day {
3498c8639dfSMike Day     switch (sensor_type) {
3508c8639dfSMike Day     case RTAS_SENSOR_TYPE_ISOLATION_STATE:
3518c8639dfSMike Day     case RTAS_SENSOR_TYPE_DR:
3528c8639dfSMike Day     case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
3538c8639dfSMike Day         return true;
3548c8639dfSMike Day     }
3558c8639dfSMike Day 
3568c8639dfSMike Day     return false;
3578c8639dfSMike Day }
3588c8639dfSMike Day 
3598c8639dfSMike Day static void rtas_set_indicator(PowerPCCPU *cpu, sPAPREnvironment *spapr,
3608c8639dfSMike Day                                uint32_t token, uint32_t nargs,
3618c8639dfSMike Day                                target_ulong args, uint32_t nret,
3628c8639dfSMike Day                                target_ulong rets)
3638c8639dfSMike Day {
3648c8639dfSMike Day     uint32_t sensor_type;
3658c8639dfSMike Day     uint32_t sensor_index;
3668c8639dfSMike Day     uint32_t sensor_state;
3678c8639dfSMike Day     sPAPRDRConnector *drc;
3688c8639dfSMike Day     sPAPRDRConnectorClass *drck;
3698c8639dfSMike Day 
3708c8639dfSMike Day     if (nargs != 3 || nret != 1) {
3718c8639dfSMike Day         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
3728c8639dfSMike Day         return;
3738c8639dfSMike Day     }
3748c8639dfSMike Day 
3758c8639dfSMike Day     sensor_type = rtas_ld(args, 0);
3768c8639dfSMike Day     sensor_index = rtas_ld(args, 1);
3778c8639dfSMike Day     sensor_state = rtas_ld(args, 2);
3788c8639dfSMike Day 
3798c8639dfSMike Day     if (!sensor_type_is_dr(sensor_type)) {
3808c8639dfSMike Day         goto out_unimplemented;
3818c8639dfSMike Day     }
3828c8639dfSMike Day 
3838c8639dfSMike Day     /* if this is a DR sensor we can assume sensor_index == drc_index */
3848c8639dfSMike Day     drc = spapr_dr_connector_by_index(sensor_index);
3858c8639dfSMike Day     if (!drc) {
3868c8639dfSMike Day         DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n",
3878c8639dfSMike Day                 sensor_index);
3888c8639dfSMike Day         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
3898c8639dfSMike Day         return;
3908c8639dfSMike Day     }
3918c8639dfSMike Day     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
3928c8639dfSMike Day 
3938c8639dfSMike Day     switch (sensor_type) {
3948c8639dfSMike Day     case RTAS_SENSOR_TYPE_ISOLATION_STATE:
395*46503c2bSMichael Roth         /* if the guest is configuring a device attached to this
396*46503c2bSMichael Roth          * DRC, we should reset the configuration state at this
397*46503c2bSMichael Roth          * point since it may no longer be reliable (guest released
398*46503c2bSMichael Roth          * device and needs to start over, or unplug occurred so
399*46503c2bSMichael Roth          * the FDT is no longer valid)
400*46503c2bSMichael Roth          */
401*46503c2bSMichael Roth         if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
402*46503c2bSMichael Roth             sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr,
403*46503c2bSMichael Roth                                                                sensor_index);
404*46503c2bSMichael Roth             if (ccs) {
405*46503c2bSMichael Roth                 spapr_ccs_remove(spapr, ccs);
406*46503c2bSMichael Roth             }
407*46503c2bSMichael Roth         }
4088c8639dfSMike Day         drck->set_isolation_state(drc, sensor_state);
4098c8639dfSMike Day         break;
4108c8639dfSMike Day     case RTAS_SENSOR_TYPE_DR:
4118c8639dfSMike Day         drck->set_indicator_state(drc, sensor_state);
4128c8639dfSMike Day         break;
4138c8639dfSMike Day     case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
4148c8639dfSMike Day         drck->set_allocation_state(drc, sensor_state);
4158c8639dfSMike Day         break;
4168c8639dfSMike Day     default:
4178c8639dfSMike Day         goto out_unimplemented;
4188c8639dfSMike Day     }
4198c8639dfSMike Day 
4208c8639dfSMike Day     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
4218c8639dfSMike Day     return;
4228c8639dfSMike Day 
4238c8639dfSMike Day out_unimplemented:
4248c8639dfSMike Day     /* currently only DR-related sensors are implemented */
4258c8639dfSMike Day     DPRINTF("rtas_set_indicator: sensor/indicator not implemented: %d\n",
4268c8639dfSMike Day             sensor_type);
4278c8639dfSMike Day     rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
4288c8639dfSMike Day }
4298c8639dfSMike Day 
430886445a6SMike Day static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPREnvironment *spapr,
431886445a6SMike Day                                   uint32_t token, uint32_t nargs,
432886445a6SMike Day                                   target_ulong args, uint32_t nret,
433886445a6SMike Day                                   target_ulong rets)
434886445a6SMike Day {
435886445a6SMike Day     uint32_t sensor_type;
436886445a6SMike Day     uint32_t sensor_index;
437886445a6SMike Day     sPAPRDRConnector *drc;
438886445a6SMike Day     sPAPRDRConnectorClass *drck;
439886445a6SMike Day     uint32_t entity_sense;
440886445a6SMike Day 
441886445a6SMike Day     if (nargs != 2 || nret != 2) {
442886445a6SMike Day         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
443886445a6SMike Day         return;
444886445a6SMike Day     }
445886445a6SMike Day 
446886445a6SMike Day     sensor_type = rtas_ld(args, 0);
447886445a6SMike Day     sensor_index = rtas_ld(args, 1);
448886445a6SMike Day 
449886445a6SMike Day     if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
450886445a6SMike Day         /* currently only DR-related sensors are implemented */
451886445a6SMike Day         DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n",
452886445a6SMike Day                 sensor_type);
453886445a6SMike Day         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
454886445a6SMike Day         return;
455886445a6SMike Day     }
456886445a6SMike Day 
457886445a6SMike Day     drc = spapr_dr_connector_by_index(sensor_index);
458886445a6SMike Day     if (!drc) {
459886445a6SMike Day         DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n",
460886445a6SMike Day                 sensor_index);
461886445a6SMike Day         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
462886445a6SMike Day         return;
463886445a6SMike Day     }
464886445a6SMike Day     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
465886445a6SMike Day     entity_sense = drck->entity_sense(drc);
466886445a6SMike Day 
467886445a6SMike Day     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
468886445a6SMike Day     rtas_st(rets, 1, entity_sense);
469886445a6SMike Day }
470886445a6SMike Day 
471*46503c2bSMichael Roth /* configure-connector work area offsets, int32_t units for field
472*46503c2bSMichael Roth  * indexes, bytes for field offset/len values.
473*46503c2bSMichael Roth  *
474*46503c2bSMichael Roth  * as documented by PAPR+ v2.7, 13.5.3.5
475*46503c2bSMichael Roth  */
476*46503c2bSMichael Roth #define CC_IDX_NODE_NAME_OFFSET 2
477*46503c2bSMichael Roth #define CC_IDX_PROP_NAME_OFFSET 2
478*46503c2bSMichael Roth #define CC_IDX_PROP_LEN 3
479*46503c2bSMichael Roth #define CC_IDX_PROP_DATA_OFFSET 4
480*46503c2bSMichael Roth #define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
481*46503c2bSMichael Roth #define CC_WA_LEN 4096
482*46503c2bSMichael Roth 
483*46503c2bSMichael Roth static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
484*46503c2bSMichael Roth                                          sPAPREnvironment *spapr,
485*46503c2bSMichael Roth                                          uint32_t token, uint32_t nargs,
486*46503c2bSMichael Roth                                          target_ulong args, uint32_t nret,
487*46503c2bSMichael Roth                                          target_ulong rets)
488*46503c2bSMichael Roth {
489*46503c2bSMichael Roth     uint64_t wa_addr;
490*46503c2bSMichael Roth     uint64_t wa_offset;
491*46503c2bSMichael Roth     uint32_t drc_index;
492*46503c2bSMichael Roth     sPAPRDRConnector *drc;
493*46503c2bSMichael Roth     sPAPRDRConnectorClass *drck;
494*46503c2bSMichael Roth     sPAPRConfigureConnectorState *ccs;
495*46503c2bSMichael Roth     sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
496*46503c2bSMichael Roth     int rc;
497*46503c2bSMichael Roth     const void *fdt;
498*46503c2bSMichael Roth 
499*46503c2bSMichael Roth     if (nargs != 2 || nret != 1) {
500*46503c2bSMichael Roth         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
501*46503c2bSMichael Roth         return;
502*46503c2bSMichael Roth     }
503*46503c2bSMichael Roth 
504*46503c2bSMichael Roth     wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
505*46503c2bSMichael Roth 
506*46503c2bSMichael Roth     drc_index = rtas_ld(wa_addr, 0);
507*46503c2bSMichael Roth     drc = spapr_dr_connector_by_index(drc_index);
508*46503c2bSMichael Roth     if (!drc) {
509*46503c2bSMichael Roth         DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n",
510*46503c2bSMichael Roth                 drc_index);
511*46503c2bSMichael Roth         rc = RTAS_OUT_PARAM_ERROR;
512*46503c2bSMichael Roth         goto out;
513*46503c2bSMichael Roth     }
514*46503c2bSMichael Roth 
515*46503c2bSMichael Roth     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
516*46503c2bSMichael Roth     fdt = drck->get_fdt(drc, NULL);
517*46503c2bSMichael Roth 
518*46503c2bSMichael Roth     ccs = spapr_ccs_find(spapr, drc_index);
519*46503c2bSMichael Roth     if (!ccs) {
520*46503c2bSMichael Roth         ccs = g_new0(sPAPRConfigureConnectorState, 1);
521*46503c2bSMichael Roth         (void)drck->get_fdt(drc, &ccs->fdt_offset);
522*46503c2bSMichael Roth         ccs->drc_index = drc_index;
523*46503c2bSMichael Roth         spapr_ccs_add(spapr, ccs);
524*46503c2bSMichael Roth     }
525*46503c2bSMichael Roth 
526*46503c2bSMichael Roth     do {
527*46503c2bSMichael Roth         uint32_t tag;
528*46503c2bSMichael Roth         const char *name;
529*46503c2bSMichael Roth         const struct fdt_property *prop;
530*46503c2bSMichael Roth         int fdt_offset_next, prop_len;
531*46503c2bSMichael Roth 
532*46503c2bSMichael Roth         tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next);
533*46503c2bSMichael Roth 
534*46503c2bSMichael Roth         switch (tag) {
535*46503c2bSMichael Roth         case FDT_BEGIN_NODE:
536*46503c2bSMichael Roth             ccs->fdt_depth++;
537*46503c2bSMichael Roth             name = fdt_get_name(fdt, ccs->fdt_offset, NULL);
538*46503c2bSMichael Roth 
539*46503c2bSMichael Roth             /* provide the name of the next OF node */
540*46503c2bSMichael Roth             wa_offset = CC_VAL_DATA_OFFSET;
541*46503c2bSMichael Roth             rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
542*46503c2bSMichael Roth             rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
543*46503c2bSMichael Roth                                   (uint8_t *)name, strlen(name) + 1);
544*46503c2bSMichael Roth             resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
545*46503c2bSMichael Roth             break;
546*46503c2bSMichael Roth         case FDT_END_NODE:
547*46503c2bSMichael Roth             ccs->fdt_depth--;
548*46503c2bSMichael Roth             if (ccs->fdt_depth == 0) {
549*46503c2bSMichael Roth                 /* done sending the device tree, don't need to track
550*46503c2bSMichael Roth                  * the state anymore
551*46503c2bSMichael Roth                  */
552*46503c2bSMichael Roth                 drck->set_configured(drc);
553*46503c2bSMichael Roth                 spapr_ccs_remove(spapr, ccs);
554*46503c2bSMichael Roth                 ccs = NULL;
555*46503c2bSMichael Roth                 resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
556*46503c2bSMichael Roth             } else {
557*46503c2bSMichael Roth                 resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
558*46503c2bSMichael Roth             }
559*46503c2bSMichael Roth             break;
560*46503c2bSMichael Roth         case FDT_PROP:
561*46503c2bSMichael Roth             prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset,
562*46503c2bSMichael Roth                                               &prop_len);
563*46503c2bSMichael Roth             name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
564*46503c2bSMichael Roth 
565*46503c2bSMichael Roth             /* provide the name of the next OF property */
566*46503c2bSMichael Roth             wa_offset = CC_VAL_DATA_OFFSET;
567*46503c2bSMichael Roth             rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
568*46503c2bSMichael Roth             rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
569*46503c2bSMichael Roth                                   (uint8_t *)name, strlen(name) + 1);
570*46503c2bSMichael Roth 
571*46503c2bSMichael Roth             /* provide the length and value of the OF property. data gets
572*46503c2bSMichael Roth              * placed immediately after NULL terminator of the OF property's
573*46503c2bSMichael Roth              * name string
574*46503c2bSMichael Roth              */
575*46503c2bSMichael Roth             wa_offset += strlen(name) + 1,
576*46503c2bSMichael Roth             rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
577*46503c2bSMichael Roth             rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
578*46503c2bSMichael Roth             rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
579*46503c2bSMichael Roth                                   (uint8_t *)((struct fdt_property *)prop)->data,
580*46503c2bSMichael Roth                                   prop_len);
581*46503c2bSMichael Roth             resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
582*46503c2bSMichael Roth             break;
583*46503c2bSMichael Roth         case FDT_END:
584*46503c2bSMichael Roth             resp = SPAPR_DR_CC_RESPONSE_ERROR;
585*46503c2bSMichael Roth         default:
586*46503c2bSMichael Roth             /* keep seeking for an actionable tag */
587*46503c2bSMichael Roth             break;
588*46503c2bSMichael Roth         }
589*46503c2bSMichael Roth         if (ccs) {
590*46503c2bSMichael Roth             ccs->fdt_offset = fdt_offset_next;
591*46503c2bSMichael Roth         }
592*46503c2bSMichael Roth     } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
593*46503c2bSMichael Roth 
594*46503c2bSMichael Roth     rc = resp;
595*46503c2bSMichael Roth out:
596*46503c2bSMichael Roth     rtas_st(rets, 0, rc);
597*46503c2bSMichael Roth }
598*46503c2bSMichael Roth 
59939ac8455SDavid Gibson static struct rtas_call {
60039ac8455SDavid Gibson     const char *name;
60139ac8455SDavid Gibson     spapr_rtas_fn fn;
6023a3b8502SAlexey Kardashevskiy } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
60339ac8455SDavid Gibson 
604210b580bSAnthony Liguori target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
60539ac8455SDavid Gibson                              uint32_t token, uint32_t nargs, target_ulong args,
60639ac8455SDavid Gibson                              uint32_t nret, target_ulong rets)
60739ac8455SDavid Gibson {
6083a3b8502SAlexey Kardashevskiy     if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
6093a3b8502SAlexey Kardashevskiy         struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
61039ac8455SDavid Gibson 
61139ac8455SDavid Gibson         if (call->fn) {
612210b580bSAnthony Liguori             call->fn(cpu, spapr, token, nargs, args, nret, rets);
61339ac8455SDavid Gibson             return H_SUCCESS;
61439ac8455SDavid Gibson         }
61539ac8455SDavid Gibson     }
61639ac8455SDavid Gibson 
617821303f5SDavid Gibson     /* HACK: Some Linux early debug code uses RTAS display-character,
618821303f5SDavid Gibson      * but assumes the token value is 0xa (which it is on some real
619821303f5SDavid Gibson      * machines) without looking it up in the device tree.  This
620821303f5SDavid Gibson      * special case makes this work */
621821303f5SDavid Gibson     if (token == 0xa) {
622210b580bSAnthony Liguori         rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
623821303f5SDavid Gibson         return H_SUCCESS;
624821303f5SDavid Gibson     }
625821303f5SDavid Gibson 
62639ac8455SDavid Gibson     hcall_dprintf("Unknown RTAS token 0x%x\n", token);
627a64d325dSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
62839ac8455SDavid Gibson     return H_PARAMETER;
62939ac8455SDavid Gibson }
63039ac8455SDavid Gibson 
6313a3b8502SAlexey Kardashevskiy void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
63239ac8455SDavid Gibson {
6333a3b8502SAlexey Kardashevskiy     if (!((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX))) {
6343a3b8502SAlexey Kardashevskiy         fprintf(stderr, "RTAS invalid token 0x%x\n", token);
635c89d5299SDavid Gibson         exit(1);
636c89d5299SDavid Gibson     }
6373a3b8502SAlexey Kardashevskiy 
6383a3b8502SAlexey Kardashevskiy     token -= RTAS_TOKEN_BASE;
6393a3b8502SAlexey Kardashevskiy     if (rtas_table[token].name) {
6403a3b8502SAlexey Kardashevskiy         fprintf(stderr, "RTAS call \"%s\" is registered already as 0x%x\n",
6413a3b8502SAlexey Kardashevskiy                 rtas_table[token].name, token);
6423a3b8502SAlexey Kardashevskiy         exit(1);
643c89d5299SDavid Gibson     }
644c89d5299SDavid Gibson 
6453a3b8502SAlexey Kardashevskiy     rtas_table[token].name = name;
6463a3b8502SAlexey Kardashevskiy     rtas_table[token].fn = fn;
64739ac8455SDavid Gibson }
64839ac8455SDavid Gibson 
649a8170e5eSAvi Kivity int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
650a8170e5eSAvi Kivity                                  hwaddr rtas_size)
65139ac8455SDavid Gibson {
65239ac8455SDavid Gibson     int ret;
65339ac8455SDavid Gibson     int i;
65439ac8455SDavid Gibson 
65539ac8455SDavid Gibson     ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
65639ac8455SDavid Gibson     if (ret < 0) {
65739ac8455SDavid Gibson         fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
65839ac8455SDavid Gibson                 fdt_strerror(ret));
65939ac8455SDavid Gibson         return ret;
66039ac8455SDavid Gibson     }
66139ac8455SDavid Gibson 
6625a4348d1SPeter Crosthwaite     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
66339ac8455SDavid Gibson                                 rtas_addr);
66439ac8455SDavid Gibson     if (ret < 0) {
66539ac8455SDavid Gibson         fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
66639ac8455SDavid Gibson                 fdt_strerror(ret));
66739ac8455SDavid Gibson         return ret;
66839ac8455SDavid Gibson     }
66939ac8455SDavid Gibson 
6705a4348d1SPeter Crosthwaite     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
67139ac8455SDavid Gibson                                 rtas_addr);
67239ac8455SDavid Gibson     if (ret < 0) {
67339ac8455SDavid Gibson         fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
67439ac8455SDavid Gibson                 fdt_strerror(ret));
67539ac8455SDavid Gibson         return ret;
67639ac8455SDavid Gibson     }
67739ac8455SDavid Gibson 
6785a4348d1SPeter Crosthwaite     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
67939ac8455SDavid Gibson                                 rtas_size);
68039ac8455SDavid Gibson     if (ret < 0) {
68139ac8455SDavid Gibson         fprintf(stderr, "Couldn't add rtas-size property: %s\n",
68239ac8455SDavid Gibson                 fdt_strerror(ret));
68339ac8455SDavid Gibson         return ret;
68439ac8455SDavid Gibson     }
68539ac8455SDavid Gibson 
6863a3b8502SAlexey Kardashevskiy     for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
68739ac8455SDavid Gibson         struct rtas_call *call = &rtas_table[i];
68839ac8455SDavid Gibson 
689d36b66f7SBen Herrenschmidt         if (!call->name) {
69039ac8455SDavid Gibson             continue;
69139ac8455SDavid Gibson         }
69239ac8455SDavid Gibson 
6935a4348d1SPeter Crosthwaite         ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
6943a3b8502SAlexey Kardashevskiy                                     i + RTAS_TOKEN_BASE);
69539ac8455SDavid Gibson         if (ret < 0) {
69639ac8455SDavid Gibson             fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
69739ac8455SDavid Gibson                     call->name, fdt_strerror(ret));
69839ac8455SDavid Gibson             return ret;
69939ac8455SDavid Gibson         }
70039ac8455SDavid Gibson 
70139ac8455SDavid Gibson     }
70239ac8455SDavid Gibson     return 0;
70339ac8455SDavid Gibson }
704821303f5SDavid Gibson 
70583f7d43aSAndreas Färber static void core_rtas_register_types(void)
706821303f5SDavid Gibson {
7073a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
7083a3b8502SAlexey Kardashevskiy                         rtas_display_character);
7093a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
7103a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
7113a3b8502SAlexey Kardashevskiy                         rtas_system_reboot);
7123a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
713a9f8ad8fSDavid Gibson                         rtas_query_cpu_stopped_state);
7143a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
7153a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
7163a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
7173a3b8502SAlexey Kardashevskiy                         "ibm,get-system-parameter",
7183ada6b11SAlexey Kardashevskiy                         rtas_ibm_get_system_parameter);
7193a3b8502SAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
7203a3b8502SAlexey Kardashevskiy                         "ibm,set-system-parameter",
7213ada6b11SAlexey Kardashevskiy                         rtas_ibm_set_system_parameter);
7222e14072fSNikunj A Dadhania     spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
7232e14072fSNikunj A Dadhania                         rtas_ibm_os_term);
724094d2058SNathan Fontenot     spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
725094d2058SNathan Fontenot                         rtas_set_power_level);
726094d2058SNathan Fontenot     spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
727094d2058SNathan Fontenot                         rtas_get_power_level);
7288c8639dfSMike Day     spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
7298c8639dfSMike Day                         rtas_set_indicator);
730886445a6SMike Day     spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
731886445a6SMike Day                         rtas_get_sensor_state);
732*46503c2bSMichael Roth     spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
733*46503c2bSMichael Roth                         rtas_ibm_configure_connector);
734821303f5SDavid Gibson }
73583f7d43aSAndreas Färber 
73683f7d43aSAndreas Färber type_init(core_rtas_register_types)
737