2
0

cpu_loop.c 16 KB

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