signal-common.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1991, 1992 Linus Torvalds
  7. * Copyright (C) 1994 - 2000 Ralf Baechle
  8. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  9. */
  10. #include <linux/config.h>
  11. static inline int
  12. setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
  13. {
  14. int err = 0;
  15. err |= __put_user(regs->cp0_epc, &sc->sc_pc);
  16. #define save_gp_reg(i) do { \
  17. err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
  18. } while(0)
  19. __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
  20. save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
  21. save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
  22. save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
  23. save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
  24. save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
  25. save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
  26. save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
  27. save_gp_reg(31);
  28. #undef save_gp_reg
  29. #ifdef CONFIG_32BIT
  30. err |= __put_user(regs->hi, &sc->sc_mdhi);
  31. err |= __put_user(regs->lo, &sc->sc_mdlo);
  32. if (cpu_has_dsp) {
  33. err |= __put_user(mfhi1(), &sc->sc_hi1);
  34. err |= __put_user(mflo1(), &sc->sc_lo1);
  35. err |= __put_user(mfhi2(), &sc->sc_hi2);
  36. err |= __put_user(mflo2(), &sc->sc_lo2);
  37. err |= __put_user(mfhi3(), &sc->sc_hi3);
  38. err |= __put_user(mflo3(), &sc->sc_lo3);
  39. err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
  40. }
  41. #endif
  42. #ifdef CONFIG_64BIT
  43. err |= __put_user(regs->hi, &sc->sc_hi[0]);
  44. err |= __put_user(regs->lo, &sc->sc_lo[0]);
  45. if (cpu_has_dsp) {
  46. err |= __put_user(mfhi1(), &sc->sc_hi[1]);
  47. err |= __put_user(mflo1(), &sc->sc_lo[1]);
  48. err |= __put_user(mfhi2(), &sc->sc_hi[2]);
  49. err |= __put_user(mflo2(), &sc->sc_lo[2]);
  50. err |= __put_user(mfhi3(), &sc->sc_hi[3]);
  51. err |= __put_user(mflo3(), &sc->sc_lo[3]);
  52. err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
  53. }
  54. #endif
  55. err |= __put_user(!!used_math(), &sc->sc_used_math);
  56. if (!used_math())
  57. goto out;
  58. /*
  59. * Save FPU state to signal context. Signal handler will "inherit"
  60. * current FPU state.
  61. */
  62. preempt_disable();
  63. if (!is_fpu_owner()) {
  64. own_fpu();
  65. restore_fp(current);
  66. }
  67. err |= save_fp_context(sc);
  68. preempt_enable();
  69. out:
  70. return err;
  71. }
  72. static inline int
  73. restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
  74. {
  75. unsigned int used_math;
  76. unsigned long treg;
  77. int err = 0;
  78. /* Always make any pending restarted system calls return -EINTR */
  79. current_thread_info()->restart_block.fn = do_no_restart_syscall;
  80. err |= __get_user(regs->cp0_epc, &sc->sc_pc);
  81. #ifdef CONFIG_32BIT
  82. err |= __get_user(regs->hi, &sc->sc_mdhi);
  83. err |= __get_user(regs->lo, &sc->sc_mdlo);
  84. if (cpu_has_dsp) {
  85. err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
  86. err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
  87. err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
  88. err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
  89. err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
  90. err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
  91. err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
  92. }
  93. #endif
  94. #ifdef CONFIG_64BIT
  95. err |= __get_user(regs->hi, &sc->sc_hi[0]);
  96. err |= __get_user(regs->lo, &sc->sc_lo[0]);
  97. if (cpu_has_dsp) {
  98. err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
  99. err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
  100. err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
  101. err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
  102. err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
  103. err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
  104. err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
  105. }
  106. #endif
  107. #define restore_gp_reg(i) do { \
  108. err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
  109. } while(0)
  110. restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
  111. restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
  112. restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
  113. restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
  114. restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
  115. restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
  116. restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
  117. restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
  118. restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
  119. restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
  120. restore_gp_reg(31);
  121. #undef restore_gp_reg
  122. err |= __get_user(used_math, &sc->sc_used_math);
  123. conditional_used_math(used_math);
  124. preempt_disable();
  125. if (used_math()) {
  126. /* restore fpu context if we have used it before */
  127. own_fpu();
  128. err |= restore_fp_context(sc);
  129. } else {
  130. /* signal handler may have used FPU. Give it up. */
  131. lose_fpu();
  132. }
  133. preempt_enable();
  134. return err;
  135. }
  136. /*
  137. * Determine which stack to use..
  138. */
  139. static inline void __user *
  140. get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
  141. {
  142. unsigned long sp;
  143. /* Default to using normal stack */
  144. sp = regs->regs[29];
  145. /*
  146. * FPU emulator may have it's own trampoline active just
  147. * above the user stack, 16-bytes before the next lowest
  148. * 16 byte boundary. Try to avoid trashing it.
  149. */
  150. sp -= 32;
  151. /* This is the X/Open sanctioned signal stack switching. */
  152. if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
  153. sp = current->sas_ss_sp + current->sas_ss_size;
  154. return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
  155. }
  156. static inline int install_sigtramp(unsigned int __user *tramp,
  157. unsigned int syscall)
  158. {
  159. int err;
  160. /*
  161. * Set up the return code ...
  162. *
  163. * li v0, __NR__foo_sigreturn
  164. * syscall
  165. */
  166. err = __put_user(0x24020000 + syscall, tramp + 0);
  167. err |= __put_user(0x0000000c , tramp + 1);
  168. if (ICACHE_REFILLS_WORKAROUND_WAR) {
  169. err |= __put_user(0, tramp + 2);
  170. err |= __put_user(0, tramp + 3);
  171. err |= __put_user(0, tramp + 4);
  172. err |= __put_user(0, tramp + 5);
  173. err |= __put_user(0, tramp + 6);
  174. err |= __put_user(0, tramp + 7);
  175. }
  176. flush_cache_sigtramp((unsigned long) tramp);
  177. return err;
  178. }