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"
22 #include "qemu/timer.h"
23 #include "user-internals.h"
24 #include "cpu_loop-common.h"
25 #include "signal-common.h"
27 static inline uint64_t cpu_ppc_get_tb(CPUPPCState
*env
)
29 return cpu_get_host_ticks();
32 uint64_t cpu_ppc_load_tbl(CPUPPCState
*env
)
34 return cpu_ppc_get_tb(env
);
37 uint32_t cpu_ppc_load_tbu(CPUPPCState
*env
)
39 return cpu_ppc_get_tb(env
) >> 32;
42 uint64_t cpu_ppc_load_atbl(CPUPPCState
*env
)
44 return cpu_ppc_get_tb(env
);
47 uint32_t cpu_ppc_load_atbu(CPUPPCState
*env
)
49 return cpu_ppc_get_tb(env
) >> 32;
52 uint64_t cpu_ppc_load_vtb(CPUPPCState
*env
)
54 return cpu_ppc_get_tb(env
);
57 /* XXX: to be fixed */
58 int ppc_dcr_read (ppc_dcr_t
*dcr_env
, int dcrn
, uint32_t *valp
)
63 int ppc_dcr_write (ppc_dcr_t
*dcr_env
, int dcrn
, uint32_t val
)
68 void cpu_loop(CPUPPCState
*env
)
70 CPUState
*cs
= env_cpu(env
);
71 int trapnr
, si_signo
, si_code
;
78 trapnr
= cpu_exec(cs
);
80 process_queued_cpu_work(cs
);
82 arch_interrupt
= true;
84 case POWERPC_EXCP_NONE
:
87 case POWERPC_EXCP_CRITICAL
: /* Critical input */
88 cpu_abort(cs
, "Critical interrupt while in user mode. "
91 case POWERPC_EXCP_MCHECK
: /* Machine check exception */
92 cpu_abort(cs
, "Machine check exception while in user mode. "
95 case POWERPC_EXCP_DSI
: /* Data storage exception */
96 case POWERPC_EXCP_ISI
: /* Instruction storage exception */
97 /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
98 force_sig_fault(TARGET_SIGSEGV
, TARGET_SEGV_MAPERR
,
101 case POWERPC_EXCP_EXTERNAL
: /* External input */
102 cpu_abort(cs
, "External interrupt while in user mode. "
105 case POWERPC_EXCP_PROGRAM
: /* Program exception */
106 case POWERPC_EXCP_HV_EMU
: /* HV emulation */
107 /* XXX: check this */
108 switch (env
->error_code
& ~0xF) {
109 case POWERPC_EXCP_FP
:
110 si_signo
= TARGET_SIGFPE
;
111 switch (env
->error_code
& 0xF) {
112 case POWERPC_EXCP_FP_OX
:
113 si_code
= TARGET_FPE_FLTOVF
;
115 case POWERPC_EXCP_FP_UX
:
116 si_code
= TARGET_FPE_FLTUND
;
118 case POWERPC_EXCP_FP_ZX
:
119 case POWERPC_EXCP_FP_VXZDZ
:
120 si_code
= TARGET_FPE_FLTDIV
;
122 case POWERPC_EXCP_FP_XX
:
123 si_code
= TARGET_FPE_FLTRES
;
125 case POWERPC_EXCP_FP_VXSOFT
:
126 si_code
= TARGET_FPE_FLTINV
;
128 case POWERPC_EXCP_FP_VXSNAN
:
129 case POWERPC_EXCP_FP_VXISI
:
130 case POWERPC_EXCP_FP_VXIDI
:
131 case POWERPC_EXCP_FP_VXIMZ
:
132 case POWERPC_EXCP_FP_VXVC
:
133 case POWERPC_EXCP_FP_VXSQRT
:
134 case POWERPC_EXCP_FP_VXCVI
:
135 si_code
= TARGET_FPE_FLTSUB
;
138 EXCP_DUMP(env
, "Unknown floating point exception (%02x)\n",
144 case POWERPC_EXCP_INVAL
:
145 si_signo
= TARGET_SIGILL
;
146 switch (env
->error_code
& 0xF) {
147 case POWERPC_EXCP_INVAL_INVAL
:
148 si_code
= TARGET_ILL_ILLOPC
;
150 case POWERPC_EXCP_INVAL_LSWX
:
151 si_code
= TARGET_ILL_ILLOPN
;
153 case POWERPC_EXCP_INVAL_SPR
:
154 si_code
= TARGET_ILL_PRVREG
;
156 case POWERPC_EXCP_INVAL_FP
:
157 si_code
= TARGET_ILL_COPROC
;
160 EXCP_DUMP(env
, "Unknown invalid operation (%02x)\n",
161 env
->error_code
& 0xF);
162 si_code
= TARGET_ILL_ILLADR
;
166 case POWERPC_EXCP_PRIV
:
167 si_signo
= TARGET_SIGILL
;
168 switch (env
->error_code
& 0xF) {
169 case POWERPC_EXCP_PRIV_OPC
:
170 si_code
= TARGET_ILL_PRVOPC
;
172 case POWERPC_EXCP_PRIV_REG
:
173 si_code
= TARGET_ILL_PRVREG
;
176 EXCP_DUMP(env
, "Unknown privilege violation (%02x)\n",
177 env
->error_code
& 0xF);
178 si_code
= TARGET_ILL_PRVOPC
;
182 case POWERPC_EXCP_TRAP
:
183 si_signo
= TARGET_SIGTRAP
;
184 si_code
= TARGET_TRAP_BRKPT
;
187 /* Should not happen ! */
188 cpu_abort(cs
, "Unknown program exception (%02x)\n",
192 force_sig_fault(si_signo
, si_code
, env
->nip
);
194 case POWERPC_EXCP_FPU
: /* Floating-point unavailable exception */
195 case POWERPC_EXCP_APU
: /* Auxiliary processor unavailable */
196 case POWERPC_EXCP_SPEU
: /* SPE/embedded floating-point unavail. */
197 case POWERPC_EXCP_VPU
: /* Vector unavailable exception */
198 force_sig_fault(TARGET_SIGILL
, TARGET_ILL_COPROC
, env
->nip
);
200 case POWERPC_EXCP_SYSCALL
: /* System call exception */
201 case POWERPC_EXCP_SYSCALL_VECTORED
:
202 cpu_abort(cs
, "Syscall exception while in user mode. "
205 case POWERPC_EXCP_DECR
: /* Decrementer exception */
206 cpu_abort(cs
, "Decrementer interrupt while in user mode. "
209 case POWERPC_EXCP_FIT
: /* Fixed-interval timer interrupt */
210 cpu_abort(cs
, "Fix interval timer interrupt while in user mode. "
213 case POWERPC_EXCP_WDT
: /* Watchdog timer interrupt */
214 cpu_abort(cs
, "Watchdog timer interrupt while in user mode. "
217 case POWERPC_EXCP_DTLB
: /* Data TLB error */
218 cpu_abort(cs
, "Data TLB exception while in user mode. "
221 case POWERPC_EXCP_ITLB
: /* Instruction TLB error */
222 cpu_abort(cs
, "Instruction TLB exception while in user mode. "
225 case POWERPC_EXCP_EFPDI
: /* Embedded floating-point data IRQ */
226 cpu_abort(cs
, "Embedded floating-point data IRQ not handled\n");
228 case POWERPC_EXCP_EFPRI
: /* Embedded floating-point round IRQ */
229 cpu_abort(cs
, "Embedded floating-point round IRQ not handled\n");
231 case POWERPC_EXCP_EPERFM
: /* Embedded performance monitor IRQ */
232 cpu_abort(cs
, "Performance monitor exception not handled\n");
234 case POWERPC_EXCP_DOORI
: /* Embedded doorbell interrupt */
235 cpu_abort(cs
, "Doorbell interrupt while in user mode. "
238 case POWERPC_EXCP_DOORCI
: /* Embedded doorbell critical interrupt */
239 cpu_abort(cs
, "Doorbell critical interrupt while in user mode. "
242 case POWERPC_EXCP_RESET
: /* System reset exception */
243 cpu_abort(cs
, "Reset interrupt while in user mode. "
246 case POWERPC_EXCP_DSEG
: /* Data segment exception */
247 cpu_abort(cs
, "Data segment exception while in user mode. "
250 case POWERPC_EXCP_ISEG
: /* Instruction segment exception */
251 cpu_abort(cs
, "Instruction segment exception "
252 "while in user mode. Aborting\n");
254 /* PowerPC 64 with hypervisor mode support */
255 case POWERPC_EXCP_HDECR
: /* Hypervisor decrementer exception */
256 cpu_abort(cs
, "Hypervisor decrementer interrupt "
257 "while in user mode. Aborting\n");
259 case POWERPC_EXCP_TRACE
: /* Trace exception */
261 * we use this exception to emulate step-by-step execution mode.
264 /* PowerPC 64 with hypervisor mode support */
265 case POWERPC_EXCP_HDSI
: /* Hypervisor data storage exception */
266 cpu_abort(cs
, "Hypervisor data storage exception "
267 "while in user mode. Aborting\n");
269 case POWERPC_EXCP_HISI
: /* Hypervisor instruction storage excp */
270 cpu_abort(cs
, "Hypervisor instruction storage exception "
271 "while in user mode. Aborting\n");
273 case POWERPC_EXCP_HDSEG
: /* Hypervisor data segment exception */
274 cpu_abort(cs
, "Hypervisor data segment exception "
275 "while in user mode. Aborting\n");
277 case POWERPC_EXCP_HISEG
: /* Hypervisor instruction segment excp */
278 cpu_abort(cs
, "Hypervisor instruction segment exception "
279 "while in user mode. Aborting\n");
281 case POWERPC_EXCP_PIT
: /* Programmable interval timer IRQ */
282 cpu_abort(cs
, "Programmable interval timer interrupt "
283 "while in user mode. Aborting\n");
285 case POWERPC_EXCP_EMUL
: /* Emulation trap exception */
286 cpu_abort(cs
, "Emulation trap exception not handled\n");
288 case POWERPC_EXCP_IFTLB
: /* Instruction fetch TLB error */
289 cpu_abort(cs
, "Instruction fetch TLB exception "
290 "while in user-mode. Aborting");
292 case POWERPC_EXCP_DLTLB
: /* Data load TLB miss */
293 cpu_abort(cs
, "Data load TLB exception while in user-mode. "
296 case POWERPC_EXCP_DSTLB
: /* Data store TLB miss */
297 cpu_abort(cs
, "Data store TLB exception while in user-mode. "
300 case POWERPC_EXCP_FPA
: /* Floating-point assist exception */
301 cpu_abort(cs
, "Floating-point assist exception not handled\n");
303 case POWERPC_EXCP_IABR
: /* Instruction address breakpoint */
304 cpu_abort(cs
, "Instruction address breakpoint exception "
307 case POWERPC_EXCP_SMI
: /* System management interrupt */
308 cpu_abort(cs
, "System management interrupt while in user mode. "
311 case POWERPC_EXCP_THERM
: /* Thermal interrupt */
312 cpu_abort(cs
, "Thermal interrupt interrupt while in user mode. "
315 case POWERPC_EXCP_PERFM
: /* Embedded performance monitor IRQ */
316 cpu_abort(cs
, "Performance monitor exception not handled\n");
318 case POWERPC_EXCP_VPUA
: /* Vector assist exception */
319 cpu_abort(cs
, "Vector assist exception not handled\n");
321 case POWERPC_EXCP_SOFTP
: /* Soft patch exception */
322 cpu_abort(cs
, "Soft patch exception not handled\n");
324 case POWERPC_EXCP_MAINT
: /* Maintenance exception */
325 cpu_abort(cs
, "Maintenance exception while in user mode. "
328 case POWERPC_EXCP_SYSCALL_USER
:
329 /* system call in user-mode emulation */
331 * PPC ABI uses overflow flag in cr0 to signal an error
336 ret
= do_syscall(env
, env
->gpr
[0], env
->gpr
[3], env
->gpr
[4],
337 env
->gpr
[5], env
->gpr
[6], env
->gpr
[7],
339 if (ret
== -QEMU_ERESTARTSYS
) {
343 if (ret
== (target_ulong
)(-QEMU_ESIGRETURN
)) {
344 /* Returning from a successful sigreturn syscall.
345 Avoid corrupting register state. */
348 if (ret
> (target_ulong
)(-515)) {
355 force_sig_fault(TARGET_SIGTRAP
, TARGET_TRAP_BRKPT
, env
->nip
);
358 /* just indicate that signals should be handled asap */
361 cpu_exec_step_atomic(cs
);
362 arch_interrupt
= false;
365 cpu_abort(cs
, "Unknown exception 0x%x. Aborting\n", trapnr
);
368 process_pending_signals(env
);
370 /* Most of the traps imply a transition through kernel mode,
371 * which implies an REI instruction has been executed. Which
372 * means that RX and LOCK_ADDR should be cleared. But there
373 * are a few exceptions for traps internal to QEMU.
375 if (arch_interrupt
) {
376 env
->reserve_addr
= -1;
381 void target_cpu_copy_regs(CPUArchState
*env
, struct target_pt_regs
*regs
)
385 #if defined(TARGET_PPC64)
386 int flag
= (env
->insns_flags2
& PPC2_BOOKE206
) ? MSR_CM
: MSR_SF
;
387 #if defined(TARGET_ABI32)
388 ppc_store_msr(env
, env
->msr
& ~((target_ulong
)1 << flag
));
390 ppc_store_msr(env
, env
->msr
| (target_ulong
)1 << flag
);
394 env
->nip
= regs
->nip
;
395 for(i
= 0; i
< 32; i
++) {
396 env
->gpr
[i
] = regs
->gpr
[i
];