]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/ppc/cpu_loop.c
linux-user: Split signal-related prototypes into signal-common.h
[mirror_qemu.git] / linux-user / ppc / cpu_loop.c
CommitLineData
cd71c089
LV
1/*
2 * qemu user cpu loop
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "qemu/osdep.h"
a8d25326 21#include "qemu-common.h"
cd71c089
LV
22#include "qemu.h"
23#include "cpu_loop-common.h"
2113aed6 24#include "signal-common.h"
cd71c089 25
11400516
LV
26static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
27{
28 return cpu_get_host_ticks();
29}
30
31uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
32{
33 return cpu_ppc_get_tb(env);
34}
35
36uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
37{
38 return cpu_ppc_get_tb(env) >> 32;
39}
40
41uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
42{
43 return cpu_ppc_get_tb(env);
44}
45
46uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
47{
48 return cpu_ppc_get_tb(env) >> 32;
49}
50
5d62725b
SJS
51uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
52{
53 return cpu_ppc_get_tb(env);
54}
55
11400516
LV
56uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
57__attribute__ (( alias ("cpu_ppc_load_tbu") ));
58
59uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
60{
61 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
62}
63
64/* XXX: to be fixed */
65int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
66{
67 return -1;
68}
69
70int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
71{
72 return -1;
73}
74
11400516
LV
75void cpu_loop(CPUPPCState *env)
76{
db70b311 77 CPUState *cs = env_cpu(env);
11400516 78 target_siginfo_t info;
b10089a1 79 int trapnr;
11400516
LV
80 target_ulong ret;
81
82 for(;;) {
14db1899
RH
83 bool arch_interrupt;
84
11400516
LV
85 cpu_exec_start(cs);
86 trapnr = cpu_exec(cs);
87 cpu_exec_end(cs);
88 process_queued_cpu_work(cs);
89
14db1899
RH
90 arch_interrupt = true;
91 switch (trapnr) {
11400516
LV
92 case POWERPC_EXCP_NONE:
93 /* Just go on */
94 break;
95 case POWERPC_EXCP_CRITICAL: /* Critical input */
96 cpu_abort(cs, "Critical interrupt while in user mode. "
97 "Aborting\n");
98 break;
99 case POWERPC_EXCP_MCHECK: /* Machine check exception */
100 cpu_abort(cs, "Machine check exception while in user mode. "
101 "Aborting\n");
102 break;
103 case POWERPC_EXCP_DSI: /* Data storage exception */
104 /* XXX: check this. Seems bugged */
105 switch (env->error_code & 0xFF000000) {
106 case 0x40000000:
107 case 0x42000000:
108 info.si_signo = TARGET_SIGSEGV;
109 info.si_errno = 0;
110 info.si_code = TARGET_SEGV_MAPERR;
111 break;
112 case 0x04000000:
113 info.si_signo = TARGET_SIGILL;
114 info.si_errno = 0;
115 info.si_code = TARGET_ILL_ILLADR;
116 break;
117 case 0x08000000:
118 info.si_signo = TARGET_SIGSEGV;
119 info.si_errno = 0;
120 info.si_code = TARGET_SEGV_ACCERR;
121 break;
122 default:
123 /* Let's send a regular segfault... */
124 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
125 env->error_code);
126 info.si_signo = TARGET_SIGSEGV;
127 info.si_errno = 0;
128 info.si_code = TARGET_SEGV_MAPERR;
129 break;
130 }
131 info._sifields._sigfault._addr = env->spr[SPR_DAR];
132 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
133 break;
134 case POWERPC_EXCP_ISI: /* Instruction storage exception */
135 /* XXX: check this */
136 switch (env->error_code & 0xFF000000) {
137 case 0x40000000:
138 info.si_signo = TARGET_SIGSEGV;
139 info.si_errno = 0;
140 info.si_code = TARGET_SEGV_MAPERR;
141 break;
142 case 0x10000000:
143 case 0x08000000:
144 info.si_signo = TARGET_SIGSEGV;
145 info.si_errno = 0;
146 info.si_code = TARGET_SEGV_ACCERR;
147 break;
148 default:
149 /* Let's send a regular segfault... */
150 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
151 env->error_code);
152 info.si_signo = TARGET_SIGSEGV;
153 info.si_errno = 0;
154 info.si_code = TARGET_SEGV_MAPERR;
155 break;
156 }
157 info._sifields._sigfault._addr = env->nip - 4;
158 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
159 break;
160 case POWERPC_EXCP_EXTERNAL: /* External input */
161 cpu_abort(cs, "External interrupt while in user mode. "
162 "Aborting\n");
163 break;
164 case POWERPC_EXCP_ALIGN: /* Alignment exception */
165 /* XXX: check this */
166 info.si_signo = TARGET_SIGBUS;
167 info.si_errno = 0;
168 info.si_code = TARGET_BUS_ADRALN;
169 info._sifields._sigfault._addr = env->nip;
170 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
171 break;
172 case POWERPC_EXCP_PROGRAM: /* Program exception */
173 case POWERPC_EXCP_HV_EMU: /* HV emulation */
174 /* XXX: check this */
175 switch (env->error_code & ~0xF) {
176 case POWERPC_EXCP_FP:
177 info.si_signo = TARGET_SIGFPE;
178 info.si_errno = 0;
179 switch (env->error_code & 0xF) {
180 case POWERPC_EXCP_FP_OX:
181 info.si_code = TARGET_FPE_FLTOVF;
182 break;
183 case POWERPC_EXCP_FP_UX:
184 info.si_code = TARGET_FPE_FLTUND;
185 break;
186 case POWERPC_EXCP_FP_ZX:
187 case POWERPC_EXCP_FP_VXZDZ:
188 info.si_code = TARGET_FPE_FLTDIV;
189 break;
190 case POWERPC_EXCP_FP_XX:
191 info.si_code = TARGET_FPE_FLTRES;
192 break;
193 case POWERPC_EXCP_FP_VXSOFT:
194 info.si_code = TARGET_FPE_FLTINV;
195 break;
196 case POWERPC_EXCP_FP_VXSNAN:
197 case POWERPC_EXCP_FP_VXISI:
198 case POWERPC_EXCP_FP_VXIDI:
199 case POWERPC_EXCP_FP_VXIMZ:
200 case POWERPC_EXCP_FP_VXVC:
201 case POWERPC_EXCP_FP_VXSQRT:
202 case POWERPC_EXCP_FP_VXCVI:
203 info.si_code = TARGET_FPE_FLTSUB;
204 break;
205 default:
206 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
207 env->error_code);
208 break;
209 }
210 break;
211 case POWERPC_EXCP_INVAL:
212 info.si_signo = TARGET_SIGILL;
213 info.si_errno = 0;
214 switch (env->error_code & 0xF) {
215 case POWERPC_EXCP_INVAL_INVAL:
216 info.si_code = TARGET_ILL_ILLOPC;
217 break;
218 case POWERPC_EXCP_INVAL_LSWX:
219 info.si_code = TARGET_ILL_ILLOPN;
220 break;
221 case POWERPC_EXCP_INVAL_SPR:
222 info.si_code = TARGET_ILL_PRVREG;
223 break;
224 case POWERPC_EXCP_INVAL_FP:
225 info.si_code = TARGET_ILL_COPROC;
226 break;
227 default:
228 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
229 env->error_code & 0xF);
230 info.si_code = TARGET_ILL_ILLADR;
231 break;
232 }
233 break;
234 case POWERPC_EXCP_PRIV:
235 info.si_signo = TARGET_SIGILL;
236 info.si_errno = 0;
237 switch (env->error_code & 0xF) {
238 case POWERPC_EXCP_PRIV_OPC:
239 info.si_code = TARGET_ILL_PRVOPC;
240 break;
241 case POWERPC_EXCP_PRIV_REG:
242 info.si_code = TARGET_ILL_PRVREG;
243 break;
244 default:
245 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
246 env->error_code & 0xF);
247 info.si_code = TARGET_ILL_PRVOPC;
248 break;
249 }
250 break;
251 case POWERPC_EXCP_TRAP:
252 cpu_abort(cs, "Tried to call a TRAP\n");
253 break;
254 default:
255 /* Should not happen ! */
256 cpu_abort(cs, "Unknown program exception (%02x)\n",
257 env->error_code);
258 break;
259 }
260 info._sifields._sigfault._addr = env->nip;
261 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
262 break;
263 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
264 info.si_signo = TARGET_SIGILL;
265 info.si_errno = 0;
266 info.si_code = TARGET_ILL_COPROC;
267 info._sifields._sigfault._addr = env->nip;
268 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
269 break;
270 case POWERPC_EXCP_SYSCALL: /* System call exception */
3c89b8d6 271 case POWERPC_EXCP_SYSCALL_VECTORED:
11400516
LV
272 cpu_abort(cs, "Syscall exception while in user mode. "
273 "Aborting\n");
274 break;
275 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
276 info.si_signo = TARGET_SIGILL;
277 info.si_errno = 0;
278 info.si_code = TARGET_ILL_COPROC;
279 info._sifields._sigfault._addr = env->nip;
280 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
281 break;
282 case POWERPC_EXCP_DECR: /* Decrementer exception */
283 cpu_abort(cs, "Decrementer interrupt while in user mode. "
284 "Aborting\n");
285 break;
286 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
287 cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
288 "Aborting\n");
289 break;
290 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
291 cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
292 "Aborting\n");
293 break;
294 case POWERPC_EXCP_DTLB: /* Data TLB error */
295 cpu_abort(cs, "Data TLB exception while in user mode. "
296 "Aborting\n");
297 break;
298 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
299 cpu_abort(cs, "Instruction TLB exception while in user mode. "
300 "Aborting\n");
301 break;
302 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
303 info.si_signo = TARGET_SIGILL;
304 info.si_errno = 0;
305 info.si_code = TARGET_ILL_COPROC;
306 info._sifields._sigfault._addr = env->nip;
307 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
308 break;
309 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
310 cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
311 break;
312 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
313 cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
314 break;
315 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
316 cpu_abort(cs, "Performance monitor exception not handled\n");
317 break;
318 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
319 cpu_abort(cs, "Doorbell interrupt while in user mode. "
320 "Aborting\n");
321 break;
322 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
323 cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
324 "Aborting\n");
325 break;
326 case POWERPC_EXCP_RESET: /* System reset exception */
327 cpu_abort(cs, "Reset interrupt while in user mode. "
328 "Aborting\n");
329 break;
330 case POWERPC_EXCP_DSEG: /* Data segment exception */
331 cpu_abort(cs, "Data segment exception while in user mode. "
332 "Aborting\n");
333 break;
334 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
335 cpu_abort(cs, "Instruction segment exception "
336 "while in user mode. Aborting\n");
337 break;
338 /* PowerPC 64 with hypervisor mode support */
339 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
340 cpu_abort(cs, "Hypervisor decrementer interrupt "
341 "while in user mode. Aborting\n");
342 break;
343 case POWERPC_EXCP_TRACE: /* Trace exception */
344 /* Nothing to do:
345 * we use this exception to emulate step-by-step execution mode.
346 */
347 break;
348 /* PowerPC 64 with hypervisor mode support */
349 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
350 cpu_abort(cs, "Hypervisor data storage exception "
351 "while in user mode. Aborting\n");
352 break;
353 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
354 cpu_abort(cs, "Hypervisor instruction storage exception "
355 "while in user mode. Aborting\n");
356 break;
357 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
358 cpu_abort(cs, "Hypervisor data segment exception "
359 "while in user mode. Aborting\n");
360 break;
361 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
362 cpu_abort(cs, "Hypervisor instruction segment exception "
363 "while in user mode. Aborting\n");
364 break;
365 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
366 info.si_signo = TARGET_SIGILL;
367 info.si_errno = 0;
368 info.si_code = TARGET_ILL_COPROC;
369 info._sifields._sigfault._addr = env->nip;
370 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
371 break;
372 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
373 cpu_abort(cs, "Programmable interval timer interrupt "
374 "while in user mode. Aborting\n");
375 break;
376 case POWERPC_EXCP_IO: /* IO error exception */
377 cpu_abort(cs, "IO error exception while in user mode. "
378 "Aborting\n");
379 break;
380 case POWERPC_EXCP_RUNM: /* Run mode exception */
381 cpu_abort(cs, "Run mode exception while in user mode. "
382 "Aborting\n");
383 break;
384 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
385 cpu_abort(cs, "Emulation trap exception not handled\n");
386 break;
387 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
388 cpu_abort(cs, "Instruction fetch TLB exception "
389 "while in user-mode. Aborting");
390 break;
391 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
392 cpu_abort(cs, "Data load TLB exception while in user-mode. "
393 "Aborting");
394 break;
395 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
396 cpu_abort(cs, "Data store TLB exception while in user-mode. "
397 "Aborting");
398 break;
399 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
400 cpu_abort(cs, "Floating-point assist exception not handled\n");
401 break;
402 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
403 cpu_abort(cs, "Instruction address breakpoint exception "
404 "not handled\n");
405 break;
406 case POWERPC_EXCP_SMI: /* System management interrupt */
407 cpu_abort(cs, "System management interrupt while in user mode. "
408 "Aborting\n");
409 break;
410 case POWERPC_EXCP_THERM: /* Thermal interrupt */
411 cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
412 "Aborting\n");
413 break;
414 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
415 cpu_abort(cs, "Performance monitor exception not handled\n");
416 break;
417 case POWERPC_EXCP_VPUA: /* Vector assist exception */
418 cpu_abort(cs, "Vector assist exception not handled\n");
419 break;
420 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
421 cpu_abort(cs, "Soft patch exception not handled\n");
422 break;
423 case POWERPC_EXCP_MAINT: /* Maintenance exception */
424 cpu_abort(cs, "Maintenance exception while in user mode. "
425 "Aborting\n");
426 break;
11400516
LV
427 case POWERPC_EXCP_SYSCALL_USER:
428 /* system call in user-mode emulation */
429 /* WARNING:
430 * PPC ABI uses overflow flag in cr0 to signal an error
431 * in syscalls.
432 */
433 env->crf[0] &= ~0x1;
434 env->nip += 4;
435 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
436 env->gpr[5], env->gpr[6], env->gpr[7],
437 env->gpr[8], 0, 0);
438 if (ret == -TARGET_ERESTARTSYS) {
439 env->nip -= 4;
440 break;
441 }
442 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
443 /* Returning from a successful sigreturn syscall.
444 Avoid corrupting register state. */
445 break;
446 }
447 if (ret > (target_ulong)(-515)) {
448 env->crf[0] |= 0x1;
449 ret = -ret;
450 }
451 env->gpr[3] = ret;
452 break;
14db1899 453 case EXCP_DEBUG:
b10089a1
PM
454 info.si_signo = TARGET_SIGTRAP;
455 info.si_errno = 0;
456 info.si_code = TARGET_TRAP_BRKPT;
457 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
11400516
LV
458 break;
459 case EXCP_INTERRUPT:
460 /* just indicate that signals should be handled asap */
461 break;
462 case EXCP_ATOMIC:
463 cpu_exec_step_atomic(cs);
14db1899 464 arch_interrupt = false;
11400516
LV
465 break;
466 default:
467 cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
468 break;
469 }
470 process_pending_signals(env);
14db1899
RH
471
472 /* Most of the traps imply a transition through kernel mode,
473 * which implies an REI instruction has been executed. Which
474 * means that RX and LOCK_ADDR should be cleared. But there
475 * are a few exceptions for traps internal to QEMU.
476 */
477 if (arch_interrupt) {
478 env->reserve_addr = -1;
479 }
11400516
LV
480 }
481}
482
cd71c089
LV
483void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
484{
11400516
LV
485 int i;
486
487#if defined(TARGET_PPC64)
488 int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
489#if defined(TARGET_ABI32)
75da4997 490 ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag));
11400516 491#else
75da4997 492 ppc_store_msr(env, env->msr | (target_ulong)1 << flag);
11400516
LV
493#endif
494#endif
75da4997 495
11400516
LV
496 env->nip = regs->nip;
497 for(i = 0; i < 32; i++) {
498 env->gpr[i] = regs->gpr[i];
499 }
cd71c089 500}