2
0

user-exec.c 20 KB

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