1cd71c089SLaurent Vivier /* 2cd71c089SLaurent Vivier * qemu user cpu loop 3cd71c089SLaurent Vivier * 4cd71c089SLaurent Vivier * Copyright (c) 2003-2008 Fabrice Bellard 5cd71c089SLaurent Vivier * 6cd71c089SLaurent Vivier * This program is free software; you can redistribute it and/or modify 7cd71c089SLaurent Vivier * it under the terms of the GNU General Public License as published by 8cd71c089SLaurent Vivier * the Free Software Foundation; either version 2 of the License, or 9cd71c089SLaurent Vivier * (at your option) any later version. 10cd71c089SLaurent Vivier * 11cd71c089SLaurent Vivier * This program is distributed in the hope that it will be useful, 12cd71c089SLaurent Vivier * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cd71c089SLaurent Vivier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cd71c089SLaurent Vivier * GNU General Public License for more details. 15cd71c089SLaurent Vivier * 16cd71c089SLaurent Vivier * You should have received a copy of the GNU General Public License 17cd71c089SLaurent Vivier * along with this program; if not, see <http://www.gnu.org/licenses/>. 18cd71c089SLaurent Vivier */ 19cd71c089SLaurent Vivier 20cd71c089SLaurent Vivier #include "qemu/osdep.h" 21a8d25326SMarkus Armbruster #include "qemu-common.h" 22cd71c089SLaurent Vivier #include "qemu.h" 23cd71c089SLaurent Vivier #include "cpu_loop-common.h" 24cd71c089SLaurent Vivier 2511400516SLaurent Vivier static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 2611400516SLaurent Vivier { 2711400516SLaurent Vivier return cpu_get_host_ticks(); 2811400516SLaurent Vivier } 2911400516SLaurent Vivier 3011400516SLaurent Vivier uint64_t cpu_ppc_load_tbl(CPUPPCState *env) 3111400516SLaurent Vivier { 3211400516SLaurent Vivier return cpu_ppc_get_tb(env); 3311400516SLaurent Vivier } 3411400516SLaurent Vivier 3511400516SLaurent Vivier uint32_t cpu_ppc_load_tbu(CPUPPCState *env) 3611400516SLaurent Vivier { 3711400516SLaurent Vivier return cpu_ppc_get_tb(env) >> 32; 3811400516SLaurent Vivier } 3911400516SLaurent Vivier 4011400516SLaurent Vivier uint64_t cpu_ppc_load_atbl(CPUPPCState *env) 4111400516SLaurent Vivier { 4211400516SLaurent Vivier return cpu_ppc_get_tb(env); 4311400516SLaurent Vivier } 4411400516SLaurent Vivier 4511400516SLaurent Vivier uint32_t cpu_ppc_load_atbu(CPUPPCState *env) 4611400516SLaurent Vivier { 4711400516SLaurent Vivier return cpu_ppc_get_tb(env) >> 32; 4811400516SLaurent Vivier } 4911400516SLaurent Vivier 505d62725bSSuraj Jitindar Singh uint64_t cpu_ppc_load_vtb(CPUPPCState *env) 515d62725bSSuraj Jitindar Singh { 525d62725bSSuraj Jitindar Singh return cpu_ppc_get_tb(env); 535d62725bSSuraj Jitindar Singh } 545d62725bSSuraj Jitindar Singh 5511400516SLaurent Vivier uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) 5611400516SLaurent Vivier __attribute__ (( alias ("cpu_ppc_load_tbu") )); 5711400516SLaurent Vivier 5811400516SLaurent Vivier uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) 5911400516SLaurent Vivier { 6011400516SLaurent Vivier return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 6111400516SLaurent Vivier } 6211400516SLaurent Vivier 6311400516SLaurent Vivier /* XXX: to be fixed */ 6411400516SLaurent Vivier int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 6511400516SLaurent Vivier { 6611400516SLaurent Vivier return -1; 6711400516SLaurent Vivier } 6811400516SLaurent Vivier 6911400516SLaurent Vivier int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 7011400516SLaurent Vivier { 7111400516SLaurent Vivier return -1; 7211400516SLaurent Vivier } 7311400516SLaurent Vivier 7411400516SLaurent Vivier void cpu_loop(CPUPPCState *env) 7511400516SLaurent Vivier { 76db70b311SRichard Henderson CPUState *cs = env_cpu(env); 7711400516SLaurent Vivier target_siginfo_t info; 78b10089a1SPeter Maydell int trapnr; 7911400516SLaurent Vivier target_ulong ret; 8011400516SLaurent Vivier 8111400516SLaurent Vivier for(;;) { 8214db1899SRichard Henderson bool arch_interrupt; 8314db1899SRichard Henderson 8411400516SLaurent Vivier cpu_exec_start(cs); 8511400516SLaurent Vivier trapnr = cpu_exec(cs); 8611400516SLaurent Vivier cpu_exec_end(cs); 8711400516SLaurent Vivier process_queued_cpu_work(cs); 8811400516SLaurent Vivier 8914db1899SRichard Henderson arch_interrupt = true; 9011400516SLaurent Vivier switch (trapnr) { 9111400516SLaurent Vivier case POWERPC_EXCP_NONE: 9211400516SLaurent Vivier /* Just go on */ 9311400516SLaurent Vivier break; 9411400516SLaurent Vivier case POWERPC_EXCP_CRITICAL: /* Critical input */ 9511400516SLaurent Vivier cpu_abort(cs, "Critical interrupt while in user mode. " 9611400516SLaurent Vivier "Aborting\n"); 9711400516SLaurent Vivier break; 9811400516SLaurent Vivier case POWERPC_EXCP_MCHECK: /* Machine check exception */ 9911400516SLaurent Vivier cpu_abort(cs, "Machine check exception while in user mode. " 10011400516SLaurent Vivier "Aborting\n"); 10111400516SLaurent Vivier break; 10211400516SLaurent Vivier case POWERPC_EXCP_DSI: /* Data storage exception */ 10311400516SLaurent Vivier /* XXX: check this. Seems bugged */ 10411400516SLaurent Vivier switch (env->error_code & 0xFF000000) { 10511400516SLaurent Vivier case 0x40000000: 10611400516SLaurent Vivier case 0x42000000: 10711400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 10811400516SLaurent Vivier info.si_errno = 0; 10911400516SLaurent Vivier info.si_code = TARGET_SEGV_MAPERR; 11011400516SLaurent Vivier break; 11111400516SLaurent Vivier case 0x04000000: 11211400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 11311400516SLaurent Vivier info.si_errno = 0; 11411400516SLaurent Vivier info.si_code = TARGET_ILL_ILLADR; 11511400516SLaurent Vivier break; 11611400516SLaurent Vivier case 0x08000000: 11711400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 11811400516SLaurent Vivier info.si_errno = 0; 11911400516SLaurent Vivier info.si_code = TARGET_SEGV_ACCERR; 12011400516SLaurent Vivier break; 12111400516SLaurent Vivier default: 12211400516SLaurent Vivier /* Let's send a regular segfault... */ 12311400516SLaurent Vivier EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 12411400516SLaurent Vivier env->error_code); 12511400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 12611400516SLaurent Vivier info.si_errno = 0; 12711400516SLaurent Vivier info.si_code = TARGET_SEGV_MAPERR; 12811400516SLaurent Vivier break; 12911400516SLaurent Vivier } 13011400516SLaurent Vivier info._sifields._sigfault._addr = env->spr[SPR_DAR]; 13111400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 13211400516SLaurent Vivier break; 13311400516SLaurent Vivier case POWERPC_EXCP_ISI: /* Instruction storage exception */ 13411400516SLaurent Vivier /* XXX: check this */ 13511400516SLaurent Vivier switch (env->error_code & 0xFF000000) { 13611400516SLaurent Vivier case 0x40000000: 13711400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 13811400516SLaurent Vivier info.si_errno = 0; 13911400516SLaurent Vivier info.si_code = TARGET_SEGV_MAPERR; 14011400516SLaurent Vivier break; 14111400516SLaurent Vivier case 0x10000000: 14211400516SLaurent Vivier case 0x08000000: 14311400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 14411400516SLaurent Vivier info.si_errno = 0; 14511400516SLaurent Vivier info.si_code = TARGET_SEGV_ACCERR; 14611400516SLaurent Vivier break; 14711400516SLaurent Vivier default: 14811400516SLaurent Vivier /* Let's send a regular segfault... */ 14911400516SLaurent Vivier EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 15011400516SLaurent Vivier env->error_code); 15111400516SLaurent Vivier info.si_signo = TARGET_SIGSEGV; 15211400516SLaurent Vivier info.si_errno = 0; 15311400516SLaurent Vivier info.si_code = TARGET_SEGV_MAPERR; 15411400516SLaurent Vivier break; 15511400516SLaurent Vivier } 15611400516SLaurent Vivier info._sifields._sigfault._addr = env->nip - 4; 15711400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 15811400516SLaurent Vivier break; 15911400516SLaurent Vivier case POWERPC_EXCP_EXTERNAL: /* External input */ 16011400516SLaurent Vivier cpu_abort(cs, "External interrupt while in user mode. " 16111400516SLaurent Vivier "Aborting\n"); 16211400516SLaurent Vivier break; 16311400516SLaurent Vivier case POWERPC_EXCP_ALIGN: /* Alignment exception */ 16411400516SLaurent Vivier /* XXX: check this */ 16511400516SLaurent Vivier info.si_signo = TARGET_SIGBUS; 16611400516SLaurent Vivier info.si_errno = 0; 16711400516SLaurent Vivier info.si_code = TARGET_BUS_ADRALN; 16811400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 16911400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 17011400516SLaurent Vivier break; 17111400516SLaurent Vivier case POWERPC_EXCP_PROGRAM: /* Program exception */ 17211400516SLaurent Vivier case POWERPC_EXCP_HV_EMU: /* HV emulation */ 17311400516SLaurent Vivier /* XXX: check this */ 17411400516SLaurent Vivier switch (env->error_code & ~0xF) { 17511400516SLaurent Vivier case POWERPC_EXCP_FP: 17611400516SLaurent Vivier info.si_signo = TARGET_SIGFPE; 17711400516SLaurent Vivier info.si_errno = 0; 17811400516SLaurent Vivier switch (env->error_code & 0xF) { 17911400516SLaurent Vivier case POWERPC_EXCP_FP_OX: 18011400516SLaurent Vivier info.si_code = TARGET_FPE_FLTOVF; 18111400516SLaurent Vivier break; 18211400516SLaurent Vivier case POWERPC_EXCP_FP_UX: 18311400516SLaurent Vivier info.si_code = TARGET_FPE_FLTUND; 18411400516SLaurent Vivier break; 18511400516SLaurent Vivier case POWERPC_EXCP_FP_ZX: 18611400516SLaurent Vivier case POWERPC_EXCP_FP_VXZDZ: 18711400516SLaurent Vivier info.si_code = TARGET_FPE_FLTDIV; 18811400516SLaurent Vivier break; 18911400516SLaurent Vivier case POWERPC_EXCP_FP_XX: 19011400516SLaurent Vivier info.si_code = TARGET_FPE_FLTRES; 19111400516SLaurent Vivier break; 19211400516SLaurent Vivier case POWERPC_EXCP_FP_VXSOFT: 19311400516SLaurent Vivier info.si_code = TARGET_FPE_FLTINV; 19411400516SLaurent Vivier break; 19511400516SLaurent Vivier case POWERPC_EXCP_FP_VXSNAN: 19611400516SLaurent Vivier case POWERPC_EXCP_FP_VXISI: 19711400516SLaurent Vivier case POWERPC_EXCP_FP_VXIDI: 19811400516SLaurent Vivier case POWERPC_EXCP_FP_VXIMZ: 19911400516SLaurent Vivier case POWERPC_EXCP_FP_VXVC: 20011400516SLaurent Vivier case POWERPC_EXCP_FP_VXSQRT: 20111400516SLaurent Vivier case POWERPC_EXCP_FP_VXCVI: 20211400516SLaurent Vivier info.si_code = TARGET_FPE_FLTSUB; 20311400516SLaurent Vivier break; 20411400516SLaurent Vivier default: 20511400516SLaurent Vivier EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 20611400516SLaurent Vivier env->error_code); 20711400516SLaurent Vivier break; 20811400516SLaurent Vivier } 20911400516SLaurent Vivier break; 21011400516SLaurent Vivier case POWERPC_EXCP_INVAL: 21111400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 21211400516SLaurent Vivier info.si_errno = 0; 21311400516SLaurent Vivier switch (env->error_code & 0xF) { 21411400516SLaurent Vivier case POWERPC_EXCP_INVAL_INVAL: 21511400516SLaurent Vivier info.si_code = TARGET_ILL_ILLOPC; 21611400516SLaurent Vivier break; 21711400516SLaurent Vivier case POWERPC_EXCP_INVAL_LSWX: 21811400516SLaurent Vivier info.si_code = TARGET_ILL_ILLOPN; 21911400516SLaurent Vivier break; 22011400516SLaurent Vivier case POWERPC_EXCP_INVAL_SPR: 22111400516SLaurent Vivier info.si_code = TARGET_ILL_PRVREG; 22211400516SLaurent Vivier break; 22311400516SLaurent Vivier case POWERPC_EXCP_INVAL_FP: 22411400516SLaurent Vivier info.si_code = TARGET_ILL_COPROC; 22511400516SLaurent Vivier break; 22611400516SLaurent Vivier default: 22711400516SLaurent Vivier EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 22811400516SLaurent Vivier env->error_code & 0xF); 22911400516SLaurent Vivier info.si_code = TARGET_ILL_ILLADR; 23011400516SLaurent Vivier break; 23111400516SLaurent Vivier } 23211400516SLaurent Vivier break; 23311400516SLaurent Vivier case POWERPC_EXCP_PRIV: 23411400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 23511400516SLaurent Vivier info.si_errno = 0; 23611400516SLaurent Vivier switch (env->error_code & 0xF) { 23711400516SLaurent Vivier case POWERPC_EXCP_PRIV_OPC: 23811400516SLaurent Vivier info.si_code = TARGET_ILL_PRVOPC; 23911400516SLaurent Vivier break; 24011400516SLaurent Vivier case POWERPC_EXCP_PRIV_REG: 24111400516SLaurent Vivier info.si_code = TARGET_ILL_PRVREG; 24211400516SLaurent Vivier break; 24311400516SLaurent Vivier default: 24411400516SLaurent Vivier EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 24511400516SLaurent Vivier env->error_code & 0xF); 24611400516SLaurent Vivier info.si_code = TARGET_ILL_PRVOPC; 24711400516SLaurent Vivier break; 24811400516SLaurent Vivier } 24911400516SLaurent Vivier break; 25011400516SLaurent Vivier case POWERPC_EXCP_TRAP: 25111400516SLaurent Vivier cpu_abort(cs, "Tried to call a TRAP\n"); 25211400516SLaurent Vivier break; 25311400516SLaurent Vivier default: 25411400516SLaurent Vivier /* Should not happen ! */ 25511400516SLaurent Vivier cpu_abort(cs, "Unknown program exception (%02x)\n", 25611400516SLaurent Vivier env->error_code); 25711400516SLaurent Vivier break; 25811400516SLaurent Vivier } 25911400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 26011400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 26111400516SLaurent Vivier break; 26211400516SLaurent Vivier case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 26311400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 26411400516SLaurent Vivier info.si_errno = 0; 26511400516SLaurent Vivier info.si_code = TARGET_ILL_COPROC; 26611400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 26711400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 26811400516SLaurent Vivier break; 26911400516SLaurent Vivier case POWERPC_EXCP_SYSCALL: /* System call exception */ 2703c89b8d6SNicholas Piggin case POWERPC_EXCP_SYSCALL_VECTORED: 27111400516SLaurent Vivier cpu_abort(cs, "Syscall exception while in user mode. " 27211400516SLaurent Vivier "Aborting\n"); 27311400516SLaurent Vivier break; 27411400516SLaurent Vivier case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 27511400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 27611400516SLaurent Vivier info.si_errno = 0; 27711400516SLaurent Vivier info.si_code = TARGET_ILL_COPROC; 27811400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 27911400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 28011400516SLaurent Vivier break; 28111400516SLaurent Vivier case POWERPC_EXCP_DECR: /* Decrementer exception */ 28211400516SLaurent Vivier cpu_abort(cs, "Decrementer interrupt while in user mode. " 28311400516SLaurent Vivier "Aborting\n"); 28411400516SLaurent Vivier break; 28511400516SLaurent Vivier case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 28611400516SLaurent Vivier cpu_abort(cs, "Fix interval timer interrupt while in user mode. " 28711400516SLaurent Vivier "Aborting\n"); 28811400516SLaurent Vivier break; 28911400516SLaurent Vivier case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 29011400516SLaurent Vivier cpu_abort(cs, "Watchdog timer interrupt while in user mode. " 29111400516SLaurent Vivier "Aborting\n"); 29211400516SLaurent Vivier break; 29311400516SLaurent Vivier case POWERPC_EXCP_DTLB: /* Data TLB error */ 29411400516SLaurent Vivier cpu_abort(cs, "Data TLB exception while in user mode. " 29511400516SLaurent Vivier "Aborting\n"); 29611400516SLaurent Vivier break; 29711400516SLaurent Vivier case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 29811400516SLaurent Vivier cpu_abort(cs, "Instruction TLB exception while in user mode. " 29911400516SLaurent Vivier "Aborting\n"); 30011400516SLaurent Vivier break; 30111400516SLaurent Vivier case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 30211400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 30311400516SLaurent Vivier info.si_errno = 0; 30411400516SLaurent Vivier info.si_code = TARGET_ILL_COPROC; 30511400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 30611400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 30711400516SLaurent Vivier break; 30811400516SLaurent Vivier case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 30911400516SLaurent Vivier cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); 31011400516SLaurent Vivier break; 31111400516SLaurent Vivier case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 31211400516SLaurent Vivier cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); 31311400516SLaurent Vivier break; 31411400516SLaurent Vivier case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 31511400516SLaurent Vivier cpu_abort(cs, "Performance monitor exception not handled\n"); 31611400516SLaurent Vivier break; 31711400516SLaurent Vivier case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 31811400516SLaurent Vivier cpu_abort(cs, "Doorbell interrupt while in user mode. " 31911400516SLaurent Vivier "Aborting\n"); 32011400516SLaurent Vivier break; 32111400516SLaurent Vivier case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 32211400516SLaurent Vivier cpu_abort(cs, "Doorbell critical interrupt while in user mode. " 32311400516SLaurent Vivier "Aborting\n"); 32411400516SLaurent Vivier break; 32511400516SLaurent Vivier case POWERPC_EXCP_RESET: /* System reset exception */ 32611400516SLaurent Vivier cpu_abort(cs, "Reset interrupt while in user mode. " 32711400516SLaurent Vivier "Aborting\n"); 32811400516SLaurent Vivier break; 32911400516SLaurent Vivier case POWERPC_EXCP_DSEG: /* Data segment exception */ 33011400516SLaurent Vivier cpu_abort(cs, "Data segment exception while in user mode. " 33111400516SLaurent Vivier "Aborting\n"); 33211400516SLaurent Vivier break; 33311400516SLaurent Vivier case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 33411400516SLaurent Vivier cpu_abort(cs, "Instruction segment exception " 33511400516SLaurent Vivier "while in user mode. Aborting\n"); 33611400516SLaurent Vivier break; 33711400516SLaurent Vivier /* PowerPC 64 with hypervisor mode support */ 33811400516SLaurent Vivier case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 33911400516SLaurent Vivier cpu_abort(cs, "Hypervisor decrementer interrupt " 34011400516SLaurent Vivier "while in user mode. Aborting\n"); 34111400516SLaurent Vivier break; 34211400516SLaurent Vivier case POWERPC_EXCP_TRACE: /* Trace exception */ 34311400516SLaurent Vivier /* Nothing to do: 34411400516SLaurent Vivier * we use this exception to emulate step-by-step execution mode. 34511400516SLaurent Vivier */ 34611400516SLaurent Vivier break; 34711400516SLaurent Vivier /* PowerPC 64 with hypervisor mode support */ 34811400516SLaurent Vivier case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 34911400516SLaurent Vivier cpu_abort(cs, "Hypervisor data storage exception " 35011400516SLaurent Vivier "while in user mode. Aborting\n"); 35111400516SLaurent Vivier break; 35211400516SLaurent Vivier case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 35311400516SLaurent Vivier cpu_abort(cs, "Hypervisor instruction storage exception " 35411400516SLaurent Vivier "while in user mode. Aborting\n"); 35511400516SLaurent Vivier break; 35611400516SLaurent Vivier case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 35711400516SLaurent Vivier cpu_abort(cs, "Hypervisor data segment exception " 35811400516SLaurent Vivier "while in user mode. Aborting\n"); 35911400516SLaurent Vivier break; 36011400516SLaurent Vivier case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 36111400516SLaurent Vivier cpu_abort(cs, "Hypervisor instruction segment exception " 36211400516SLaurent Vivier "while in user mode. Aborting\n"); 36311400516SLaurent Vivier break; 36411400516SLaurent Vivier case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 36511400516SLaurent Vivier info.si_signo = TARGET_SIGILL; 36611400516SLaurent Vivier info.si_errno = 0; 36711400516SLaurent Vivier info.si_code = TARGET_ILL_COPROC; 36811400516SLaurent Vivier info._sifields._sigfault._addr = env->nip; 36911400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 37011400516SLaurent Vivier break; 37111400516SLaurent Vivier case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 37211400516SLaurent Vivier cpu_abort(cs, "Programmable interval timer interrupt " 37311400516SLaurent Vivier "while in user mode. Aborting\n"); 37411400516SLaurent Vivier break; 37511400516SLaurent Vivier case POWERPC_EXCP_IO: /* IO error exception */ 37611400516SLaurent Vivier cpu_abort(cs, "IO error exception while in user mode. " 37711400516SLaurent Vivier "Aborting\n"); 37811400516SLaurent Vivier break; 37911400516SLaurent Vivier case POWERPC_EXCP_RUNM: /* Run mode exception */ 38011400516SLaurent Vivier cpu_abort(cs, "Run mode exception while in user mode. " 38111400516SLaurent Vivier "Aborting\n"); 38211400516SLaurent Vivier break; 38311400516SLaurent Vivier case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 38411400516SLaurent Vivier cpu_abort(cs, "Emulation trap exception not handled\n"); 38511400516SLaurent Vivier break; 38611400516SLaurent Vivier case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 38711400516SLaurent Vivier cpu_abort(cs, "Instruction fetch TLB exception " 38811400516SLaurent Vivier "while in user-mode. Aborting"); 38911400516SLaurent Vivier break; 39011400516SLaurent Vivier case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 39111400516SLaurent Vivier cpu_abort(cs, "Data load TLB exception while in user-mode. " 39211400516SLaurent Vivier "Aborting"); 39311400516SLaurent Vivier break; 39411400516SLaurent Vivier case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 39511400516SLaurent Vivier cpu_abort(cs, "Data store TLB exception while in user-mode. " 39611400516SLaurent Vivier "Aborting"); 39711400516SLaurent Vivier break; 39811400516SLaurent Vivier case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 39911400516SLaurent Vivier cpu_abort(cs, "Floating-point assist exception not handled\n"); 40011400516SLaurent Vivier break; 40111400516SLaurent Vivier case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 40211400516SLaurent Vivier cpu_abort(cs, "Instruction address breakpoint exception " 40311400516SLaurent Vivier "not handled\n"); 40411400516SLaurent Vivier break; 40511400516SLaurent Vivier case POWERPC_EXCP_SMI: /* System management interrupt */ 40611400516SLaurent Vivier cpu_abort(cs, "System management interrupt while in user mode. " 40711400516SLaurent Vivier "Aborting\n"); 40811400516SLaurent Vivier break; 40911400516SLaurent Vivier case POWERPC_EXCP_THERM: /* Thermal interrupt */ 41011400516SLaurent Vivier cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " 41111400516SLaurent Vivier "Aborting\n"); 41211400516SLaurent Vivier break; 41311400516SLaurent Vivier case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 41411400516SLaurent Vivier cpu_abort(cs, "Performance monitor exception not handled\n"); 41511400516SLaurent Vivier break; 41611400516SLaurent Vivier case POWERPC_EXCP_VPUA: /* Vector assist exception */ 41711400516SLaurent Vivier cpu_abort(cs, "Vector assist exception not handled\n"); 41811400516SLaurent Vivier break; 41911400516SLaurent Vivier case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 42011400516SLaurent Vivier cpu_abort(cs, "Soft patch exception not handled\n"); 42111400516SLaurent Vivier break; 42211400516SLaurent Vivier case POWERPC_EXCP_MAINT: /* Maintenance exception */ 42311400516SLaurent Vivier cpu_abort(cs, "Maintenance exception while in user mode. " 42411400516SLaurent Vivier "Aborting\n"); 42511400516SLaurent Vivier break; 42611400516SLaurent Vivier case POWERPC_EXCP_STOP: /* stop translation */ 42711400516SLaurent Vivier /* We did invalidate the instruction cache. Go on */ 42811400516SLaurent Vivier break; 42911400516SLaurent Vivier case POWERPC_EXCP_BRANCH: /* branch instruction: */ 43011400516SLaurent Vivier /* We just stopped because of a branch. Go on */ 43111400516SLaurent Vivier break; 43211400516SLaurent Vivier case POWERPC_EXCP_SYSCALL_USER: 43311400516SLaurent Vivier /* system call in user-mode emulation */ 43411400516SLaurent Vivier /* WARNING: 43511400516SLaurent Vivier * PPC ABI uses overflow flag in cr0 to signal an error 43611400516SLaurent Vivier * in syscalls. 43711400516SLaurent Vivier */ 43811400516SLaurent Vivier env->crf[0] &= ~0x1; 43911400516SLaurent Vivier env->nip += 4; 44011400516SLaurent Vivier ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 44111400516SLaurent Vivier env->gpr[5], env->gpr[6], env->gpr[7], 44211400516SLaurent Vivier env->gpr[8], 0, 0); 44311400516SLaurent Vivier if (ret == -TARGET_ERESTARTSYS) { 44411400516SLaurent Vivier env->nip -= 4; 44511400516SLaurent Vivier break; 44611400516SLaurent Vivier } 44711400516SLaurent Vivier if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 44811400516SLaurent Vivier /* Returning from a successful sigreturn syscall. 44911400516SLaurent Vivier Avoid corrupting register state. */ 45011400516SLaurent Vivier break; 45111400516SLaurent Vivier } 45211400516SLaurent Vivier if (ret > (target_ulong)(-515)) { 45311400516SLaurent Vivier env->crf[0] |= 0x1; 45411400516SLaurent Vivier ret = -ret; 45511400516SLaurent Vivier } 45611400516SLaurent Vivier env->gpr[3] = ret; 45711400516SLaurent Vivier break; 45811400516SLaurent Vivier case EXCP_DEBUG: 459b10089a1SPeter Maydell info.si_signo = TARGET_SIGTRAP; 46011400516SLaurent Vivier info.si_errno = 0; 46111400516SLaurent Vivier info.si_code = TARGET_TRAP_BRKPT; 46211400516SLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 46311400516SLaurent Vivier break; 46411400516SLaurent Vivier case EXCP_INTERRUPT: 46511400516SLaurent Vivier /* just indicate that signals should be handled asap */ 46611400516SLaurent Vivier break; 46711400516SLaurent Vivier case EXCP_ATOMIC: 46811400516SLaurent Vivier cpu_exec_step_atomic(cs); 46914db1899SRichard Henderson arch_interrupt = false; 47011400516SLaurent Vivier break; 47111400516SLaurent Vivier default: 47211400516SLaurent Vivier cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr); 47311400516SLaurent Vivier break; 47411400516SLaurent Vivier } 47511400516SLaurent Vivier process_pending_signals(env); 47614db1899SRichard Henderson 47714db1899SRichard Henderson /* Most of the traps imply a transition through kernel mode, 47814db1899SRichard Henderson * which implies an REI instruction has been executed. Which 47914db1899SRichard Henderson * means that RX and LOCK_ADDR should be cleared. But there 48014db1899SRichard Henderson * are a few exceptions for traps internal to QEMU. 48114db1899SRichard Henderson */ 48214db1899SRichard Henderson if (arch_interrupt) { 48314db1899SRichard Henderson env->reserve_addr = -1; 48414db1899SRichard Henderson } 48511400516SLaurent Vivier } 48611400516SLaurent Vivier } 48711400516SLaurent Vivier 488cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 489cd71c089SLaurent Vivier { 49011400516SLaurent Vivier int i; 49111400516SLaurent Vivier 49211400516SLaurent Vivier #if defined(TARGET_PPC64) 49311400516SLaurent Vivier int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF; 49411400516SLaurent Vivier #if defined(TARGET_ABI32) 495*75da4997SRichard Henderson ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag)); 49611400516SLaurent Vivier #else 497*75da4997SRichard Henderson ppc_store_msr(env, env->msr | (target_ulong)1 << flag); 49811400516SLaurent Vivier #endif 49911400516SLaurent Vivier #endif 500*75da4997SRichard Henderson 50111400516SLaurent Vivier env->nip = regs->nip; 50211400516SLaurent Vivier for(i = 0; i < 32; i++) { 50311400516SLaurent Vivier env->gpr[i] = regs->gpr[i]; 50411400516SLaurent Vivier } 505cd71c089SLaurent Vivier } 506