My QEMU builds
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

677 lines
21 KiB

  1. /*
  2. * User emulator execution
  3. *
  4. * Copyright (c) 2003-2005 Fabrice Bellard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library 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 GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "cpu.h"
  21. #include "disas/disas.h"
  22. #include "tcg.h"
  23. #include "qemu/bitops.h"
  24. #include "exec/cpu_ldst.h"
  25. #include "translate-all.h"
  26. #undef EAX
  27. #undef ECX
  28. #undef EDX
  29. #undef EBX
  30. #undef ESP
  31. #undef EBP
  32. #undef ESI
  33. #undef EDI
  34. #undef EIP
  35. #ifdef __linux__
  36. #include <sys/ucontext.h>
  37. #endif
  38. //#define DEBUG_SIGNAL
  39. static void exception_action(CPUState *cpu)
  40. {
  41. #if defined(TARGET_I386)
  42. X86CPU *x86_cpu = X86_CPU(cpu);
  43. CPUX86State *env1 = &x86_cpu->env;
  44. raise_exception_err(env1, cpu->exception_index, env1->error_code);
  45. #else
  46. cpu_loop_exit(cpu);
  47. #endif
  48. }
  49. /* exit the current TB from a signal handler. The host registers are
  50. restored in a state compatible with the CPU emulator
  51. */
  52. void cpu_resume_from_signal(CPUState *cpu, void *puc)
  53. {
  54. #ifdef __linux__
  55. struct ucontext *uc = puc;
  56. #elif defined(__OpenBSD__)
  57. struct sigcontext *uc = puc;
  58. #endif
  59. if (puc) {
  60. /* XXX: use siglongjmp ? */
  61. #ifdef __linux__
  62. #ifdef __ia64
  63. sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
  64. #else
  65. sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
  66. #endif
  67. #elif defined(__OpenBSD__)
  68. sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
  69. #endif
  70. }
  71. cpu->exception_index = -1;
  72. siglongjmp(cpu->jmp_env, 1);
  73. }
  74. /* 'pc' is the host PC at which the exception was raised. 'address' is
  75. the effective address of the memory exception. 'is_write' is 1 if a
  76. write caused the exception and otherwise 0'. 'old_set' is the
  77. signal set which should be restored */
  78. static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
  79. int is_write, sigset_t *old_set,
  80. void *puc)
  81. {
  82. CPUState *cpu;
  83. CPUClass *cc;
  84. int ret;
  85. #if defined(DEBUG_SIGNAL)
  86. printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  87. pc, address, is_write, *(unsigned long *)old_set);
  88. #endif
  89. /* XXX: locking issue */
  90. if (is_write && h2g_valid(address)
  91. && page_unprotect(h2g(address), pc, puc)) {
  92. return 1;
  93. }
  94. /* Convert forcefully to guest address space, invalid addresses
  95. are still valid segv ones */
  96. address = h2g_nocheck(address);
  97. cpu = current_cpu;
  98. cc = CPU_GET_CLASS(cpu);
  99. /* see if it is an MMU fault */
  100. g_assert(cc->handle_mmu_fault);
  101. ret = cc->handle_mmu_fault(cpu, address, is_write, MMU_USER_IDX);
  102. if (ret < 0) {
  103. return 0; /* not an MMU fault */
  104. }
  105. if (ret == 0) {
  106. return 1; /* the MMU fault was handled without causing real CPU fault */
  107. }
  108. /* now we have a real cpu fault */
  109. cpu_restore_state(cpu, pc);
  110. /* we restore the process signal mask as the sigreturn should
  111. do it (XXX: use sigsetjmp) */
  112. sigprocmask(SIG_SETMASK, old_set, NULL);
  113. exception_action(cpu);
  114. /* never comes here */
  115. return 1;
  116. }
  117. #if defined(__i386__)
  118. #if defined(__APPLE__)
  119. #include <sys/ucontext.h>
  120. #define EIP_sig(context) (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
  121. #define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
  122. #define ERROR_sig(context) ((context)->uc_mcontext->es.err)
  123. #define MASK_sig(context) ((context)->uc_sigmask)
  124. #elif defined(__NetBSD__)
  125. #include <ucontext.h>
  126. #define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
  127. #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
  128. #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
  129. #define MASK_sig(context) ((context)->uc_sigmask)
  130. #elif defined(__FreeBSD__) || defined(__DragonFly__)
  131. #include <ucontext.h>
  132. #define EIP_sig(context) (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
  133. #define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
  134. #define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
  135. #define MASK_sig(context) ((context)->uc_sigmask)
  136. #elif defined(__OpenBSD__)
  137. #define EIP_sig(context) ((context)->sc_eip)
  138. #define TRAP_sig(context) ((context)->sc_trapno)
  139. #define ERROR_sig(context) ((context)->sc_err)
  140. #define MASK_sig(context) ((context)->sc_mask)
  141. #else
  142. #define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
  143. #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
  144. #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
  145. #define MASK_sig(context) ((context)->uc_sigmask)
  146. #endif
  147. int cpu_signal_handler(int host_signum, void *pinfo,
  148. void *puc)
  149. {
  150. siginfo_t *info = pinfo;
  151. #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  152. ucontext_t *uc = puc;
  153. #elif defined(__OpenBSD__)
  154. struct sigcontext *uc = puc;
  155. #else
  156. struct ucontext *uc = puc;
  157. #endif
  158. unsigned long pc;
  159. int trapno;
  160. #ifndef REG_EIP
  161. /* for glibc 2.1 */
  162. #define REG_EIP EIP
  163. #define REG_ERR ERR
  164. #define REG_TRAPNO TRAPNO
  165. #endif
  166. pc = EIP_sig(uc);
  167. trapno = TRAP_sig(uc);
  168. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  169. trapno == 0xe ?
  170. (ERROR_sig(uc) >> 1) & 1 : 0,
  171. &MASK_sig(uc), puc);
  172. }
  173. #elif defined(__x86_64__)
  174. #ifdef __NetBSD__
  175. #define PC_sig(context) _UC_MACHINE_PC(context)
  176. #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
  177. #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
  178. #define MASK_sig(context) ((context)->uc_sigmask)
  179. #elif defined(__OpenBSD__)
  180. #define PC_sig(context) ((context)->sc_rip)
  181. #define TRAP_sig(context) ((context)->sc_trapno)
  182. #define ERROR_sig(context) ((context)->sc_err)
  183. #define MASK_sig(context) ((context)->sc_mask)
  184. #elif defined(__FreeBSD__) || defined(__DragonFly__)
  185. #include <ucontext.h>
  186. #define PC_sig(context) (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
  187. #define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
  188. #define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
  189. #define MASK_sig(context) ((context)->uc_sigmask)
  190. #else
  191. #define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
  192. #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
  193. #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
  194. #define MASK_sig(context) ((context)->uc_sigmask)
  195. #endif
  196. int cpu_signal_handler(int host_signum, void *pinfo,
  197. void *puc)
  198. {
  199. siginfo_t *info = pinfo;
  200. unsigned long pc;
  201. #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  202. ucontext_t *uc = puc;
  203. #elif defined(__OpenBSD__)
  204. struct sigcontext *uc = puc;
  205. #else
  206. struct ucontext *uc = puc;
  207. #endif
  208. pc = PC_sig(uc);
  209. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  210. TRAP_sig(uc) == 0xe ?
  211. (ERROR_sig(uc) >> 1) & 1 : 0,
  212. &MASK_sig(uc), puc);
  213. }
  214. #elif defined(_ARCH_PPC)
  215. /***********************************************************************
  216. * signal context platform-specific definitions
  217. * From Wine
  218. */
  219. #ifdef linux
  220. /* All Registers access - only for local access */
  221. #define REG_sig(reg_name, context) \
  222. ((context)->uc_mcontext.regs->reg_name)
  223. /* Gpr Registers access */
  224. #define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
  225. /* Program counter */
  226. #define IAR_sig(context) REG_sig(nip, context)
  227. /* Machine State Register (Supervisor) */
  228. #define MSR_sig(context) REG_sig(msr, context)
  229. /* Count register */
  230. #define CTR_sig(context) REG_sig(ctr, context)
  231. /* User's integer exception register */
  232. #define XER_sig(context) REG_sig(xer, context)
  233. /* Link register */
  234. #define LR_sig(context) REG_sig(link, context)
  235. /* Condition register */
  236. #define CR_sig(context) REG_sig(ccr, context)
  237. /* Float Registers access */
  238. #define FLOAT_sig(reg_num, context) \
  239. (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
  240. #define FPSCR_sig(context) \
  241. (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
  242. /* Exception Registers access */
  243. #define DAR_sig(context) REG_sig(dar, context)
  244. #define DSISR_sig(context) REG_sig(dsisr, context)
  245. #define TRAP_sig(context) REG_sig(trap, context)
  246. #endif /* linux */
  247. #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  248. #include <ucontext.h>
  249. #define IAR_sig(context) ((context)->uc_mcontext.mc_srr0)
  250. #define MSR_sig(context) ((context)->uc_mcontext.mc_srr1)
  251. #define CTR_sig(context) ((context)->uc_mcontext.mc_ctr)
  252. #define XER_sig(context) ((context)->uc_mcontext.mc_xer)
  253. #define LR_sig(context) ((context)->uc_mcontext.mc_lr)
  254. #define CR_sig(context) ((context)->uc_mcontext.mc_cr)
  255. /* Exception Registers access */
  256. #define DAR_sig(context) ((context)->uc_mcontext.mc_dar)
  257. #define DSISR_sig(context) ((context)->uc_mcontext.mc_dsisr)
  258. #define TRAP_sig(context) ((context)->uc_mcontext.mc_exc)
  259. #endif /* __FreeBSD__|| __FreeBSD_kernel__ */
  260. #ifdef __APPLE__
  261. #include <sys/ucontext.h>
  262. typedef struct ucontext SIGCONTEXT;
  263. /* All Registers access - only for local access */
  264. #define REG_sig(reg_name, context) \
  265. ((context)->uc_mcontext->ss.reg_name)
  266. #define FLOATREG_sig(reg_name, context) \
  267. ((context)->uc_mcontext->fs.reg_name)
  268. #define EXCEPREG_sig(reg_name, context) \
  269. ((context)->uc_mcontext->es.reg_name)
  270. #define VECREG_sig(reg_name, context) \
  271. ((context)->uc_mcontext->vs.reg_name)
  272. /* Gpr Registers access */
  273. #define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
  274. /* Program counter */
  275. #define IAR_sig(context) REG_sig(srr0, context)
  276. /* Machine State Register (Supervisor) */
  277. #define MSR_sig(context) REG_sig(srr1, context)
  278. #define CTR_sig(context) REG_sig(ctr, context)
  279. /* Link register */
  280. #define XER_sig(context) REG_sig(xer, context)
  281. /* User's integer exception register */
  282. #define LR_sig(context) REG_sig(lr, context)
  283. /* Condition register */
  284. #define CR_sig(context) REG_sig(cr, context)
  285. /* Float Registers access */
  286. #define FLOAT_sig(reg_num, context) \
  287. FLOATREG_sig(fpregs[reg_num], context)
  288. #define FPSCR_sig(context) \
  289. ((double)FLOATREG_sig(fpscr, context))
  290. /* Exception Registers access */
  291. /* Fault registers for coredump */
  292. #define DAR_sig(context) EXCEPREG_sig(dar, context)
  293. #define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
  294. /* number of powerpc exception taken */
  295. #define TRAP_sig(context) EXCEPREG_sig(exception, context)
  296. #endif /* __APPLE__ */
  297. int cpu_signal_handler(int host_signum, void *pinfo,
  298. void *puc)
  299. {
  300. siginfo_t *info = pinfo;
  301. #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  302. ucontext_t *uc = puc;
  303. #else
  304. struct ucontext *uc = puc;
  305. #endif
  306. unsigned long pc;
  307. int is_write;
  308. pc = IAR_sig(uc);
  309. is_write = 0;
  310. #if 0
  311. /* ppc 4xx case */
  312. if (DSISR_sig(uc) & 0x00800000) {
  313. is_write = 1;
  314. }
  315. #else
  316. if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
  317. is_write = 1;
  318. }
  319. #endif
  320. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  321. is_write, &uc->uc_sigmask, puc);
  322. }
  323. #elif defined(__alpha__)
  324. int cpu_signal_handler(int host_signum, void *pinfo,
  325. void *puc)
  326. {
  327. siginfo_t *info = pinfo;
  328. struct ucontext *uc = puc;
  329. uint32_t *pc = uc->uc_mcontext.sc_pc;
  330. uint32_t insn = *pc;
  331. int is_write = 0;
  332. /* XXX: need kernel patch to get write flag faster */
  333. switch (insn >> 26) {
  334. case 0x0d: /* stw */
  335. case 0x0e: /* stb */
  336. case 0x0f: /* stq_u */
  337. case 0x24: /* stf */
  338. case 0x25: /* stg */
  339. case 0x26: /* sts */
  340. case 0x27: /* stt */
  341. case 0x2c: /* stl */
  342. case 0x2d: /* stq */
  343. case 0x2e: /* stl_c */
  344. case 0x2f: /* stq_c */
  345. is_write = 1;
  346. }
  347. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  348. is_write, &uc->uc_sigmask, puc);
  349. }
  350. #elif defined(__sparc__)
  351. int cpu_signal_handler(int host_signum, void *pinfo,
  352. void *puc)
  353. {
  354. siginfo_t *info = pinfo;
  355. int is_write;
  356. uint32_t insn;
  357. #if !defined(__arch64__) || defined(CONFIG_SOLARIS)
  358. uint32_t *regs = (uint32_t *)(info + 1);
  359. void *sigmask = (regs + 20);
  360. /* XXX: is there a standard glibc define ? */
  361. unsigned long pc = regs[1];
  362. #else
  363. #ifdef __linux__
  364. struct sigcontext *sc = puc;
  365. unsigned long pc = sc->sigc_regs.tpc;
  366. void *sigmask = (void *)sc->sigc_mask;
  367. #elif defined(__OpenBSD__)
  368. struct sigcontext *uc = puc;
  369. unsigned long pc = uc->sc_pc;
  370. void *sigmask = (void *)(long)uc->sc_mask;
  371. #elif defined(__NetBSD__)
  372. ucontext_t *uc = puc;
  373. unsigned long pc = _UC_MACHINE_PC(uc);
  374. void *sigmask = (void *)&uc->uc_sigmask;
  375. #endif
  376. #endif
  377. /* XXX: need kernel patch to get write flag faster */
  378. is_write = 0;
  379. insn = *(uint32_t *)pc;
  380. if ((insn >> 30) == 3) {
  381. switch ((insn >> 19) & 0x3f) {
  382. case 0x05: /* stb */
  383. case 0x15: /* stba */
  384. case 0x06: /* sth */
  385. case 0x16: /* stha */
  386. case 0x04: /* st */
  387. case 0x14: /* sta */
  388. case 0x07: /* std */
  389. case 0x17: /* stda */
  390. case 0x0e: /* stx */
  391. case 0x1e: /* stxa */
  392. case 0x24: /* stf */
  393. case 0x34: /* stfa */
  394. case 0x27: /* stdf */
  395. case 0x37: /* stdfa */
  396. case 0x26: /* stqf */
  397. case 0x36: /* stqfa */
  398. case 0x25: /* stfsr */
  399. case 0x3c: /* casa */
  400. case 0x3e: /* casxa */
  401. is_write = 1;
  402. break;
  403. }
  404. }
  405. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  406. is_write, sigmask, NULL);
  407. }
  408. #elif defined(__arm__)
  409. #if defined(__NetBSD__)
  410. #include <ucontext.h>
  411. #endif
  412. int cpu_signal_handler(int host_signum, void *pinfo,
  413. void *puc)
  414. {
  415. siginfo_t *info = pinfo;
  416. #if defined(__NetBSD__)
  417. ucontext_t *uc = puc;
  418. #else
  419. struct ucontext *uc = puc;
  420. #endif
  421. unsigned long pc;
  422. int is_write;
  423. #if defined(__NetBSD__)
  424. pc = uc->uc_mcontext.__gregs[_REG_R15];
  425. #elif defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
  426. pc = uc->uc_mcontext.gregs[R15];
  427. #else
  428. pc = uc->uc_mcontext.arm_pc;
  429. #endif
  430. /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or
  431. * later processor; on v5 we will always report this as a read).
  432. */
  433. is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
  434. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  435. is_write,
  436. &uc->uc_sigmask, puc);
  437. }
  438. #elif defined(__aarch64__)
  439. int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
  440. {
  441. siginfo_t *info = pinfo;
  442. struct ucontext *uc = puc;
  443. uintptr_t pc = uc->uc_mcontext.pc;
  444. uint32_t insn = *(uint32_t *)pc;
  445. bool is_write;
  446. /* XXX: need kernel patch to get write flag faster. */
  447. is_write = ( (insn & 0xbfff0000) == 0x0c000000 /* C3.3.1 */
  448. || (insn & 0xbfe00000) == 0x0c800000 /* C3.3.2 */
  449. || (insn & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */
  450. || (insn & 0xbfc00000) == 0x0d800000 /* C3.3.4 */
  451. || (insn & 0x3f400000) == 0x08000000 /* C3.3.6 */
  452. || (insn & 0x3bc00000) == 0x39000000 /* C3.3.13 */
  453. || (insn & 0x3fc00000) == 0x3d800000 /* ... 128bit */
  454. /* Ingore bits 10, 11 & 21, controlling indexing. */
  455. || (insn & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */
  456. || (insn & 0x3fe00000) == 0x3c800000 /* ... 128bit */
  457. /* Ignore bits 23 & 24, controlling indexing. */
  458. || (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
  459. return handle_cpu_signal(pc, (uintptr_t)info->si_addr,
  460. is_write, &uc->uc_sigmask, puc);
  461. }
  462. #elif defined(__mc68000)
  463. int cpu_signal_handler(int host_signum, void *pinfo,
  464. void *puc)
  465. {
  466. siginfo_t *info = pinfo;
  467. struct ucontext *uc = puc;
  468. unsigned long pc;
  469. int is_write;
  470. pc = uc->uc_mcontext.gregs[16];
  471. /* XXX: compute is_write */
  472. is_write = 0;
  473. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  474. is_write,
  475. &uc->uc_sigmask, puc);
  476. }
  477. #elif defined(__ia64)
  478. #ifndef __ISR_VALID
  479. /* This ought to be in <bits/siginfo.h>... */
  480. # define __ISR_VALID 1
  481. #endif
  482. int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
  483. {
  484. siginfo_t *info = pinfo;
  485. struct ucontext *uc = puc;
  486. unsigned long ip;
  487. int is_write = 0;
  488. ip = uc->uc_mcontext.sc_ip;
  489. switch (host_signum) {
  490. case SIGILL:
  491. case SIGFPE:
  492. case SIGSEGV:
  493. case SIGBUS:
  494. case SIGTRAP:
  495. if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
  496. /* ISR.W (write-access) is bit 33: */
  497. is_write = (info->si_isr >> 33) & 1;
  498. }
  499. break;
  500. default:
  501. break;
  502. }
  503. return handle_cpu_signal(ip, (unsigned long)info->si_addr,
  504. is_write,
  505. (sigset_t *)&uc->uc_sigmask, puc);
  506. }
  507. #elif defined(__s390__)
  508. int cpu_signal_handler(int host_signum, void *pinfo,
  509. void *puc)
  510. {
  511. siginfo_t *info = pinfo;
  512. struct ucontext *uc = puc;
  513. unsigned long pc;
  514. uint16_t *pinsn;
  515. int is_write = 0;
  516. pc = uc->uc_mcontext.psw.addr;
  517. /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
  518. of the normal 2 arguments. The 3rd argument contains the "int_code"
  519. from the hardware which does in fact contain the is_write value.
  520. The rt signal handler, as far as I can tell, does not give this value
  521. at all. Not that we could get to it from here even if it were. */
  522. /* ??? This is not even close to complete, since it ignores all
  523. of the read-modify-write instructions. */
  524. pinsn = (uint16_t *)pc;
  525. switch (pinsn[0] >> 8) {
  526. case 0x50: /* ST */
  527. case 0x42: /* STC */
  528. case 0x40: /* STH */
  529. is_write = 1;
  530. break;
  531. case 0xc4: /* RIL format insns */
  532. switch (pinsn[0] & 0xf) {
  533. case 0xf: /* STRL */
  534. case 0xb: /* STGRL */
  535. case 0x7: /* STHRL */
  536. is_write = 1;
  537. }
  538. break;
  539. case 0xe3: /* RXY format insns */
  540. switch (pinsn[2] & 0xff) {
  541. case 0x50: /* STY */
  542. case 0x24: /* STG */
  543. case 0x72: /* STCY */
  544. case 0x70: /* STHY */
  545. case 0x8e: /* STPQ */
  546. case 0x3f: /* STRVH */
  547. case 0x3e: /* STRV */
  548. case 0x2f: /* STRVG */
  549. is_write = 1;
  550. }
  551. break;
  552. }
  553. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  554. is_write, &uc->uc_sigmask, puc);
  555. }
  556. #elif defined(__mips__)
  557. int cpu_signal_handler(int host_signum, void *pinfo,
  558. void *puc)
  559. {
  560. siginfo_t *info = pinfo;
  561. struct ucontext *uc = puc;
  562. greg_t pc = uc->uc_mcontext.pc;
  563. int is_write;
  564. /* XXX: compute is_write */
  565. is_write = 0;
  566. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  567. is_write, &uc->uc_sigmask, puc);
  568. }
  569. #elif defined(__hppa__)
  570. int cpu_signal_handler(int host_signum, void *pinfo,
  571. void *puc)
  572. {
  573. siginfo_t *info = pinfo;
  574. struct ucontext *uc = puc;
  575. unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
  576. uint32_t insn = *(uint32_t *)pc;
  577. int is_write = 0;
  578. /* XXX: need kernel patch to get write flag faster. */
  579. switch (insn >> 26) {
  580. case 0x1a: /* STW */
  581. case 0x19: /* STH */
  582. case 0x18: /* STB */
  583. case 0x1b: /* STWM */
  584. is_write = 1;
  585. break;
  586. case 0x09: /* CSTWX, FSTWX, FSTWS */
  587. case 0x0b: /* CSTDX, FSTDX, FSTDS */
  588. /* Distinguish from coprocessor load ... */
  589. is_write = (insn >> 9) & 1;
  590. break;
  591. case 0x03:
  592. switch ((insn >> 6) & 15) {
  593. case 0xa: /* STWS */
  594. case 0x9: /* STHS */
  595. case 0x8: /* STBS */
  596. case 0xe: /* STWAS */
  597. case 0xc: /* STBYS */
  598. is_write = 1;
  599. }
  600. break;
  601. }
  602. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  603. is_write, &uc->uc_sigmask, puc);
  604. }
  605. #else
  606. #error host CPU specific signal handler needed
  607. #endif