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"
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
)
69 int ppc_dcr_write (ppc_dcr_t
*dcr_env
, int dcrn
, uint32_t val
)
74 void cpu_loop(CPUPPCState
*env
)
76 CPUState
*cs
= env_cpu(env
);
77 target_siginfo_t info
;
85 trapnr
= cpu_exec(cs
);
87 process_queued_cpu_work(cs
);
89 arch_interrupt
= true;
91 case POWERPC_EXCP_NONE
:
94 case POWERPC_EXCP_CRITICAL
: /* Critical input */
95 cpu_abort(cs
, "Critical interrupt while in user mode. "
98 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
99 cpu_abort(cs
, "Machine check exception while in user mode. "
102 case POWERPC_EXCP_DSI
: /* Data storage exception */
103 /* XXX: check this. Seems bugged */
104 switch (env
->error_code
& 0xFF000000) {
107 info
.si_signo
= TARGET_SIGSEGV
;
109 info
.si_code
= TARGET_SEGV_MAPERR
;
112 info
.si_signo
= TARGET_SIGILL
;
114 info
.si_code
= TARGET_ILL_ILLADR
;
117 info
.si_signo
= TARGET_SIGSEGV
;
119 info
.si_code
= TARGET_SEGV_ACCERR
;
122 /* Let's send a regular segfault... */
123 EXCP_DUMP(env
, "Invalid segfault errno (%02x)\n",
125 info
.si_signo
= TARGET_SIGSEGV
;
127 info
.si_code
= TARGET_SEGV_MAPERR
;
130 info
._sifields
._sigfault
._addr
= env
->spr
[SPR_DAR
];
131 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
133 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
134 /* XXX: check this */
135 switch (env
->error_code
& 0xFF000000) {
137 info
.si_signo
= TARGET_SIGSEGV
;
139 info
.si_code
= TARGET_SEGV_MAPERR
;
143 info
.si_signo
= TARGET_SIGSEGV
;
145 info
.si_code
= TARGET_SEGV_ACCERR
;
148 /* Let's send a regular segfault... */
149 EXCP_DUMP(env
, "Invalid segfault errno (%02x)\n",
151 info
.si_signo
= TARGET_SIGSEGV
;
153 info
.si_code
= TARGET_SEGV_MAPERR
;
156 info
._sifields
._sigfault
._addr
= env
->nip
- 4;
157 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
159 case POWERPC_EXCP_EXTERNAL
: /* External input */
160 cpu_abort(cs
, "External interrupt while in user mode. "
163 case POWERPC_EXCP_ALIGN
: /* Alignment exception */
164 /* XXX: check this */
165 info
.si_signo
= TARGET_SIGBUS
;
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
);
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
;
178 switch (env
->error_code
& 0xF) {
179 case POWERPC_EXCP_FP_OX
:
180 info
.si_code
= TARGET_FPE_FLTOVF
;
182 case POWERPC_EXCP_FP_UX
:
183 info
.si_code
= TARGET_FPE_FLTUND
;
185 case POWERPC_EXCP_FP_ZX
:
186 case POWERPC_EXCP_FP_VXZDZ
:
187 info
.si_code
= TARGET_FPE_FLTDIV
;
189 case POWERPC_EXCP_FP_XX
:
190 info
.si_code
= TARGET_FPE_FLTRES
;
192 case POWERPC_EXCP_FP_VXSOFT
:
193 info
.si_code
= TARGET_FPE_FLTINV
;
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
;
205 EXCP_DUMP(env
, "Unknown floating point exception (%02x)\n",
210 case POWERPC_EXCP_INVAL
:
211 info
.si_signo
= TARGET_SIGILL
;
213 switch (env
->error_code
& 0xF) {
214 case POWERPC_EXCP_INVAL_INVAL
:
215 info
.si_code
= TARGET_ILL_ILLOPC
;
217 case POWERPC_EXCP_INVAL_LSWX
:
218 info
.si_code
= TARGET_ILL_ILLOPN
;
220 case POWERPC_EXCP_INVAL_SPR
:
221 info
.si_code
= TARGET_ILL_PRVREG
;
223 case POWERPC_EXCP_INVAL_FP
:
224 info
.si_code
= TARGET_ILL_COPROC
;
227 EXCP_DUMP(env
, "Unknown invalid operation (%02x)\n",
228 env
->error_code
& 0xF);
229 info
.si_code
= TARGET_ILL_ILLADR
;
233 case POWERPC_EXCP_PRIV
:
234 info
.si_signo
= TARGET_SIGILL
;
236 switch (env
->error_code
& 0xF) {
237 case POWERPC_EXCP_PRIV_OPC
:
238 info
.si_code
= TARGET_ILL_PRVOPC
;
240 case POWERPC_EXCP_PRIV_REG
:
241 info
.si_code
= TARGET_ILL_PRVREG
;
244 EXCP_DUMP(env
, "Unknown privilege violation (%02x)\n",
245 env
->error_code
& 0xF);
246 info
.si_code
= TARGET_ILL_PRVOPC
;
250 case POWERPC_EXCP_TRAP
:
251 cpu_abort(cs
, "Tried to call a TRAP\n");
254 /* Should not happen ! */
255 cpu_abort(cs
, "Unknown program exception (%02x)\n",
259 info
._sifields
._sigfault
._addr
= env
->nip
;
260 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
262 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
263 info
.si_signo
= TARGET_SIGILL
;
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
);
269 case POWERPC_EXCP_SYSCALL
: /* System call exception */
270 case POWERPC_EXCP_SYSCALL_VECTORED
:
271 cpu_abort(cs
, "Syscall exception while in user mode. "
274 case POWERPC_EXCP_APU
: /* Auxiliary processor unavailable */
275 info
.si_signo
= TARGET_SIGILL
;
277 info
.si_code
= TARGET_ILL_COPROC
;
278 info
._sifields
._sigfault
._addr
= env
->nip
;
279 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
281 case POWERPC_EXCP_DECR
: /* Decrementer exception */
282 cpu_abort(cs
, "Decrementer interrupt while in user mode. "
285 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
286 cpu_abort(cs
, "Fix interval timer interrupt while in user mode. "
289 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
290 cpu_abort(cs
, "Watchdog timer interrupt while in user mode. "
293 case POWERPC_EXCP_DTLB
: /* Data TLB error */
294 cpu_abort(cs
, "Data TLB exception while in user mode. "
297 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
298 cpu_abort(cs
, "Instruction TLB exception while in user mode. "
301 case POWERPC_EXCP_SPEU
: /* SPE/embedded floating-point unavail. */
302 info
.si_signo
= TARGET_SIGILL
;
304 info
.si_code
= TARGET_ILL_COPROC
;
305 info
._sifields
._sigfault
._addr
= env
->nip
;
306 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
308 case POWERPC_EXCP_EFPDI
: /* Embedded floating-point data IRQ */
309 cpu_abort(cs
, "Embedded floating-point data IRQ not handled\n");
311 case POWERPC_EXCP_EFPRI
: /* Embedded floating-point round IRQ */
312 cpu_abort(cs
, "Embedded floating-point round IRQ not handled\n");
314 case POWERPC_EXCP_EPERFM
: /* Embedded performance monitor IRQ */
315 cpu_abort(cs
, "Performance monitor exception not handled\n");
317 case POWERPC_EXCP_DOORI
: /* Embedded doorbell interrupt */
318 cpu_abort(cs
, "Doorbell interrupt while in user mode. "
321 case POWERPC_EXCP_DOORCI
: /* Embedded doorbell critical interrupt */
322 cpu_abort(cs
, "Doorbell critical interrupt while in user mode. "
325 case POWERPC_EXCP_RESET
: /* System reset exception */
326 cpu_abort(cs
, "Reset interrupt while in user mode. "
329 case POWERPC_EXCP_DSEG
: /* Data segment exception */
330 cpu_abort(cs
, "Data segment exception while in user mode. "
333 case POWERPC_EXCP_ISEG
: /* Instruction segment exception */
334 cpu_abort(cs
, "Instruction segment exception "
335 "while in user mode. Aborting\n");
337 /* PowerPC 64 with hypervisor mode support */
338 case POWERPC_EXCP_HDECR
: /* Hypervisor decrementer exception */
339 cpu_abort(cs
, "Hypervisor decrementer interrupt "
340 "while in user mode. Aborting\n");
342 case POWERPC_EXCP_TRACE
: /* Trace exception */
344 * we use this exception to emulate step-by-step execution mode.
347 /* PowerPC 64 with hypervisor mode support */
348 case POWERPC_EXCP_HDSI
: /* Hypervisor data storage exception */
349 cpu_abort(cs
, "Hypervisor data storage exception "
350 "while in user mode. Aborting\n");
352 case POWERPC_EXCP_HISI
: /* Hypervisor instruction storage excp */
353 cpu_abort(cs
, "Hypervisor instruction storage exception "
354 "while in user mode. Aborting\n");
356 case POWERPC_EXCP_HDSEG
: /* Hypervisor data segment exception */
357 cpu_abort(cs
, "Hypervisor data segment exception "
358 "while in user mode. Aborting\n");
360 case POWERPC_EXCP_HISEG
: /* Hypervisor instruction segment excp */
361 cpu_abort(cs
, "Hypervisor instruction segment exception "
362 "while in user mode. Aborting\n");
364 case POWERPC_EXCP_VPU
: /* Vector unavailable exception */
365 info
.si_signo
= TARGET_SIGILL
;
367 info
.si_code
= TARGET_ILL_COPROC
;
368 info
._sifields
._sigfault
._addr
= env
->nip
;
369 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
371 case POWERPC_EXCP_PIT
: /* Programmable interval timer IRQ */
372 cpu_abort(cs
, "Programmable interval timer interrupt "
373 "while in user mode. Aborting\n");
375 case POWERPC_EXCP_IO
: /* IO error exception */
376 cpu_abort(cs
, "IO error exception while in user mode. "
379 case POWERPC_EXCP_RUNM
: /* Run mode exception */
380 cpu_abort(cs
, "Run mode exception while in user mode. "
383 case POWERPC_EXCP_EMUL
: /* Emulation trap exception */
384 cpu_abort(cs
, "Emulation trap exception not handled\n");
386 case POWERPC_EXCP_IFTLB
: /* Instruction fetch TLB error */
387 cpu_abort(cs
, "Instruction fetch TLB exception "
388 "while in user-mode. Aborting");
390 case POWERPC_EXCP_DLTLB
: /* Data load TLB miss */
391 cpu_abort(cs
, "Data load TLB exception while in user-mode. "
394 case POWERPC_EXCP_DSTLB
: /* Data store TLB miss */
395 cpu_abort(cs
, "Data store TLB exception while in user-mode. "
398 case POWERPC_EXCP_FPA
: /* Floating-point assist exception */
399 cpu_abort(cs
, "Floating-point assist exception not handled\n");
401 case POWERPC_EXCP_IABR
: /* Instruction address breakpoint */
402 cpu_abort(cs
, "Instruction address breakpoint exception "
405 case POWERPC_EXCP_SMI
: /* System management interrupt */
406 cpu_abort(cs
, "System management interrupt while in user mode. "
409 case POWERPC_EXCP_THERM
: /* Thermal interrupt */
410 cpu_abort(cs
, "Thermal interrupt interrupt while in user mode. "
413 case POWERPC_EXCP_PERFM
: /* Embedded performance monitor IRQ */
414 cpu_abort(cs
, "Performance monitor exception not handled\n");
416 case POWERPC_EXCP_VPUA
: /* Vector assist exception */
417 cpu_abort(cs
, "Vector assist exception not handled\n");
419 case POWERPC_EXCP_SOFTP
: /* Soft patch exception */
420 cpu_abort(cs
, "Soft patch exception not handled\n");
422 case POWERPC_EXCP_MAINT
: /* Maintenance exception */
423 cpu_abort(cs
, "Maintenance exception while in user mode. "
426 case POWERPC_EXCP_STOP
: /* stop translation */
427 /* We did invalidate the instruction cache. Go on */
429 case POWERPC_EXCP_BRANCH
: /* branch instruction: */
430 /* We just stopped because of a branch. Go on */
432 case POWERPC_EXCP_SYSCALL_USER
:
433 /* system call in user-mode emulation */
435 * PPC ABI uses overflow flag in cr0 to signal an error
440 ret
= do_syscall(env
, env
->gpr
[0], env
->gpr
[3], env
->gpr
[4],
441 env
->gpr
[5], env
->gpr
[6], env
->gpr
[7],
443 if (ret
== -TARGET_ERESTARTSYS
) {
447 if (ret
== (target_ulong
)(-TARGET_QEMU_ESIGRETURN
)) {
448 /* Returning from a successful sigreturn syscall.
449 Avoid corrupting register state. */
452 if (ret
> (target_ulong
)(-515)) {
459 info
.si_signo
= TARGET_SIGTRAP
;
461 info
.si_code
= TARGET_TRAP_BRKPT
;
462 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
465 /* just indicate that signals should be handled asap */
468 cpu_exec_step_atomic(cs
);
469 arch_interrupt
= false;
472 cpu_abort(cs
, "Unknown exception 0x%x. Aborting\n", trapnr
);
475 process_pending_signals(env
);
477 /* Most of the traps imply a transition through kernel mode,
478 * which implies an REI instruction has been executed. Which
479 * means that RX and LOCK_ADDR should be cleared. But there
480 * are a few exceptions for traps internal to QEMU.
482 if (arch_interrupt
) {
483 env
->reserve_addr
= -1;
488 void target_cpu_copy_regs(CPUArchState
*env
, struct target_pt_regs
*regs
)
492 #if defined(TARGET_PPC64)
493 int flag
= (env
->insns_flags2
& PPC2_BOOKE206
) ? MSR_CM
: MSR_SF
;
494 #if defined(TARGET_ABI32)
495 env
->msr
&= ~((target_ulong
)1 << flag
);
497 env
->msr
|= (target_ulong
)1 << flag
;
500 env
->nip
= regs
->nip
;
501 for(i
= 0; i
< 32; i
++) {
502 env
->gpr
[i
] = regs
->gpr
[i
];