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