user-exec.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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 "dyngen-exec.h"
  22. #include "disas.h"
  23. #include "tcg.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 *env1)
  39. {
  40. #if defined(TARGET_I386)
  41. raise_exception_err_env(env1, env1->exception_index, env1->error_code);
  42. #else
  43. cpu_loop_exit(env1);
  44. #endif
  45. }
  46. /* exit the current TB from a signal handler. The host registers are
  47. restored in a state compatible with the CPU emulator
  48. */
  49. void cpu_resume_from_signal(CPUState *env1, void *puc)
  50. {
  51. #ifdef __linux__
  52. struct ucontext *uc = puc;
  53. #elif defined(__OpenBSD__)
  54. struct sigcontext *uc = puc;
  55. #endif
  56. env = env1;
  57. /* XXX: restore cpu registers saved in host registers */
  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. env->exception_index = -1;
  71. longjmp(env->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(unsigned long pc, unsigned long address,
  78. int is_write, sigset_t *old_set,
  79. void *puc)
  80. {
  81. TranslationBlock *tb;
  82. int ret;
  83. if (cpu_single_env) {
  84. env = cpu_single_env; /* XXX: find a correct solution for multithread */
  85. }
  86. #if defined(DEBUG_SIGNAL)
  87. qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  88. pc, address, is_write, *(unsigned long *)old_set);
  89. #endif
  90. /* XXX: locking issue */
  91. if (is_write && page_unprotect(h2g(address), pc, puc)) {
  92. return 1;
  93. }
  94. /* see if it is an MMU fault */
  95. ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
  96. if (ret < 0) {
  97. return 0; /* not an MMU fault */
  98. }
  99. if (ret == 0) {
  100. return 1; /* the MMU fault was handled without causing real CPU fault */
  101. }
  102. /* now we have a real cpu fault */
  103. tb = tb_find_pc(pc);
  104. if (tb) {
  105. /* the PC is inside the translated code. It means that we have
  106. a virtual CPU fault */
  107. cpu_restore_state(tb, env, pc);
  108. }
  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(env);
  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 (__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. /* XXX: compute is_write */
  417. is_write = 0;
  418. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  419. is_write,
  420. &uc->uc_sigmask, puc);
  421. }
  422. #elif defined(__mc68000)
  423. int cpu_signal_handler(int host_signum, void *pinfo,
  424. void *puc)
  425. {
  426. siginfo_t *info = pinfo;
  427. struct ucontext *uc = puc;
  428. unsigned long pc;
  429. int is_write;
  430. pc = uc->uc_mcontext.gregs[16];
  431. /* XXX: compute is_write */
  432. is_write = 0;
  433. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  434. is_write,
  435. &uc->uc_sigmask, puc);
  436. }
  437. #elif defined(__ia64)
  438. #ifndef __ISR_VALID
  439. /* This ought to be in <bits/siginfo.h>... */
  440. # define __ISR_VALID 1
  441. #endif
  442. int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
  443. {
  444. siginfo_t *info = pinfo;
  445. struct ucontext *uc = puc;
  446. unsigned long ip;
  447. int is_write = 0;
  448. ip = uc->uc_mcontext.sc_ip;
  449. switch (host_signum) {
  450. case SIGILL:
  451. case SIGFPE:
  452. case SIGSEGV:
  453. case SIGBUS:
  454. case SIGTRAP:
  455. if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
  456. /* ISR.W (write-access) is bit 33: */
  457. is_write = (info->si_isr >> 33) & 1;
  458. }
  459. break;
  460. default:
  461. break;
  462. }
  463. return handle_cpu_signal(ip, (unsigned long)info->si_addr,
  464. is_write,
  465. (sigset_t *)&uc->uc_sigmask, puc);
  466. }
  467. #elif defined(__s390__)
  468. int cpu_signal_handler(int host_signum, void *pinfo,
  469. void *puc)
  470. {
  471. siginfo_t *info = pinfo;
  472. struct ucontext *uc = puc;
  473. unsigned long pc;
  474. uint16_t *pinsn;
  475. int is_write = 0;
  476. pc = uc->uc_mcontext.psw.addr;
  477. /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
  478. of the normal 2 arguments. The 3rd argument contains the "int_code"
  479. from the hardware which does in fact contain the is_write value.
  480. The rt signal handler, as far as I can tell, does not give this value
  481. at all. Not that we could get to it from here even if it were. */
  482. /* ??? This is not even close to complete, since it ignores all
  483. of the read-modify-write instructions. */
  484. pinsn = (uint16_t *)pc;
  485. switch (pinsn[0] >> 8) {
  486. case 0x50: /* ST */
  487. case 0x42: /* STC */
  488. case 0x40: /* STH */
  489. is_write = 1;
  490. break;
  491. case 0xc4: /* RIL format insns */
  492. switch (pinsn[0] & 0xf) {
  493. case 0xf: /* STRL */
  494. case 0xb: /* STGRL */
  495. case 0x7: /* STHRL */
  496. is_write = 1;
  497. }
  498. break;
  499. case 0xe3: /* RXY format insns */
  500. switch (pinsn[2] & 0xff) {
  501. case 0x50: /* STY */
  502. case 0x24: /* STG */
  503. case 0x72: /* STCY */
  504. case 0x70: /* STHY */
  505. case 0x8e: /* STPQ */
  506. case 0x3f: /* STRVH */
  507. case 0x3e: /* STRV */
  508. case 0x2f: /* STRVG */
  509. is_write = 1;
  510. }
  511. break;
  512. }
  513. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  514. is_write, &uc->uc_sigmask, puc);
  515. }
  516. #elif defined(__mips__)
  517. int cpu_signal_handler(int host_signum, void *pinfo,
  518. void *puc)
  519. {
  520. siginfo_t *info = pinfo;
  521. struct ucontext *uc = puc;
  522. greg_t pc = uc->uc_mcontext.pc;
  523. int is_write;
  524. /* XXX: compute is_write */
  525. is_write = 0;
  526. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  527. is_write, &uc->uc_sigmask, puc);
  528. }
  529. #elif defined(__hppa__)
  530. int cpu_signal_handler(int host_signum, void *pinfo,
  531. void *puc)
  532. {
  533. struct siginfo *info = pinfo;
  534. struct ucontext *uc = puc;
  535. unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
  536. uint32_t insn = *(uint32_t *)pc;
  537. int is_write = 0;
  538. /* XXX: need kernel patch to get write flag faster. */
  539. switch (insn >> 26) {
  540. case 0x1a: /* STW */
  541. case 0x19: /* STH */
  542. case 0x18: /* STB */
  543. case 0x1b: /* STWM */
  544. is_write = 1;
  545. break;
  546. case 0x09: /* CSTWX, FSTWX, FSTWS */
  547. case 0x0b: /* CSTDX, FSTDX, FSTDS */
  548. /* Distinguish from coprocessor load ... */
  549. is_write = (insn >> 9) & 1;
  550. break;
  551. case 0x03:
  552. switch ((insn >> 6) & 15) {
  553. case 0xa: /* STWS */
  554. case 0x9: /* STHS */
  555. case 0x8: /* STBS */
  556. case 0xe: /* STWAS */
  557. case 0xc: /* STBYS */
  558. is_write = 1;
  559. }
  560. break;
  561. }
  562. return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  563. is_write, &uc->uc_sigmask, puc);
  564. }
  565. #else
  566. #error host CPU specific signal handler needed
  567. #endif