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