signal.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * Emulation of Linux signals
  3. *
  4. * Copyright (c) 2003 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 "signal-common.h"
  22. #include "linux-user/trace.h"
  23. struct target_sigcontext {
  24. abi_long sc_onstack;
  25. abi_long sc_mask;
  26. abi_long sc_pc;
  27. abi_long sc_ps;
  28. abi_long sc_regs[32];
  29. abi_long sc_ownedfp;
  30. abi_long sc_fpregs[32];
  31. abi_ulong sc_fpcr;
  32. abi_ulong sc_fp_control;
  33. abi_ulong sc_reserved1;
  34. abi_ulong sc_reserved2;
  35. abi_ulong sc_ssize;
  36. abi_ulong sc_sbase;
  37. abi_ulong sc_traparg_a0;
  38. abi_ulong sc_traparg_a1;
  39. abi_ulong sc_traparg_a2;
  40. abi_ulong sc_fp_trap_pc;
  41. abi_ulong sc_fp_trigger_sum;
  42. abi_ulong sc_fp_trigger_inst;
  43. };
  44. struct target_ucontext {
  45. abi_ulong tuc_flags;
  46. abi_ulong tuc_link;
  47. abi_ulong tuc_osf_sigmask;
  48. target_stack_t tuc_stack;
  49. struct target_sigcontext tuc_mcontext;
  50. target_sigset_t tuc_sigmask;
  51. };
  52. struct target_sigframe {
  53. struct target_sigcontext sc;
  54. unsigned int retcode[3];
  55. };
  56. struct target_rt_sigframe {
  57. target_siginfo_t info;
  58. struct target_ucontext uc;
  59. unsigned int retcode[3];
  60. };
  61. #define INSN_MOV_R30_R16 0x47fe0410
  62. #define INSN_LDI_R0 0x201f0000
  63. #define INSN_CALLSYS 0x00000083
  64. static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
  65. abi_ulong frame_addr, target_sigset_t *set)
  66. {
  67. int i;
  68. __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
  69. __put_user(set->sig[0], &sc->sc_mask);
  70. __put_user(env->pc, &sc->sc_pc);
  71. __put_user(8, &sc->sc_ps);
  72. for (i = 0; i < 31; ++i) {
  73. __put_user(env->ir[i], &sc->sc_regs[i]);
  74. }
  75. __put_user(0, &sc->sc_regs[31]);
  76. for (i = 0; i < 31; ++i) {
  77. __put_user(env->fir[i], &sc->sc_fpregs[i]);
  78. }
  79. __put_user(0, &sc->sc_fpregs[31]);
  80. __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
  81. __put_user(0, &sc->sc_traparg_a0); /* FIXME */
  82. __put_user(0, &sc->sc_traparg_a1); /* FIXME */
  83. __put_user(0, &sc->sc_traparg_a2); /* FIXME */
  84. }
  85. static void restore_sigcontext(CPUAlphaState *env,
  86. struct target_sigcontext *sc)
  87. {
  88. uint64_t fpcr;
  89. int i;
  90. __get_user(env->pc, &sc->sc_pc);
  91. for (i = 0; i < 31; ++i) {
  92. __get_user(env->ir[i], &sc->sc_regs[i]);
  93. }
  94. for (i = 0; i < 31; ++i) {
  95. __get_user(env->fir[i], &sc->sc_fpregs[i]);
  96. }
  97. __get_user(fpcr, &sc->sc_fpcr);
  98. cpu_alpha_store_fpcr(env, fpcr);
  99. }
  100. static inline abi_ulong get_sigframe(struct target_sigaction *sa,
  101. CPUAlphaState *env,
  102. unsigned long framesize)
  103. {
  104. abi_ulong sp;
  105. sp = target_sigsp(get_sp_from_cpustate(env), sa);
  106. return (sp - framesize) & -32;
  107. }
  108. void setup_frame(int sig, struct target_sigaction *ka,
  109. target_sigset_t *set, CPUAlphaState *env)
  110. {
  111. abi_ulong frame_addr, r26;
  112. struct target_sigframe *frame;
  113. int err = 0;
  114. frame_addr = get_sigframe(ka, env, sizeof(*frame));
  115. trace_user_setup_frame(env, frame_addr);
  116. if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
  117. goto give_sigsegv;
  118. }
  119. setup_sigcontext(&frame->sc, env, frame_addr, set);
  120. if (ka->sa_restorer) {
  121. r26 = ka->sa_restorer;
  122. } else {
  123. __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
  124. __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
  125. &frame->retcode[1]);
  126. __put_user(INSN_CALLSYS, &frame->retcode[2]);
  127. /* imb() */
  128. r26 = frame_addr + offsetof(struct target_sigframe, retcode);
  129. }
  130. unlock_user_struct(frame, frame_addr, 1);
  131. if (err) {
  132. give_sigsegv:
  133. force_sigsegv(sig);
  134. return;
  135. }
  136. env->ir[IR_RA] = r26;
  137. env->ir[IR_PV] = env->pc = ka->_sa_handler;
  138. env->ir[IR_A0] = sig;
  139. env->ir[IR_A1] = 0;
  140. env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
  141. env->ir[IR_SP] = frame_addr;
  142. }
  143. void setup_rt_frame(int sig, struct target_sigaction *ka,
  144. target_siginfo_t *info,
  145. target_sigset_t *set, CPUAlphaState *env)
  146. {
  147. abi_ulong frame_addr, r26;
  148. struct target_rt_sigframe *frame;
  149. int i, err = 0;
  150. frame_addr = get_sigframe(ka, env, sizeof(*frame));
  151. trace_user_setup_rt_frame(env, frame_addr);
  152. if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
  153. goto give_sigsegv;
  154. }
  155. tswap_siginfo(&frame->info, info);
  156. __put_user(0, &frame->uc.tuc_flags);
  157. __put_user(0, &frame->uc.tuc_link);
  158. __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
  159. target_save_altstack(&frame->uc.tuc_stack, env);
  160. setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
  161. for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
  162. __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
  163. }
  164. if (ka->sa_restorer) {
  165. r26 = ka->sa_restorer;
  166. } else {
  167. __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
  168. __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
  169. &frame->retcode[1]);
  170. __put_user(INSN_CALLSYS, &frame->retcode[2]);
  171. /* imb(); */
  172. r26 = frame_addr + offsetof(struct target_sigframe, retcode);
  173. }
  174. if (err) {
  175. give_sigsegv:
  176. force_sigsegv(sig);
  177. return;
  178. }
  179. env->ir[IR_RA] = r26;
  180. env->ir[IR_PV] = env->pc = ka->_sa_handler;
  181. env->ir[IR_A0] = sig;
  182. env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
  183. env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
  184. env->ir[IR_SP] = frame_addr;
  185. }
  186. long do_sigreturn(CPUAlphaState *env)
  187. {
  188. struct target_sigcontext *sc;
  189. abi_ulong sc_addr = env->ir[IR_A0];
  190. target_sigset_t target_set;
  191. sigset_t set;
  192. if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
  193. goto badframe;
  194. }
  195. target_sigemptyset(&target_set);
  196. __get_user(target_set.sig[0], &sc->sc_mask);
  197. target_to_host_sigset_internal(&set, &target_set);
  198. set_sigmask(&set);
  199. restore_sigcontext(env, sc);
  200. unlock_user_struct(sc, sc_addr, 0);
  201. return -TARGET_QEMU_ESIGRETURN;
  202. badframe:
  203. force_sig(TARGET_SIGSEGV);
  204. return -TARGET_QEMU_ESIGRETURN;
  205. }
  206. long do_rt_sigreturn(CPUAlphaState *env)
  207. {
  208. abi_ulong frame_addr = env->ir[IR_A0];
  209. struct target_rt_sigframe *frame;
  210. sigset_t set;
  211. trace_user_do_rt_sigreturn(env, frame_addr);
  212. if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
  213. goto badframe;
  214. }
  215. target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
  216. set_sigmask(&set);
  217. restore_sigcontext(env, &frame->uc.tuc_mcontext);
  218. if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
  219. uc.tuc_stack),
  220. 0, env->ir[IR_SP]) == -EFAULT) {
  221. goto badframe;
  222. }
  223. unlock_user_struct(frame, frame_addr, 0);
  224. return -TARGET_QEMU_ESIGRETURN;
  225. badframe:
  226. unlock_user_struct(frame, frame_addr, 0);
  227. force_sig(TARGET_SIGSEGV);
  228. return -TARGET_QEMU_ESIGRETURN;
  229. }