linux-user: Add support for btrfs ioctls used to manage quota
[qemu.git] / linux-user / ppc / cpu_loop.c
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"
21 #include "qemu-common.h"
22 #include "qemu.h"
23 #include "cpu_loop-common.h"
24
25 static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
26 {
27 return cpu_get_host_ticks();
28 }
29
30 uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
31 {
32 return cpu_ppc_get_tb(env);
33 }
34
35 uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
36 {
37 return cpu_ppc_get_tb(env) >> 32;
38 }
39
40 uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
41 {
42 return cpu_ppc_get_tb(env);
43 }
44
45 uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
46 {
47 return cpu_ppc_get_tb(env) >> 32;
48 }
49
50 uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
51 {
52 return cpu_ppc_get_tb(env);
53 }
54
55 uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
56 __attribute__ (( alias ("cpu_ppc_load_tbu") ));
57
58 uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
59 {
60 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
61 }
62
63 /* XXX: to be fixed */
64 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
65 {
66 return -1;
67 }
68
69 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
70 {
71 return -1;
72 }
73
74 void cpu_loop(CPUPPCState *env)
75 {
76 CPUState *cs = env_cpu(env);
77 target_siginfo_t info;
78 int trapnr;
79 target_ulong ret;
80
81 for(;;) {
82 bool arch_interrupt;
83
84 cpu_exec_start(cs);
85 trapnr = cpu_exec(cs);
86 cpu_exec_end(cs);
87 process_queued_cpu_work(cs);
88
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;
129 }
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;
155 }
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;
208 }
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;
231 }
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;
248 }
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;
258 }
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 case POWERPC_EXCP_SYSCALL_VECTORED:
271 cpu_abort(cs, "Syscall exception while in user mode. "
272 "Aborting\n");
273 break;
274 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
275 info.si_signo = TARGET_SIGILL;
276 info.si_errno = 0;
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);
280 break;
281 case POWERPC_EXCP_DECR: /* Decrementer exception */
282 cpu_abort(cs, "Decrementer interrupt while in user mode. "
283 "Aborting\n");
284 break;
285 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
286 cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
287 "Aborting\n");
288 break;
289 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
290 cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
291 "Aborting\n");
292 break;
293 case POWERPC_EXCP_DTLB: /* Data TLB error */
294 cpu_abort(cs, "Data TLB exception while in user mode. "
295 "Aborting\n");
296 break;
297 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
298 cpu_abort(cs, "Instruction TLB exception while in user mode. "
299 "Aborting\n");
300 break;
301 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
302 info.si_signo = TARGET_SIGILL;
303 info.si_errno = 0;
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);
307 break;
308 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
309 cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
310 break;
311 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
312 cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
313 break;
314 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
315 cpu_abort(cs, "Performance monitor exception not handled\n");
316 break;
317 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
318 cpu_abort(cs, "Doorbell interrupt while in user mode. "
319 "Aborting\n");
320 break;
321 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
322 cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
323 "Aborting\n");
324 break;
325 case POWERPC_EXCP_RESET: /* System reset exception */
326 cpu_abort(cs, "Reset interrupt while in user mode. "
327 "Aborting\n");
328 break;
329 case POWERPC_EXCP_DSEG: /* Data segment exception */
330 cpu_abort(cs, "Data segment exception while in user mode. "
331 "Aborting\n");
332 break;
333 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
334 cpu_abort(cs, "Instruction segment exception "
335 "while in user mode. Aborting\n");
336 break;
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");
341 break;
342 case POWERPC_EXCP_TRACE: /* Trace exception */
343 /* Nothing to do:
344 * we use this exception to emulate step-by-step execution mode.
345 */
346 break;
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");
351 break;
352 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
353 cpu_abort(cs, "Hypervisor instruction storage exception "
354 "while in user mode. Aborting\n");
355 break;
356 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
357 cpu_abort(cs, "Hypervisor data segment exception "
358 "while in user mode. Aborting\n");
359 break;
360 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
361 cpu_abort(cs, "Hypervisor instruction segment exception "
362 "while in user mode. Aborting\n");
363 break;
364 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
365 info.si_signo = TARGET_SIGILL;
366 info.si_errno = 0;
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);
370 break;
371 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
372 cpu_abort(cs, "Programmable interval timer interrupt "
373 "while in user mode. Aborting\n");
374 break;
375 case POWERPC_EXCP_IO: /* IO error exception */
376 cpu_abort(cs, "IO error exception while in user mode. "
377 "Aborting\n");
378 break;
379 case POWERPC_EXCP_RUNM: /* Run mode exception */
380 cpu_abort(cs, "Run mode exception while in user mode. "
381 "Aborting\n");
382 break;
383 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
384 cpu_abort(cs, "Emulation trap exception not handled\n");
385 break;
386 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
387 cpu_abort(cs, "Instruction fetch TLB exception "
388 "while in user-mode. Aborting");
389 break;
390 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
391 cpu_abort(cs, "Data load TLB exception while in user-mode. "
392 "Aborting");
393 break;
394 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
395 cpu_abort(cs, "Data store TLB exception while in user-mode. "
396 "Aborting");
397 break;
398 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
399 cpu_abort(cs, "Floating-point assist exception not handled\n");
400 break;
401 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
402 cpu_abort(cs, "Instruction address breakpoint exception "
403 "not handled\n");
404 break;
405 case POWERPC_EXCP_SMI: /* System management interrupt */
406 cpu_abort(cs, "System management interrupt while in user mode. "
407 "Aborting\n");
408 break;
409 case POWERPC_EXCP_THERM: /* Thermal interrupt */
410 cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
411 "Aborting\n");
412 break;
413 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
414 cpu_abort(cs, "Performance monitor exception not handled\n");
415 break;
416 case POWERPC_EXCP_VPUA: /* Vector assist exception */
417 cpu_abort(cs, "Vector assist exception not handled\n");
418 break;
419 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
420 cpu_abort(cs, "Soft patch exception not handled\n");
421 break;
422 case POWERPC_EXCP_MAINT: /* Maintenance exception */
423 cpu_abort(cs, "Maintenance exception while in user mode. "
424 "Aborting\n");
425 break;
426 case POWERPC_EXCP_STOP: /* stop translation */
427 /* We did invalidate the instruction cache. Go on */
428 break;
429 case POWERPC_EXCP_BRANCH: /* branch instruction: */
430 /* We just stopped because of a branch. Go on */
431 break;
432 case POWERPC_EXCP_SYSCALL_USER:
433 /* system call in user-mode emulation */
434 /* WARNING:
435 * PPC ABI uses overflow flag in cr0 to signal an error
436 * in syscalls.
437 */
438 env->crf[0] &= ~0x1;
439 env->nip += 4;
440 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
441 env->gpr[5], env->gpr[6], env->gpr[7],
442 env->gpr[8], 0, 0);
443 if (ret == -TARGET_ERESTARTSYS) {
444 env->nip -= 4;
445 break;
446 }
447 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
448 /* Returning from a successful sigreturn syscall.
449 Avoid corrupting register state. */
450 break;
451 }
452 if (ret > (target_ulong)(-515)) {
453 env->crf[0] |= 0x1;
454 ret = -ret;
455 }
456 env->gpr[3] = ret;
457 break;
458 case EXCP_DEBUG:
459 info.si_signo = TARGET_SIGTRAP;
460 info.si_errno = 0;
461 info.si_code = TARGET_TRAP_BRKPT;
462 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
463 break;
464 case EXCP_INTERRUPT:
465 /* just indicate that signals should be handled asap */
466 break;
467 case EXCP_ATOMIC:
468 cpu_exec_step_atomic(cs);
469 arch_interrupt = false;
470 break;
471 default:
472 cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
473 break;
474 }
475 process_pending_signals(env);
476
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.
481 */
482 if (arch_interrupt) {
483 env->reserve_addr = -1;
484 }
485 }
486 }
487
488 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
489 {
490 int i;
491
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);
496 #else
497 env->msr |= (target_ulong)1 << flag;
498 #endif
499 #endif
500 env->nip = regs->nip;
501 for(i = 0; i < 32; i++) {
502 env->gpr[i] = regs->gpr[i];
503 }
504 }