master
c 758 lines 24.3 KB
Raw
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
28 #include "qemu/osdep.h"
29 #include "qemu/log.h"
30 #include "qemu/error-report.h"
31 #include "system/system.h"
32 #include "system/device_tree.h"
33 #include "system/cpus.h"
34 #include "system/hw_accel.h"
35 #include "system/physmem.h"
36 #include "system/runstate.h"
37 #include "system/qtest.h"
38 #include "kvm_ppc.h"
39
40 #include "hw/ppc/spapr.h"
41 #include "hw/ppc/spapr_vio.h"
42 #include "hw/ppc/spapr_cpu_core.h"
43 #include "hw/ppc/ppc.h"
44
45 #include <libfdt.h>
46 #include "hw/ppc/spapr_drc.h"
47 #include "qemu/cutils.h"
48 #include "trace.h"
49 #include "hw/ppc/fdt.h"
50 #include "exec/cpu-common.h"
51 #include "target/ppc/mmu-hash64.h"
52 #include "target/ppc/mmu-book3s-v3.h"
53 #include "migration/blocker.h"
54 #include "helper_regs.h"
55
56 uint32_t rtas_ld(target_ulong phys, int n)
57 {
58 return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4 * n));
59 }
60
61 uint64_t rtas_ldq(target_ulong phys, int n)
62 {
63 return (uint64_t)rtas_ld(phys, n) << 32 | rtas_ld(phys, n + 1);
64 }
65
66 void rtas_st(target_ulong phys, int n, uint32_t val)
67 {
68 stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4 * n), val);
69 }
70
71 static void rtas_display_character(PowerPCCPU *cpu, SpaprMachineState *spapr,
72 uint32_t token, uint32_t nargs,
73 target_ulong args,
74 uint32_t nret, target_ulong rets)
75 {
76 uint8_t c = rtas_ld(args, 0);
77 SpaprVioDevice *sdev = vty_lookup(spapr, 0);
78
79 if (!sdev) {
80 rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
81 } else {
82 vty_putchars(sdev, &c, sizeof(c));
83 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
84 }
85 }
86
87 static void rtas_power_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
88 uint32_t token, uint32_t nargs, target_ulong args,
89 uint32_t nret, target_ulong rets)
90 {
91 if (nargs != 2 || nret != 1) {
92 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
93 return;
94 }
95 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
96 cpu_stop_current();
97 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
98 }
99
100 static void rtas_system_reboot(PowerPCCPU *cpu, SpaprMachineState *spapr,
101 uint32_t token, uint32_t nargs,
102 target_ulong args,
103 uint32_t nret, target_ulong rets)
104 {
105 if (nargs != 0 || nret != 1) {
106 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
107 return;
108 }
109 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
110 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
111 }
112
113 static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
114 SpaprMachineState *spapr,
115 uint32_t token, uint32_t nargs,
116 target_ulong args,
117 uint32_t nret, target_ulong rets)
118 {
119 target_ulong id;
120 PowerPCCPU *cpu;
121
122 if (nargs != 1 || nret != 2) {
123 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
124 return;
125 }
126
127 id = rtas_ld(args, 0);
128 cpu = spapr_find_cpu(id);
129 if (cpu != NULL) {
130 CPUPPCState *env = &cpu->env;
131 if (env->quiesced) {
132 rtas_st(rets, 1, 0);
133 } else {
134 rtas_st(rets, 1, 2);
135 }
136
137 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
138 return;
139 }
140
141 /* Didn't find a matching cpu */
142 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
143 }
144
145 static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
146 uint32_t token, uint32_t nargs,
147 target_ulong args,
148 uint32_t nret, target_ulong rets)
149 {
150 target_ulong id, start, r3;
151 PowerPCCPU *newcpu;
152 CPUPPCState *env;
153 target_ulong lpcr;
154 target_ulong caller_lpcr;
155
156 if (nargs != 3 || nret != 1) {
157 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
158 return;
159 }
160
161 id = rtas_ld(args, 0);
162 start = rtas_ld(args, 1);
163 r3 = rtas_ld(args, 2);
164
165 newcpu = spapr_find_cpu(id);
166 if (!newcpu) {
167 /* Didn't find a matching cpu */
168 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
169 return;
170 }
171
172 env = &newcpu->env;
173
174 if (!CPU(newcpu)->halted) {
175 rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
176 return;
177 }
178
179 cpu_synchronize_state(CPU(newcpu));
180
181 env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
182 hreg_compute_hflags(env);
183
184 caller_lpcr = callcpu->env.spr[SPR_LPCR];
185 lpcr = env->spr[SPR_LPCR];
186
187 /* Set ILE the same way */
188 lpcr = (lpcr & ~LPCR_ILE) | (caller_lpcr & LPCR_ILE);
189
190 /* Set AIL the same way */
191 lpcr = (lpcr & ~LPCR_AIL) | (caller_lpcr & LPCR_AIL);
192
193 if (env->mmu_model == POWERPC_MMU_3_00) {
194 /*
195 * New cpus are expected to start in the same radix/hash mode
196 * as the existing CPUs
197 */
198 if (ppc64_v3_radix(callcpu)) {
199 lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
200 } else {
201 lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
202 }
203 env->spr[SPR_PSSCR] &= ~PSSCR_EC;
204 }
205 ppc_store_lpcr(newcpu, lpcr);
206
207 /*
208 * Set the timebase offset of the new CPU to that of the invoking
209 * CPU. This helps hotplugged CPU to have the correct timebase
210 * offset.
211 */
212 newcpu->env.tb_env->tb_offset = callcpu->env.tb_env->tb_offset;
213
214 spapr_cpu_set_entry_state(newcpu, start, 0, r3, 0);
215
216 qemu_cpu_kick(CPU(newcpu));
217
218 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
219 }
220
221 static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
222 uint32_t token, uint32_t nargs,
223 target_ulong args,
224 uint32_t nret, target_ulong rets)
225 {
226 CPUState *cs = CPU(cpu);
227 CPUPPCState *env = &cpu->env;
228 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
229
230 /* Disable Power-saving mode Exit Cause exceptions for the CPU.
231 * This could deliver an interrupt on a dying CPU and crash the
232 * guest.
233 * For the same reason, set PSSCR_EC.
234 */
235 env->spr[SPR_PSSCR] |= PSSCR_EC;
236 env->quiesced = true; /* set "RTAS stopped" state. */
237 ppc_maybe_interrupt(env);
238 cs->halted = 1;
239 ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
240 kvmppc_set_reg_ppc_online(cpu, 0);
241 cpu_exit(cs);
242 }
243
244 static void rtas_ibm_suspend_me(PowerPCCPU *cpu, SpaprMachineState *spapr,
245 uint32_t token, uint32_t nargs,
246 target_ulong args,
247 uint32_t nret, target_ulong rets)
248 {
249 CPUState *cs;
250
251 if (nargs != 0 || nret != 1) {
252 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
253 return;
254 }
255
256 CPU_FOREACH(cs) {
257 PowerPCCPU *c = POWERPC_CPU(cs);
258 CPUPPCState *e = &c->env;
259 if (c == cpu) {
260 continue;
261 }
262
263 /* See h_join */
264 if (!cs->halted || (e->msr & (1ULL << MSR_EE))) {
265 rtas_st(rets, 0, H_MULTI_THREADS_ACTIVE);
266 return;
267 }
268 }
269
270 qemu_system_suspend_request();
271 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
272 }
273
274 static inline int sysparm_st(target_ulong addr, target_ulong len,
275 const void *val, uint16_t vallen)
276 {
277 hwaddr phys = ppc64_phys_to_real(addr);
278
279 if (len < 2) {
280 return RTAS_OUT_SYSPARM_PARAM_ERROR;
281 }
282 stw_be_phys(&address_space_memory, phys, vallen);
283 physical_memory_write(phys + 2, val, MIN(len - 2, vallen));
284 return RTAS_OUT_SUCCESS;
285 }
286
287 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
288 SpaprMachineState *spapr,
289 uint32_t token, uint32_t nargs,
290 target_ulong args,
291 uint32_t nret, target_ulong rets)
292 {
293 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
294 MachineState *ms = MACHINE(spapr);
295 target_ulong parameter = rtas_ld(args, 0);
296 target_ulong buffer = rtas_ld(args, 1);
297 target_ulong length = rtas_ld(args, 2);
298 target_ulong ret;
299
300 switch (parameter) {
301 case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
302 g_autofree char *param_val = g_strdup_printf("MaxEntCap=%d,"
303 "DesMem=%" PRIu64 ","
304 "DesProcs=%d,"
305 "MaxPlatProcs=%d",
306 ms->smp.max_cpus,
307 ms->ram_size / MiB,
308 ms->smp.cpus,
309 ms->smp.max_cpus);
310 if (pcc->n_host_threads > 0) {
311 /*
312 * Add HostThrs property. This property is not present in PAPR but
313 * is expected by some guests to communicate the number of physical
314 * host threads per core on the system so that they can scale
315 * information which varies based on the thread configuration.
316 */
317 g_autofree char *hostthr_val = g_strdup_printf(",HostThrs=%d",
318 pcc->n_host_threads);
319 char *old = param_val;
320
321 param_val = g_strconcat(param_val, hostthr_val, NULL);
322 g_free(old);
323 }
324 ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
325 break;
326 }
327 case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
328 uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
329
330 ret = sysparm_st(buffer, length, &param_val, sizeof(param_val));
331 break;
332 }
333 case RTAS_SYSPARM_UUID:
334 ret = sysparm_st(buffer, length, (unsigned char *)&qemu_uuid,
335 (qemu_uuid_set ? 16 : 0));
336 break;
337 default:
338 ret = RTAS_OUT_NOT_SUPPORTED;
339 }
340
341 rtas_st(rets, 0, ret);
342 }
343
344 static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
345 SpaprMachineState *spapr,
346 uint32_t token, uint32_t nargs,
347 target_ulong args,
348 uint32_t nret, target_ulong rets)
349 {
350 target_ulong parameter = rtas_ld(args, 0);
351 target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
352
353 switch (parameter) {
354 case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS:
355 case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE:
356 case RTAS_SYSPARM_UUID:
357 ret = RTAS_OUT_NOT_AUTHORIZED;
358 break;
359 }
360
361 rtas_st(rets, 0, ret);
362 }
363
364 /* Papr Section 7.4.9 ibm,configure-kernel-dump RTAS call */
365 static void rtas_configure_kernel_dump(PowerPCCPU *cpu,
366 SpaprMachineState *spapr,
367 uint32_t token, uint32_t nargs,
368 target_ulong args,
369 uint32_t nret, target_ulong rets)
370 {
371 target_ulong cmd = rtas_ld(args, 0);
372 uint32_t ret_val;
373
374 /* Number of outputs has to be 1 */
375 if (nret != 1) {
376 qemu_log_mask(LOG_GUEST_ERROR,
377 "FADump: ibm,configure-kernel-dump called with nret != 1.\n");
378 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
379 return;
380 }
381
382 /* Number of inputs has to be 3 */
383 if (nargs != 3) {
384 qemu_log_mask(LOG_GUEST_ERROR,
385 "FADump: ibm,configure-kernel-dump called with nargs != 3.\n");
386 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
387 return;
388 }
389
390 switch (cmd) {
391 case FADUMP_CMD_REGISTER:
392 ret_val = do_fadump_register(spapr, args);
393 if (ret_val != RTAS_OUT_SUCCESS) {
394 rtas_st(rets, 0, ret_val);
395 return;
396 }
397 break;
398 case FADUMP_CMD_UNREGISTER:
399 if (spapr->fadump_dump_active) {
400 rtas_st(rets, 0, RTAS_OUT_DUMP_ACTIVE);
401 return;
402 }
403
404 spapr->fadump_registered = false;
405 spapr->fadump_dump_active = false;
406 memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
407 break;
408 case FADUMP_CMD_INVALIDATE:
409 if (!spapr->fadump_dump_active) {
410 qemu_log_mask(LOG_GUEST_ERROR,
411 "FADump: Nothing to invalidate, no dump active\n");
412
413 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
414 }
415
416 spapr->fadump_registered = false;
417 spapr->fadump_dump_active = false;
418 memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
419 break;
420 default:
421 qemu_log_mask(LOG_GUEST_ERROR,
422 "FADump: Unknown command: " TARGET_FMT_lu "\n", cmd);
423
424 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
425 return;
426 }
427
428 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
429 }
430
431 static void rtas_ibm_os_term(PowerPCCPU *cpu,
432 SpaprMachineState *spapr,
433 uint32_t token, uint32_t nargs,
434 target_ulong args,
435 uint32_t nret, target_ulong rets)
436 {
437 target_ulong msgaddr = rtas_ld(args, 0);
438 char msg[512];
439
440 if (spapr->fadump_registered) {
441 /* If fadump boot works, control won't come back here */
442 return trigger_fadump_boot(spapr, rets);
443 }
444
445 physical_memory_read(msgaddr, msg, sizeof(msg) - 1);
446 msg[sizeof(msg) - 1] = 0;
447
448 error_report("OS terminated: %s", msg);
449 qemu_system_guest_panicked(NULL);
450
451 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
452 }
453
454 static void rtas_set_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
455 uint32_t token, uint32_t nargs,
456 target_ulong args, uint32_t nret,
457 target_ulong rets)
458 {
459 int32_t power_domain;
460
461 if (nargs != 2 || nret != 2) {
462 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
463 return;
464 }
465
466 /* we currently only use a single, "live insert" powerdomain for
467 * hotplugged/dlpar'd resources, so the power is always live/full (100)
468 */
469 power_domain = rtas_ld(args, 0);
470 if (power_domain != -1) {
471 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
472 return;
473 }
474
475 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
476 rtas_st(rets, 1, 100);
477 }
478
479 static void rtas_get_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
480 uint32_t token, uint32_t nargs,
481 target_ulong args, uint32_t nret,
482 target_ulong rets)
483 {
484 int32_t power_domain;
485
486 if (nargs != 1 || nret != 2) {
487 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
488 return;
489 }
490
491 /* we currently only use a single, "live insert" powerdomain for
492 * hotplugged/dlpar'd resources, so the power is always live/full (100)
493 */
494 power_domain = rtas_ld(args, 0);
495 if (power_domain != -1) {
496 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
497 return;
498 }
499
500 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
501 rtas_st(rets, 1, 100);
502 }
503
504 static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
505 SpaprMachineState *spapr,
506 uint32_t token, uint32_t nargs,
507 target_ulong args,
508 uint32_t nret, target_ulong rets)
509 {
510 hwaddr rtas_addr;
511 target_ulong sreset_addr, mce_addr;
512
513 if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
514 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
515 return;
516 }
517
518 rtas_addr = spapr_get_rtas_addr();
519 if (!rtas_addr) {
520 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
521 return;
522 }
523
524 sreset_addr = rtas_ld(args, 0);
525 mce_addr = rtas_ld(args, 1);
526
527 /* PAPR requires these are in the first 32M of memory and within RMA */
528 if (sreset_addr >= 32 * MiB || sreset_addr >= spapr->rma_size ||
529 mce_addr >= 32 * MiB || mce_addr >= spapr->rma_size) {
530 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
531 return;
532 }
533
534 if (kvm_enabled()) {
535 if (kvmppc_set_fwnmi(cpu) < 0) {
536 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
537 return;
538 }
539 }
540
541 spapr->fwnmi_system_reset_addr = sreset_addr;
542 spapr->fwnmi_machine_check_addr = mce_addr;
543
544 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
545 }
546
547 static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
548 SpaprMachineState *spapr,
549 uint32_t token, uint32_t nargs,
550 target_ulong args,
551 uint32_t nret, target_ulong rets)
552 {
553 if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
554 rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
555 return;
556 }
557
558 if (spapr->fwnmi_machine_check_addr == -1) {
559 qemu_log_mask(LOG_GUEST_ERROR,
560 "FWNMI: ibm,nmi-interlock RTAS called with FWNMI not registered.\n");
561
562 /* NMI register not called */
563 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
564 return;
565 }
566
567 if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) {
568 /*
569 * The vCPU that hit the NMI should invoke "ibm,nmi-interlock"
570 * This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock"
571 * for system reset interrupts, despite them not being interlocked.
572 * PowerVM silently ignores this and returns success here. Returning
573 * failure causes Linux to print the error "FWNMI: nmi-interlock
574 * failed: -3", although no other apparent ill effects, this is a
575 * regression for the user when enabling FWNMI. So for now, match
576 * PowerVM. When most Linux clients are fixed, this could be
577 * changed.
578 */
579 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
580 return;
581 }
582
583 /*
584 * vCPU issuing "ibm,nmi-interlock" is done with NMI handling,
585 * hence unset fwnmi_machine_check_interlock.
586 */
587 spapr->fwnmi_machine_check_interlock = -1;
588 qemu_cond_signal(&spapr->fwnmi_machine_check_interlock_cond);
589 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
590 migrate_del_blocker(&spapr->fwnmi_migration_blocker);
591 }
592
593 static struct rtas_call {
594 const char *name;
595 spapr_rtas_fn fn;
596 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
597
598 target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *spapr,
599 uint32_t token, uint32_t nargs, target_ulong args,
600 uint32_t nret, target_ulong rets)
601 {
602 if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
603 struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
604
605 if (call->fn) {
606 call->fn(cpu, spapr, token, nargs, args, nret, rets);
607 return H_SUCCESS;
608 }
609 }
610
611 /* HACK: Some Linux early debug code uses RTAS display-character,
612 * but assumes the token value is 0xa (which it is on some real
613 * machines) without looking it up in the device tree. This
614 * special case makes this work */
615 if (token == 0xa) {
616 rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
617 return H_SUCCESS;
618 }
619
620 hcall_dprintf("Unknown RTAS token 0x%x\n", token);
621 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
622 return H_PARAMETER;
623 }
624
625 static uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
626 uint32_t nret, uint64_t rets)
627 {
628 int token;
629
630 for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) {
631 if (strcmp(cmd, rtas_table[token].name) == 0) {
632 SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
633 PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
634
635 rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE,
636 nargs, args, nret, rets);
637 return H_SUCCESS;
638 }
639 }
640 return H_PARAMETER;
641 }
642
643 static bool spapr_qtest_callback(CharFrontend *chr, gchar **words)
644 {
645 if (strcmp(words[0], "rtas") == 0) {
646 uint64_t res, args, ret;
647 unsigned long nargs, nret;
648 int rc;
649
650 rc = qemu_strtoul(words[2], NULL, 0, &nargs);
651 g_assert(rc == 0);
652 rc = qemu_strtou64(words[3], NULL, 0, &args);
653 g_assert(rc == 0);
654 rc = qemu_strtoul(words[4], NULL, 0, &nret);
655 g_assert(rc == 0);
656 rc = qemu_strtou64(words[5], NULL, 0, &ret);
657 g_assert(rc == 0);
658 res = qtest_rtas_call(words[1], nargs, args, nret, ret);
659
660 qtest_sendf(chr, "OK %"PRIu64"\n", res);
661
662 return true;
663 }
664
665 return false;
666 }
667
668 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
669 {
670 assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
671
672 token -= RTAS_TOKEN_BASE;
673
674 assert(!name || !rtas_table[token].name);
675
676 rtas_table[token].name = name;
677 rtas_table[token].fn = fn;
678 }
679
680 void spapr_dt_rtas_tokens(void *fdt, int rtas)
681 {
682 int i;
683
684 for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
685 struct rtas_call *call = &rtas_table[i];
686
687 if (!call->name) {
688 continue;
689 }
690
691 _FDT(fdt_setprop_cell(fdt, rtas, call->name, i + RTAS_TOKEN_BASE));
692 }
693 }
694
695 hwaddr spapr_get_rtas_addr(void)
696 {
697 SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
698 int rtas_node;
699 const fdt32_t *rtas_data;
700 void *fdt = spapr->fdt_blob;
701
702 /* fetch rtas addr from fdt */
703 rtas_node = fdt_path_offset(fdt, "/rtas");
704 if (rtas_node < 0) {
705 return 0;
706 }
707
708 rtas_data = fdt_getprop(fdt, rtas_node, "linux,rtas-base", NULL);
709 if (!rtas_data) {
710 return 0;
711 }
712
713 /*
714 * We assume that the OS called RTAS instantiate-rtas, but some other
715 * OS might call RTAS instantiate-rtas-64 instead. This fine as of now
716 * as SLOF only supports 32-bit variant.
717 */
718 return (hwaddr)fdt32_to_cpu(*rtas_data);
719 }
720
721 static void core_rtas_register_types(void)
722 {
723 spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
724 rtas_display_character);
725 spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
726 spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
727 rtas_system_reboot);
728 spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
729 rtas_query_cpu_stopped_state);
730 spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
731 spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
732 spapr_rtas_register(RTAS_IBM_SUSPEND_ME, "ibm,suspend-me",
733 rtas_ibm_suspend_me);
734 spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
735 "ibm,get-system-parameter",
736 rtas_ibm_get_system_parameter);
737 spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
738 "ibm,set-system-parameter",
739 rtas_ibm_set_system_parameter);
740 spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
741 rtas_ibm_os_term);
742 spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
743 rtas_set_power_level);
744 spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
745 rtas_get_power_level);
746 spapr_rtas_register(RTAS_IBM_NMI_REGISTER, "ibm,nmi-register",
747 rtas_ibm_nmi_register);
748 spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
749 rtas_ibm_nmi_interlock);
750
751 /* Register fadump rtas call */
752 spapr_rtas_register(RTAS_CONFIGURE_KERNEL_DUMP, "ibm,configure-kernel-dump",
753 rtas_configure_kernel_dump);
754
755 qtest_set_command_cb(spapr_qtest_callback);
756 }
757
758 type_init(core_rtas_register_types)