signal-common.h 5.1 KB

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