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