signal-common.h 5.1 KB

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