0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/compiler.h>
0012 #include <linux/errno.h>
0013 #include <linux/signal.h>
0014 #include <linux/sched/signal.h>
0015 #include <linux/uaccess.h>
0016
0017 #include <asm/abi.h>
0018 #include <asm/compat-signal.h>
0019 #include <asm/dsp.h>
0020 #include <asm/sim.h>
0021 #include <asm/unistd.h>
0022
0023 #include "signal-common.h"
0024
0025
0026
0027
0028 #define __NR_O32_restart_syscall 4253
0029
0030 struct sigframe32 {
0031 u32 sf_ass[4];
0032 u32 sf_pad[2];
0033 struct sigcontext32 sf_sc;
0034 compat_sigset_t sf_mask;
0035 };
0036
0037 struct ucontext32 {
0038 u32 uc_flags;
0039 s32 uc_link;
0040 compat_stack_t uc_stack;
0041 struct sigcontext32 uc_mcontext;
0042 compat_sigset_t uc_sigmask;
0043 };
0044
0045 struct rt_sigframe32 {
0046 u32 rs_ass[4];
0047 u32 rs_pad[2];
0048 compat_siginfo_t rs_info;
0049 struct ucontext32 rs_uc;
0050 };
0051
0052 static int setup_sigcontext32(struct pt_regs *regs,
0053 struct sigcontext32 __user *sc)
0054 {
0055 int err = 0;
0056 int i;
0057
0058 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
0059
0060 err |= __put_user(0, &sc->sc_regs[0]);
0061 for (i = 1; i < 32; i++)
0062 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
0063
0064 err |= __put_user(regs->hi, &sc->sc_mdhi);
0065 err |= __put_user(regs->lo, &sc->sc_mdlo);
0066 if (cpu_has_dsp) {
0067 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
0068 err |= __put_user(mfhi1(), &sc->sc_hi1);
0069 err |= __put_user(mflo1(), &sc->sc_lo1);
0070 err |= __put_user(mfhi2(), &sc->sc_hi2);
0071 err |= __put_user(mflo2(), &sc->sc_lo2);
0072 err |= __put_user(mfhi3(), &sc->sc_hi3);
0073 err |= __put_user(mflo3(), &sc->sc_lo3);
0074 }
0075
0076
0077
0078
0079
0080 err |= protected_save_fp_context(sc);
0081
0082 return err;
0083 }
0084
0085 static int restore_sigcontext32(struct pt_regs *regs,
0086 struct sigcontext32 __user *sc)
0087 {
0088 int err = 0;
0089 s32 treg;
0090 int i;
0091
0092
0093 current->restart_block.fn = do_no_restart_syscall;
0094
0095 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
0096 err |= __get_user(regs->hi, &sc->sc_mdhi);
0097 err |= __get_user(regs->lo, &sc->sc_mdlo);
0098 if (cpu_has_dsp) {
0099 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
0100 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
0101 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
0102 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
0103 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
0104 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
0105 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
0106 }
0107
0108 for (i = 1; i < 32; i++)
0109 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
0110
0111 return err ?: protected_restore_fp_context(sc);
0112 }
0113
0114 static int setup_frame_32(void *sig_return, struct ksignal *ksig,
0115 struct pt_regs *regs, sigset_t *set)
0116 {
0117 struct sigframe32 __user *frame;
0118 int err = 0;
0119
0120 frame = get_sigframe(ksig, regs, sizeof(*frame));
0121 if (!access_ok(frame, sizeof (*frame)))
0122 return -EFAULT;
0123
0124 err |= setup_sigcontext32(regs, &frame->sf_sc);
0125 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
0126
0127 if (err)
0128 return -EFAULT;
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 regs->regs[ 4] = ksig->sig;
0141 regs->regs[ 5] = 0;
0142 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
0143 regs->regs[29] = (unsigned long) frame;
0144 regs->regs[31] = (unsigned long) sig_return;
0145 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
0146
0147 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
0148 current->comm, current->pid,
0149 frame, regs->cp0_epc, regs->regs[31]);
0150
0151 return 0;
0152 }
0153
0154 asmlinkage void sys32_rt_sigreturn(void)
0155 {
0156 struct rt_sigframe32 __user *frame;
0157 struct pt_regs *regs;
0158 sigset_t set;
0159 int sig;
0160
0161 regs = current_pt_regs();
0162 frame = (struct rt_sigframe32 __user *)regs->regs[29];
0163 if (!access_ok(frame, sizeof(*frame)))
0164 goto badframe;
0165 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
0166 goto badframe;
0167
0168 set_current_blocked(&set);
0169
0170 sig = restore_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
0171 if (sig < 0)
0172 goto badframe;
0173 else if (sig)
0174 force_sig(sig);
0175
0176 if (compat_restore_altstack(&frame->rs_uc.uc_stack))
0177 goto badframe;
0178
0179
0180
0181
0182 __asm__ __volatile__(
0183 "move\t$29, %0\n\t"
0184 "j\tsyscall_exit"
0185 :
0186 : "r" (regs));
0187
0188
0189 badframe:
0190 force_sig(SIGSEGV);
0191 }
0192
0193 static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
0194 struct pt_regs *regs, sigset_t *set)
0195 {
0196 struct rt_sigframe32 __user *frame;
0197 int err = 0;
0198
0199 frame = get_sigframe(ksig, regs, sizeof(*frame));
0200 if (!access_ok(frame, sizeof (*frame)))
0201 return -EFAULT;
0202
0203
0204 err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
0205
0206
0207 err |= __put_user(0, &frame->rs_uc.uc_flags);
0208 err |= __put_user(0, &frame->rs_uc.uc_link);
0209 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
0210 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
0211 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
0212
0213 if (err)
0214 return -EFAULT;
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 regs->regs[ 4] = ksig->sig;
0227 regs->regs[ 5] = (unsigned long) &frame->rs_info;
0228 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
0229 regs->regs[29] = (unsigned long) frame;
0230 regs->regs[31] = (unsigned long) sig_return;
0231 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
0232
0233 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
0234 current->comm, current->pid,
0235 frame, regs->cp0_epc, regs->regs[31]);
0236
0237 return 0;
0238 }
0239
0240
0241
0242
0243 struct mips_abi mips_abi_32 = {
0244 .setup_frame = setup_frame_32,
0245 .setup_rt_frame = setup_rt_frame_32,
0246 .restart = __NR_O32_restart_syscall,
0247
0248 .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
0249 .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
0250 .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
0251
0252 .vdso = &vdso_image_o32,
0253 };
0254
0255
0256 asmlinkage void sys32_sigreturn(void)
0257 {
0258 struct sigframe32 __user *frame;
0259 struct pt_regs *regs;
0260 sigset_t blocked;
0261 int sig;
0262
0263 regs = current_pt_regs();
0264 frame = (struct sigframe32 __user *)regs->regs[29];
0265 if (!access_ok(frame, sizeof(*frame)))
0266 goto badframe;
0267 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
0268 goto badframe;
0269
0270 set_current_blocked(&blocked);
0271
0272 sig = restore_sigcontext32(regs, &frame->sf_sc);
0273 if (sig < 0)
0274 goto badframe;
0275 else if (sig)
0276 force_sig(sig);
0277
0278
0279
0280
0281 __asm__ __volatile__(
0282 "move\t$29, %0\n\t"
0283 "j\tsyscall_exit"
0284 :
0285 : "r" (regs));
0286
0287
0288 badframe:
0289 force_sig(SIGSEGV);
0290 }