signal.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. /*
  24. * code and data structures from linux kernel:
  25. * include/asm-sh/sigcontext.h
  26. * arch/sh/kernel/signal.c
  27. */
  28. struct target_sigcontext {
  29. target_ulong oldmask;
  30. /* CPU registers */
  31. target_ulong sc_gregs[16];
  32. target_ulong sc_pc;
  33. target_ulong sc_pr;
  34. target_ulong sc_sr;
  35. target_ulong sc_gbr;
  36. target_ulong sc_mach;
  37. target_ulong sc_macl;
  38. /* FPU registers */
  39. target_ulong sc_fpregs[16];
  40. target_ulong sc_xfpregs[16];
  41. unsigned int sc_fpscr;
  42. unsigned int sc_fpul;
  43. unsigned int sc_ownedfp;
  44. };
  45. struct target_sigframe
  46. {
  47. struct target_sigcontext sc;
  48. target_ulong extramask[TARGET_NSIG_WORDS-1];
  49. uint16_t retcode[3];
  50. };
  51. struct target_ucontext {
  52. target_ulong tuc_flags;
  53. struct target_ucontext *tuc_link;
  54. target_stack_t tuc_stack;
  55. struct target_sigcontext tuc_mcontext;
  56. target_sigset_t tuc_sigmask; /* mask last for extensibility */
  57. };
  58. struct target_rt_sigframe
  59. {
  60. struct target_siginfo info;
  61. struct target_ucontext uc;
  62. uint16_t retcode[3];
  63. };
  64. #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
  65. #define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
  66. static abi_ulong get_sigframe(struct target_sigaction *ka,
  67. unsigned long sp, size_t frame_size)
  68. {
  69. sp = target_sigsp(sp, ka);
  70. return (sp - frame_size) & -8ul;
  71. }
  72. /* Notice when we're in the middle of a gUSA region and reset.
  73. Note that this will only occur for !parallel_cpus, as we will
  74. translate such sequences differently in a parallel context. */
  75. static void unwind_gusa(CPUSH4State *regs)
  76. {
  77. /* If the stack pointer is sufficiently negative, and we haven't
  78. completed the sequence, then reset to the entry to the region. */
  79. /* ??? The SH4 kernel checks for and address above 0xC0000000.
  80. However, the page mappings in qemu linux-user aren't as restricted
  81. and we wind up with the normal stack mapped above 0xF0000000.
  82. That said, there is no reason why the kernel should be allowing
  83. a gUSA region that spans 1GB. Use a tighter check here, for what
  84. can actually be enabled by the immediate move. */
  85. if (regs->gregs[15] >= -128u && regs->pc < regs->gregs[0]) {
  86. /* Reset the PC to before the gUSA region, as computed from
  87. R0 = region end, SP = -(region size), plus one more for the
  88. insn that actually initializes SP to the region size. */
  89. regs->pc = regs->gregs[0] + regs->gregs[15] - 2;
  90. /* Reset the SP to the saved version in R1. */
  91. regs->gregs[15] = regs->gregs[1];
  92. }
  93. }
  94. static void setup_sigcontext(struct target_sigcontext *sc,
  95. CPUSH4State *regs, unsigned long mask)
  96. {
  97. int i;
  98. #define COPY(x) __put_user(regs->x, &sc->sc_##x)
  99. COPY(gregs[0]); COPY(gregs[1]);
  100. COPY(gregs[2]); COPY(gregs[3]);
  101. COPY(gregs[4]); COPY(gregs[5]);
  102. COPY(gregs[6]); COPY(gregs[7]);
  103. COPY(gregs[8]); COPY(gregs[9]);
  104. COPY(gregs[10]); COPY(gregs[11]);
  105. COPY(gregs[12]); COPY(gregs[13]);
  106. COPY(gregs[14]); COPY(gregs[15]);
  107. COPY(gbr); COPY(mach);
  108. COPY(macl); COPY(pr);
  109. COPY(sr); COPY(pc);
  110. #undef COPY
  111. for (i=0; i<16; i++) {
  112. __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
  113. }
  114. __put_user(regs->fpscr, &sc->sc_fpscr);
  115. __put_user(regs->fpul, &sc->sc_fpul);
  116. /* non-iBCS2 extensions.. */
  117. __put_user(mask, &sc->oldmask);
  118. }
  119. static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
  120. {
  121. int i;
  122. #define COPY(x) __get_user(regs->x, &sc->sc_##x)
  123. COPY(gregs[0]); COPY(gregs[1]);
  124. COPY(gregs[2]); COPY(gregs[3]);
  125. COPY(gregs[4]); COPY(gregs[5]);
  126. COPY(gregs[6]); COPY(gregs[7]);
  127. COPY(gregs[8]); COPY(gregs[9]);
  128. COPY(gregs[10]); COPY(gregs[11]);
  129. COPY(gregs[12]); COPY(gregs[13]);
  130. COPY(gregs[14]); COPY(gregs[15]);
  131. COPY(gbr); COPY(mach);
  132. COPY(macl); COPY(pr);
  133. COPY(sr); COPY(pc);
  134. #undef COPY
  135. for (i=0; i<16; i++) {
  136. __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
  137. }
  138. __get_user(regs->fpscr, &sc->sc_fpscr);
  139. __get_user(regs->fpul, &sc->sc_fpul);
  140. regs->tra = -1; /* disable syscall checks */
  141. regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
  142. }
  143. void setup_frame(int sig, struct target_sigaction *ka,
  144. target_sigset_t *set, CPUSH4State *regs)
  145. {
  146. struct target_sigframe *frame;
  147. abi_ulong frame_addr;
  148. int i;
  149. unwind_gusa(regs);
  150. frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
  151. trace_user_setup_frame(regs, frame_addr);
  152. if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
  153. goto give_sigsegv;
  154. }
  155. setup_sigcontext(&frame->sc, regs, set->sig[0]);
  156. for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
  157. __put_user(set->sig[i + 1], &frame->extramask[i]);
  158. }
  159. /* Set up to return from userspace. If provided, use a stub
  160. already in userspace. */
  161. if (ka->sa_flags & TARGET_SA_RESTORER) {
  162. regs->pr = (unsigned long) ka->sa_restorer;
  163. } else {
  164. /* Generate return code (system call to sigreturn) */
  165. abi_ulong retcode_addr = frame_addr +
  166. offsetof(struct target_sigframe, retcode);
  167. __put_user(MOVW(2), &frame->retcode[0]);
  168. __put_user(TRAP_NOARG, &frame->retcode[1]);
  169. __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
  170. regs->pr = (unsigned long) retcode_addr;
  171. }
  172. /* Set up registers for signal handler */
  173. regs->gregs[15] = frame_addr;
  174. regs->gregs[4] = sig; /* Arg for signal handler */
  175. regs->gregs[5] = 0;
  176. regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
  177. regs->pc = (unsigned long) ka->_sa_handler;
  178. regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
  179. unlock_user_struct(frame, frame_addr, 1);
  180. return;
  181. give_sigsegv:
  182. unlock_user_struct(frame, frame_addr, 1);
  183. force_sigsegv(sig);
  184. }
  185. void setup_rt_frame(int sig, struct target_sigaction *ka,
  186. target_siginfo_t *info,
  187. target_sigset_t *set, CPUSH4State *regs)
  188. {
  189. struct target_rt_sigframe *frame;
  190. abi_ulong frame_addr;
  191. int i;
  192. unwind_gusa(regs);
  193. frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
  194. trace_user_setup_rt_frame(regs, frame_addr);
  195. if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
  196. goto give_sigsegv;
  197. }
  198. tswap_siginfo(&frame->info, info);
  199. /* Create the ucontext. */
  200. __put_user(0, &frame->uc.tuc_flags);
  201. __put_user(0, (unsigned long *)&frame->uc.tuc_link);
  202. target_save_altstack(&frame->uc.tuc_stack, regs);
  203. setup_sigcontext(&frame->uc.tuc_mcontext,
  204. regs, set->sig[0]);
  205. for(i = 0; i < TARGET_NSIG_WORDS; i++) {
  206. __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
  207. }
  208. /* Set up to return from userspace. If provided, use a stub
  209. already in userspace. */
  210. if (ka->sa_flags & TARGET_SA_RESTORER) {
  211. regs->pr = (unsigned long) ka->sa_restorer;
  212. } else {
  213. /* Generate return code (system call to sigreturn) */
  214. abi_ulong retcode_addr = frame_addr +
  215. offsetof(struct target_rt_sigframe, retcode);
  216. __put_user(MOVW(2), &frame->retcode[0]);
  217. __put_user(TRAP_NOARG, &frame->retcode[1]);
  218. __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
  219. regs->pr = (unsigned long) retcode_addr;
  220. }
  221. /* Set up registers for signal handler */
  222. regs->gregs[15] = frame_addr;
  223. regs->gregs[4] = sig; /* Arg for signal handler */
  224. regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
  225. regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
  226. regs->pc = (unsigned long) ka->_sa_handler;
  227. regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
  228. unlock_user_struct(frame, frame_addr, 1);
  229. return;
  230. give_sigsegv:
  231. unlock_user_struct(frame, frame_addr, 1);
  232. force_sigsegv(sig);
  233. }
  234. long do_sigreturn(CPUSH4State *regs)
  235. {
  236. struct target_sigframe *frame;
  237. abi_ulong frame_addr;
  238. sigset_t blocked;
  239. target_sigset_t target_set;
  240. int i;
  241. frame_addr = regs->gregs[15];
  242. trace_user_do_sigreturn(regs, frame_addr);
  243. if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
  244. goto badframe;
  245. }
  246. __get_user(target_set.sig[0], &frame->sc.oldmask);
  247. for(i = 1; i < TARGET_NSIG_WORDS; i++) {
  248. __get_user(target_set.sig[i], &frame->extramask[i - 1]);
  249. }
  250. target_to_host_sigset_internal(&blocked, &target_set);
  251. set_sigmask(&blocked);
  252. restore_sigcontext(regs, &frame->sc);
  253. unlock_user_struct(frame, frame_addr, 0);
  254. return -TARGET_QEMU_ESIGRETURN;
  255. badframe:
  256. unlock_user_struct(frame, frame_addr, 0);
  257. force_sig(TARGET_SIGSEGV);
  258. return -TARGET_QEMU_ESIGRETURN;
  259. }
  260. long do_rt_sigreturn(CPUSH4State *regs)
  261. {
  262. struct target_rt_sigframe *frame;
  263. abi_ulong frame_addr;
  264. sigset_t blocked;
  265. frame_addr = regs->gregs[15];
  266. trace_user_do_rt_sigreturn(regs, frame_addr);
  267. if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
  268. goto badframe;
  269. }
  270. target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
  271. set_sigmask(&blocked);
  272. restore_sigcontext(regs, &frame->uc.tuc_mcontext);
  273. if (do_sigaltstack(frame_addr +
  274. offsetof(struct target_rt_sigframe, uc.tuc_stack),
  275. 0, get_sp_from_cpustate(regs)) == -EFAULT) {
  276. goto badframe;
  277. }
  278. unlock_user_struct(frame, frame_addr, 0);
  279. return -TARGET_QEMU_ESIGRETURN;
  280. badframe:
  281. unlock_user_struct(frame, frame_addr, 0);
  282. force_sig(TARGET_SIGSEGV);
  283. return -TARGET_QEMU_ESIGRETURN;
  284. }