2
0

user-exec.c 19 KB

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