xref: /qemu/hw/ppc/spapr_rtas.c (revision 886445a6ee808ee06533f9ecdf0f169c9ea83fbb)
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 "cpu.h"
28 #include "sysemu/sysemu.h"
29 #include "sysemu/char.h"
30 #include "hw/qdev.h"
31 #include "sysemu/device_tree.h"
32 
33 #include "hw/ppc/spapr.h"
34 #include "hw/ppc/spapr_vio.h"
35 #include "qapi-event.h"
36 
37 #include <libfdt.h>
38 #include "hw/ppc/spapr_drc.h"
39 
40 /* #define DEBUG_SPAPR */
41 
42 #ifdef DEBUG_SPAPR
43 #define DPRINTF(fmt, ...) \
44     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
45 #else
46 #define DPRINTF(fmt, ...) \
47     do { } while (0)
48 #endif
49 
50 
51 static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
52                                    uint32_t token, uint32_t nargs,
53                                    target_ulong args,
54                                    uint32_t nret, target_ulong rets)
55 {
56     uint8_t c = rtas_ld(args, 0);
57     VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
58 
59     if (!sdev) {
60         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
61     } else {
62         vty_putchars(sdev, &c, sizeof(c));
63         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
64     }
65 }
66 
67 static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
68                            uint32_t token, uint32_t nargs, target_ulong args,
69                            uint32_t nret, target_ulong rets)
70 {
71     if (nargs != 2 || nret != 1) {
72         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
73         return;
74     }
75     qemu_system_shutdown_request();
76     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
77 }
78 
79 static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr,
80                                uint32_t token, uint32_t nargs,
81                                target_ulong args,
82                                uint32_t nret, target_ulong rets)
83 {
84     if (nargs != 0 || nret != 1) {
85         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
86         return;
87     }
88     qemu_system_reset_request();
89     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
90 }
91 
92 static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
93                                          sPAPREnvironment *spapr,
94                                          uint32_t token, uint32_t nargs,
95                                          target_ulong args,
96                                          uint32_t nret, target_ulong rets)
97 {
98     target_ulong id;
99     PowerPCCPU *cpu;
100 
101     if (nargs != 1 || nret != 2) {
102         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
103         return;
104     }
105 
106     id = rtas_ld(args, 0);
107     cpu = ppc_get_vcpu_by_dt_id(id);
108     if (cpu != NULL) {
109         if (CPU(cpu)->halted) {
110             rtas_st(rets, 1, 0);
111         } else {
112             rtas_st(rets, 1, 2);
113         }
114 
115         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
116         return;
117     }
118 
119     /* Didn't find a matching cpu */
120     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
121 }
122 
123 static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
124                            uint32_t token, uint32_t nargs,
125                            target_ulong args,
126                            uint32_t nret, target_ulong rets)
127 {
128     target_ulong id, start, r3;
129     PowerPCCPU *cpu;
130 
131     if (nargs != 3 || nret != 1) {
132         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
133         return;
134     }
135 
136     id = rtas_ld(args, 0);
137     start = rtas_ld(args, 1);
138     r3 = rtas_ld(args, 2);
139 
140     cpu = ppc_get_vcpu_by_dt_id(id);
141     if (cpu != NULL) {
142         CPUState *cs = CPU(cpu);
143         CPUPPCState *env = &cpu->env;
144 
145         if (!cs->halted) {
146             rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
147             return;
148         }
149 
150         /* This will make sure qemu state is up to date with kvm, and
151          * mark it dirty so our changes get flushed back before the
152          * new cpu enters */
153         kvm_cpu_synchronize_state(cs);
154 
155         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
156         env->nip = start;
157         env->gpr[3] = r3;
158         cs->halted = 0;
159 
160         qemu_cpu_kick(cs);
161 
162         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
163         return;
164     }
165 
166     /* Didn't find a matching cpu */
167     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
168 }
169 
170 static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr,
171                            uint32_t token, uint32_t nargs,
172                            target_ulong args,
173                            uint32_t nret, target_ulong rets)
174 {
175     CPUState *cs = CPU(cpu);
176     CPUPPCState *env = &cpu->env;
177 
178     cs->halted = 1;
179     cpu_exit(cs);
180     /*
181      * While stopping a CPU, the guest calls H_CPPR which
182      * effectively disables interrupts on XICS level.
183      * However decrementer interrupts in TCG can still
184      * wake the CPU up so here we disable interrupts in MSR
185      * as well.
186      * As rtas_start_cpu() resets the whole MSR anyway, there is
187      * no need to bother with specific bits, we just clear it.
188      */
189     env->msr = 0;
190 }
191 
192 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
193                                           sPAPREnvironment *spapr,
194                                           uint32_t token, uint32_t nargs,
195                                           target_ulong args,
196                                           uint32_t nret, target_ulong rets)
197 {
198     target_ulong parameter = rtas_ld(args, 0);
199     target_ulong buffer = rtas_ld(args, 1);
200     target_ulong length = rtas_ld(args, 2);
201     target_ulong ret = RTAS_OUT_SUCCESS;
202 
203     switch (parameter) {
204     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
205         char *param_val = g_strdup_printf("MaxEntCap=%d,MaxPlatProcs=%d",
206                                           max_cpus, smp_cpus);
207         rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val));
208         g_free(param_val);
209         break;
210     }
211     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
212         uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
213 
214         rtas_st_buffer(buffer, length, &param_val, sizeof(param_val));
215         break;
216     }
217     case RTAS_SYSPARM_UUID:
218         rtas_st_buffer(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0));
219         break;
220     default:
221         ret = RTAS_OUT_NOT_SUPPORTED;
222     }
223 
224     rtas_st(rets, 0, ret);
225 }
226 
227 static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
228                                           sPAPREnvironment *spapr,
229                                           uint32_t token, uint32_t nargs,
230                                           target_ulong args,
231                                           uint32_t nret, target_ulong rets)
232 {
233     target_ulong parameter = rtas_ld(args, 0);
234     target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
235 
236     switch (parameter) {
237     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS:
238     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE:
239     case RTAS_SYSPARM_UUID:
240         ret = RTAS_OUT_NOT_AUTHORIZED;
241         break;
242     }
243 
244     rtas_st(rets, 0, ret);
245 }
246 
247 static void rtas_ibm_os_term(PowerPCCPU *cpu,
248                             sPAPREnvironment *spapr,
249                             uint32_t token, uint32_t nargs,
250                             target_ulong args,
251                             uint32_t nret, target_ulong rets)
252 {
253     target_ulong ret = 0;
254 
255     qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
256 
257     rtas_st(rets, 0, ret);
258 }
259 
260 static void rtas_set_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr,
261                                  uint32_t token, uint32_t nargs,
262                                  target_ulong args, uint32_t nret,
263                                  target_ulong rets)
264 {
265     int32_t power_domain;
266 
267     if (nargs != 2 || nret != 2) {
268         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
269         return;
270     }
271 
272     /* we currently only use a single, "live insert" powerdomain for
273      * hotplugged/dlpar'd resources, so the power is always live/full (100)
274      */
275     power_domain = rtas_ld(args, 0);
276     if (power_domain != -1) {
277         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
278         return;
279     }
280 
281     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
282     rtas_st(rets, 1, 100);
283 }
284 
285 static void rtas_get_power_level(PowerPCCPU *cpu, sPAPREnvironment *spapr,
286                                   uint32_t token, uint32_t nargs,
287                                   target_ulong args, uint32_t nret,
288                                   target_ulong rets)
289 {
290     int32_t power_domain;
291 
292     if (nargs != 1 || nret != 2) {
293         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
294         return;
295     }
296 
297     /* we currently only use a single, "live insert" powerdomain for
298      * hotplugged/dlpar'd resources, so the power is always live/full (100)
299      */
300     power_domain = rtas_ld(args, 0);
301     if (power_domain != -1) {
302         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
303         return;
304     }
305 
306     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
307     rtas_st(rets, 1, 100);
308 }
309 
310 static bool sensor_type_is_dr(uint32_t sensor_type)
311 {
312     switch (sensor_type) {
313     case RTAS_SENSOR_TYPE_ISOLATION_STATE:
314     case RTAS_SENSOR_TYPE_DR:
315     case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
316         return true;
317     }
318 
319     return false;
320 }
321 
322 static void rtas_set_indicator(PowerPCCPU *cpu, sPAPREnvironment *spapr,
323                                uint32_t token, uint32_t nargs,
324                                target_ulong args, uint32_t nret,
325                                target_ulong rets)
326 {
327     uint32_t sensor_type;
328     uint32_t sensor_index;
329     uint32_t sensor_state;
330     sPAPRDRConnector *drc;
331     sPAPRDRConnectorClass *drck;
332 
333     if (nargs != 3 || nret != 1) {
334         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
335         return;
336     }
337 
338     sensor_type = rtas_ld(args, 0);
339     sensor_index = rtas_ld(args, 1);
340     sensor_state = rtas_ld(args, 2);
341 
342     if (!sensor_type_is_dr(sensor_type)) {
343         goto out_unimplemented;
344     }
345 
346     /* if this is a DR sensor we can assume sensor_index == drc_index */
347     drc = spapr_dr_connector_by_index(sensor_index);
348     if (!drc) {
349         DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n",
350                 sensor_index);
351         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
352         return;
353     }
354     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
355 
356     switch (sensor_type) {
357     case RTAS_SENSOR_TYPE_ISOLATION_STATE:
358         drck->set_isolation_state(drc, sensor_state);
359         break;
360     case RTAS_SENSOR_TYPE_DR:
361         drck->set_indicator_state(drc, sensor_state);
362         break;
363     case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
364         drck->set_allocation_state(drc, sensor_state);
365         break;
366     default:
367         goto out_unimplemented;
368     }
369 
370     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
371     return;
372 
373 out_unimplemented:
374     /* currently only DR-related sensors are implemented */
375     DPRINTF("rtas_set_indicator: sensor/indicator not implemented: %d\n",
376             sensor_type);
377     rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
378 }
379 
380 static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPREnvironment *spapr,
381                                   uint32_t token, uint32_t nargs,
382                                   target_ulong args, uint32_t nret,
383                                   target_ulong rets)
384 {
385     uint32_t sensor_type;
386     uint32_t sensor_index;
387     sPAPRDRConnector *drc;
388     sPAPRDRConnectorClass *drck;
389     uint32_t entity_sense;
390 
391     if (nargs != 2 || nret != 2) {
392         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
393         return;
394     }
395 
396     sensor_type = rtas_ld(args, 0);
397     sensor_index = rtas_ld(args, 1);
398 
399     if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
400         /* currently only DR-related sensors are implemented */
401         DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n",
402                 sensor_type);
403         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
404         return;
405     }
406 
407     drc = spapr_dr_connector_by_index(sensor_index);
408     if (!drc) {
409         DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n",
410                 sensor_index);
411         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
412         return;
413     }
414     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
415     entity_sense = drck->entity_sense(drc);
416 
417     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
418     rtas_st(rets, 1, entity_sense);
419 }
420 
421 static struct rtas_call {
422     const char *name;
423     spapr_rtas_fn fn;
424 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
425 
426 target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
427                              uint32_t token, uint32_t nargs, target_ulong args,
428                              uint32_t nret, target_ulong rets)
429 {
430     if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
431         struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
432 
433         if (call->fn) {
434             call->fn(cpu, spapr, token, nargs, args, nret, rets);
435             return H_SUCCESS;
436         }
437     }
438 
439     /* HACK: Some Linux early debug code uses RTAS display-character,
440      * but assumes the token value is 0xa (which it is on some real
441      * machines) without looking it up in the device tree.  This
442      * special case makes this work */
443     if (token == 0xa) {
444         rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
445         return H_SUCCESS;
446     }
447 
448     hcall_dprintf("Unknown RTAS token 0x%x\n", token);
449     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
450     return H_PARAMETER;
451 }
452 
453 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
454 {
455     if (!((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX))) {
456         fprintf(stderr, "RTAS invalid token 0x%x\n", token);
457         exit(1);
458     }
459 
460     token -= RTAS_TOKEN_BASE;
461     if (rtas_table[token].name) {
462         fprintf(stderr, "RTAS call \"%s\" is registered already as 0x%x\n",
463                 rtas_table[token].name, token);
464         exit(1);
465     }
466 
467     rtas_table[token].name = name;
468     rtas_table[token].fn = fn;
469 }
470 
471 int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
472                                  hwaddr rtas_size)
473 {
474     int ret;
475     int i;
476 
477     ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
478     if (ret < 0) {
479         fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
480                 fdt_strerror(ret));
481         return ret;
482     }
483 
484     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
485                                 rtas_addr);
486     if (ret < 0) {
487         fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
488                 fdt_strerror(ret));
489         return ret;
490     }
491 
492     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
493                                 rtas_addr);
494     if (ret < 0) {
495         fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
496                 fdt_strerror(ret));
497         return ret;
498     }
499 
500     ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
501                                 rtas_size);
502     if (ret < 0) {
503         fprintf(stderr, "Couldn't add rtas-size property: %s\n",
504                 fdt_strerror(ret));
505         return ret;
506     }
507 
508     for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
509         struct rtas_call *call = &rtas_table[i];
510 
511         if (!call->name) {
512             continue;
513         }
514 
515         ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
516                                     i + RTAS_TOKEN_BASE);
517         if (ret < 0) {
518             fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
519                     call->name, fdt_strerror(ret));
520             return ret;
521         }
522 
523     }
524     return 0;
525 }
526 
527 static void core_rtas_register_types(void)
528 {
529     spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
530                         rtas_display_character);
531     spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
532     spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
533                         rtas_system_reboot);
534     spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
535                         rtas_query_cpu_stopped_state);
536     spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
537     spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
538     spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
539                         "ibm,get-system-parameter",
540                         rtas_ibm_get_system_parameter);
541     spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
542                         "ibm,set-system-parameter",
543                         rtas_ibm_set_system_parameter);
544     spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
545                         rtas_ibm_os_term);
546     spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
547                         rtas_set_power_level);
548     spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
549                         rtas_get_power_level);
550     spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
551                         rtas_set_indicator);
552     spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
553                         rtas_get_sensor_state);
554 }
555 
556 type_init(core_rtas_register_types)
557