• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * arch/score/kernel/signal.c
3  *
4  * Score Processor version.
5  *
6  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7  *  Chen Liqin <liqin.chen@sunplusct.com>
8  *  Lennox Wu <lennox.wu@sunplusct.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see the file COPYING, or write
22  * to the Free Software Foundation, Inc.,
23  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25 
26 #include <linux/errno.h>
27 #include <linux/signal.h>
28 #include <linux/ptrace.h>
29 #include <linux/unistd.h>
30 #include <linux/uaccess.h>
31 #include <linux/tracehook.h>
32 
33 #include <asm/cacheflush.h>
34 #include <asm/syscalls.h>
35 #include <asm/ucontext.h>
36 
37 struct rt_sigframe {
38 	u32 rs_ass[4];		/* argument save space */
39 	u32 rs_code[2];		/* signal trampoline */
40 	struct siginfo rs_info;
41 	struct ucontext rs_uc;
42 };
43 
setup_sigcontext(struct pt_regs * regs,struct sigcontext __user * sc)44 static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
45 {
46 	int err = 0;
47 	unsigned long reg;
48 
49 	reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc);
50 	err |= __put_user(regs->cp0_psr, &sc->sc_psr);
51 	err |= __put_user(regs->cp0_condition, &sc->sc_condition);
52 
53 
54 #define save_gp_reg(i) {				\
55 	reg = regs->regs[i];				\
56 	err |= __put_user(reg, &sc->sc_regs[i]);	\
57 } while (0)
58 	save_gp_reg(0); save_gp_reg(1); save_gp_reg(2);
59 	save_gp_reg(3); save_gp_reg(4); save_gp_reg(5);
60 	save_gp_reg(6);	save_gp_reg(7); save_gp_reg(8);
61 	save_gp_reg(9); save_gp_reg(10); save_gp_reg(11);
62 	save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
63 	save_gp_reg(15); save_gp_reg(16); save_gp_reg(17);
64 	save_gp_reg(18); save_gp_reg(19); save_gp_reg(20);
65 	save_gp_reg(21); save_gp_reg(22); save_gp_reg(23);
66 	save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
67 	save_gp_reg(27); save_gp_reg(28); save_gp_reg(29);
68 #undef save_gp_reg
69 
70 	reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh);
71 	reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel);
72 	err |= __put_user(regs->cp0_ecr, &sc->sc_ecr);
73 	err |= __put_user(regs->cp0_ema, &sc->sc_ema);
74 
75 	return err;
76 }
77 
restore_sigcontext(struct pt_regs * regs,struct sigcontext __user * sc)78 static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
79 {
80 	int err = 0;
81 	u32 reg;
82 
83 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
84 	err |= __get_user(regs->cp0_condition, &sc->sc_condition);
85 
86 	err |= __get_user(reg, &sc->sc_mdceh);
87 	regs->ceh = (int) reg;
88 	err |= __get_user(reg, &sc->sc_mdcel);
89 	regs->cel = (int) reg;
90 
91 	err |= __get_user(reg, &sc->sc_psr);
92 	regs->cp0_psr = (int) reg;
93 	err |= __get_user(reg, &sc->sc_ecr);
94 	regs->cp0_ecr = (int) reg;
95 	err |= __get_user(reg, &sc->sc_ema);
96 	regs->cp0_ema = (int) reg;
97 
98 #define restore_gp_reg(i) do {				\
99 	err |= __get_user(reg, &sc->sc_regs[i]);	\
100 	regs->regs[i] = reg;				\
101 } while (0)
102 	restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2);
103 	restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5);
104 	restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8);
105 	restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11);
106 	restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14);
107 	restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17);
108 	restore_gp_reg(18); restore_gp_reg(19);	restore_gp_reg(20);
109 	restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23);
110 	restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26);
111 	restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29);
112 #undef restore_gp_reg
113 
114 	return err;
115 }
116 
117 /*
118  * Determine which stack to use..
119  */
get_sigframe(struct k_sigaction * ka,struct pt_regs * regs,size_t frame_size)120 static void __user *get_sigframe(struct k_sigaction *ka,
121 			struct pt_regs *regs, size_t frame_size)
122 {
123 	unsigned long sp;
124 
125 	/* Default to using normal stack */
126 	sp = regs->regs[0];
127 	sp -= 32;
128 
129 	/* This is the X/Open sanctioned signal stack switching.  */
130 	if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp)))
131 		sp = current->sas_ss_sp + current->sas_ss_size;
132 
133 	return (void __user*)((sp - frame_size) & ~7);
134 }
135 
136 asmlinkage long
score_rt_sigreturn(struct pt_regs * regs)137 score_rt_sigreturn(struct pt_regs *regs)
138 {
139 	struct rt_sigframe __user *frame;
140 	sigset_t set;
141 	int sig;
142 
143 	/* Always make any pending restarted system calls return -EINTR */
144 	current->restart_block.fn = do_no_restart_syscall;
145 
146 	frame = (struct rt_sigframe __user *) regs->regs[0];
147 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
148 		goto badframe;
149 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
150 		goto badframe;
151 
152 	set_current_blocked(&set);
153 
154 	sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
155 	if (sig < 0)
156 		goto badframe;
157 	else if (sig)
158 		force_sig(sig, current);
159 
160 	if (restore_altstack(&frame->rs_uc.uc_stack))
161 		goto badframe;
162 	regs->is_syscall = 0;
163 
164 	__asm__ __volatile__(
165 		"mv\tr0, %0\n\t"
166 		"la\tr8, syscall_exit\n\t"
167 		"br\tr8\n\t"
168 		: : "r" (regs) : "r8");
169 
170 badframe:
171 	force_sig(SIGSEGV, current);
172 
173 	return 0;
174 }
175 
setup_rt_frame(struct ksignal * ksig,struct pt_regs * regs,sigset_t * set)176 static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
177 			  sigset_t *set)
178 {
179 	struct rt_sigframe __user *frame;
180 	int err = 0;
181 
182 	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
183 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
184 		return -EFAULT;
185 
186 	/*
187 	 * Set up the return code ...
188 	 *
189 	 *         li      v0, __NR_rt_sigreturn
190 	 *         syscall
191 	 */
192 	err |= __put_user(0x87788000 + __NR_rt_sigreturn*2,
193 			frame->rs_code + 0);
194 	err |= __put_user(0x80008002, frame->rs_code + 1);
195 	flush_cache_sigtramp((unsigned long) frame->rs_code);
196 
197 	err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
198 	err |= __put_user(0, &frame->rs_uc.uc_flags);
199 	err |= __put_user(NULL, &frame->rs_uc.uc_link);
200 	err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]);
201 	err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
202 	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
203 
204 	if (err)
205 		return -EFAULT;
206 
207 	regs->regs[0] = (unsigned long) frame;
208 	regs->regs[3] = (unsigned long) frame->rs_code;
209 	regs->regs[4] = ksig->sig;
210 	regs->regs[5] = (unsigned long) &frame->rs_info;
211 	regs->regs[6] = (unsigned long) &frame->rs_uc;
212 	regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler;
213 	regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler;
214 
215 	return 0;
216 }
217 
handle_signal(struct ksignal * ksig,struct pt_regs * regs)218 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
219 {
220 	int ret;
221 
222 	if (regs->is_syscall) {
223 		switch (regs->regs[4]) {
224 		case ERESTART_RESTARTBLOCK:
225 		case ERESTARTNOHAND:
226 			regs->regs[4] = EINTR;
227 			break;
228 		case ERESTARTSYS:
229 			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
230 				regs->regs[4] = EINTR;
231 				break;
232 			}
233 		case ERESTARTNOINTR:
234 			regs->regs[4] = regs->orig_r4;
235 			regs->regs[7] = regs->orig_r7;
236 			regs->cp0_epc -= 8;
237 		}
238 
239 		regs->is_syscall = 0;
240 	}
241 
242 	/*
243 	 * Set up the stack frame
244 	 */
245 	ret = setup_rt_frame(ksig, regs, sigmask_to_save());
246 
247 	signal_setup_done(ret, ksig, 0);
248 }
249 
do_signal(struct pt_regs * regs)250 static void do_signal(struct pt_regs *regs)
251 {
252 	struct ksignal ksig;
253 
254 	/*
255 	 * We want the common case to go fast, which is why we may in certain
256 	 * cases get here from kernel mode. Just return without doing anything
257 	 * if so.
258 	 */
259 	if (!user_mode(regs))
260 		return;
261 
262 	if (get_signal(&ksig)) {
263 		/* Actually deliver the signal.  */
264 		handle_signal(&ksig, regs);
265 		return;
266 	}
267 
268 	if (regs->is_syscall) {
269 		if (regs->regs[4] == ERESTARTNOHAND ||
270 		    regs->regs[4] == ERESTARTSYS ||
271 		    regs->regs[4] == ERESTARTNOINTR) {
272 			regs->regs[4] = regs->orig_r4;
273 			regs->regs[7] = regs->orig_r7;
274 			regs->cp0_epc -= 8;
275 		}
276 
277 		if (regs->regs[4] == ERESTART_RESTARTBLOCK) {
278 			regs->regs[27] = __NR_restart_syscall;
279 			regs->regs[4] = regs->orig_r4;
280 			regs->regs[7] = regs->orig_r7;
281 			regs->cp0_epc -= 8;
282 		}
283 
284 		regs->is_syscall = 0;	/* Don't deal with this again.  */
285 	}
286 
287 	/*
288 	 * If there's no signal to deliver, we just put the saved sigmask
289 	 * back
290 	 */
291 	restore_saved_sigmask();
292 }
293 
294 /*
295  * notification of userspace execution resumption
296  * - triggered by the TIF_WORK_MASK flags
297  */
do_notify_resume(struct pt_regs * regs,void * unused,__u32 thread_info_flags)298 asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
299 				__u32 thread_info_flags)
300 {
301 	/* deal with pending signal delivery */
302 	if (thread_info_flags & _TIF_SIGPENDING)
303 		do_signal(regs);
304 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
305 		clear_thread_flag(TIF_NOTIFY_RESUME);
306 		tracehook_notify_resume(regs);
307 	}
308 }
309