aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/signal.c')
-rw-r--r--arch/xtensa/kernel/signal.c65
1 files changed, 42 insertions, 23 deletions
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 42d9fd8a4225..299be42d116b 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -35,13 +35,17 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
35 35
36extern struct task_struct *coproc_owners[]; 36extern struct task_struct *coproc_owners[];
37 37
38extern void release_all_cp (struct task_struct *);
39
40struct rt_sigframe 38struct rt_sigframe
41{ 39{
42 struct siginfo info; 40 struct siginfo info;
43 struct ucontext uc; 41 struct ucontext uc;
44 cp_state_t cpstate; 42 struct {
43 xtregs_opt_t opt;
44 xtregs_user_t user;
45#if XTENSA_HAVE_COPROCESSORS
46 xtregs_coprocessor_t cp;
47#endif
48 } xtregs;
45 unsigned char retcode[6]; 49 unsigned char retcode[6];
46 unsigned int window[4]; 50 unsigned int window[4];
47}; 51};
@@ -132,9 +136,10 @@ errout:
132 */ 136 */
133 137
134static int 138static int
135setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate, 139setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs)
136 struct pt_regs *regs)
137{ 140{
141 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
142 struct thread_info *ti = current_thread_info();
138 int err = 0; 143 int err = 0;
139 144
140#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) 145#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
@@ -148,21 +153,32 @@ setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate,
148 153
149 err |= flush_window_regs_user(regs); 154 err |= flush_window_regs_user(regs);
150 err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4); 155 err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4);
156 err |= __put_user(0, &sc->sc_xtregs);
151 157
152 // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4) 158 if (err)
159 return err;
153 160
154#if XCHAL_HAVE_CP 161#if XTENSA_HAVE_COPROCESSORS
155# error Coprocessors unsupported 162 coprocessor_flush_all(ti);
156 err |= save_cpextra(cpstate); 163 coprocessor_release_all(ti);
157 err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate); 164 err |= __copy_to_user(&frame->xtregs.cp, &ti->xtregs_cp,
165 sizeof (frame->xtregs.cp));
158#endif 166#endif
167 err |= __copy_to_user(&frame->xtregs.opt, &regs->xtregs_opt,
168 sizeof (xtregs_opt_t));
169 err |= __copy_to_user(&frame->xtregs.user, &ti->xtregs_user,
170 sizeof (xtregs_user_t));
171
172 err |= __put_user(err ? NULL : &frame->xtregs, &sc->sc_xtregs);
159 173
160 return err; 174 return err;
161} 175}
162 176
163static int 177static int
164restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 178restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame)
165{ 179{
180 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
181 struct thread_info *ti = current_thread_info();
166 unsigned int err = 0; 182 unsigned int err = 0;
167 unsigned long ps; 183 unsigned long ps;
168 184
@@ -180,6 +196,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
180 regs->windowbase = 0; 196 regs->windowbase = 0;
181 regs->windowstart = 1; 197 regs->windowstart = 1;
182 198
199 regs->syscall = -1; /* disable syscall checks */
200
183 /* For PS, restore only PS.CALLINC. 201 /* For PS, restore only PS.CALLINC.
184 * Assume that all other bits are either the same as for the signal 202 * Assume that all other bits are either the same as for the signal
185 * handler, or the user mode value doesn't matter (e.g. PS.OWB). 203 * handler, or the user mode value doesn't matter (e.g. PS.OWB).
@@ -195,8 +213,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
195 213
196 err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4); 214 err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4);
197 215
198#if XCHAL_HAVE_CP 216 if (err)
199# error Coprocessors unsupported 217 return err;
218
200 /* The signal handler may have used coprocessors in which 219 /* The signal handler may have used coprocessors in which
201 * case they are still enabled. We disable them to force a 220 * case they are still enabled. We disable them to force a
202 * reloading of the original task's CP state by the lazy 221 * reloading of the original task's CP state by the lazy
@@ -204,20 +223,20 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
204 * Also, we essentially discard any coprocessor state that the 223 * Also, we essentially discard any coprocessor state that the
205 * signal handler created. */ 224 * signal handler created. */
206 225
207 if (!err) { 226#if XTENSA_HAVE_COPROCESSORS
208 struct task_struct *tsk = current; 227 coprocessor_release_all(ti);
209 release_all_cp(tsk); 228 err |= __copy_from_user(&ti->xtregs_cp, &frame->xtregs.cp,
210 err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate, 229 sizeof (frame->xtregs.cp));
211 XTENSA_CP_EXTRA_SIZE);
212 }
213#endif 230#endif
231 err |= __copy_from_user(&ti->xtregs_user, &frame->xtregs.user,
232 sizeof (xtregs_user_t));
233 err |= __copy_from_user(&regs->xtregs_opt, &frame->xtregs.opt,
234 sizeof (xtregs_opt_t));
214 235
215 regs->syscall = -1; /* disable syscall checks */
216 return err; 236 return err;
217} 237}
218 238
219 239
220
221/* 240/*
222 * Do a signal return; undo the signal stack. 241 * Do a signal return; undo the signal stack.
223 */ 242 */
@@ -246,7 +265,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
246 recalc_sigpending(); 265 recalc_sigpending();
247 spin_unlock_irq(&current->sighand->siglock); 266 spin_unlock_irq(&current->sighand->siglock);
248 267
249 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 268 if (restore_sigcontext(regs, frame))
250 goto badframe; 269 goto badframe;
251 270
252 ret = regs->areg[2]; 271 ret = regs->areg[2];
@@ -359,7 +378,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
359 err |= __put_user(sas_ss_flags(regs->areg[1]), 378 err |= __put_user(sas_ss_flags(regs->areg[1]),
360 &frame->uc.uc_stack.ss_flags); 379 &frame->uc.uc_stack.ss_flags);
361 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 380 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
362 err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate, regs); 381 err |= setup_sigcontext(frame, regs);
363 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 382 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
364 383
365 /* Create sys_rt_sigreturn syscall in stack frame */ 384 /* Create sys_rt_sigreturn syscall in stack frame */