• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Port on Texas Instruments TMS320C6x architecture
4  *
5  *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
6  *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
7  *
8  *  Updated for 2.6.34: Mark Salter <msalter@redhat.com>
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/uaccess.h>
13 #include <linux/syscalls.h>
14 #include <linux/tracehook.h>
15 
16 #include <asm/asm-offsets.h>
17 #include <asm/ucontext.h>
18 #include <asm/cacheflush.h>
19 
20 
21 /*
22  * Do a signal return, undo the signal stack.
23  */
24 
25 #define RETCODE_SIZE (9 << 2)	/* 9 instructions = 36 bytes */
26 
27 struct rt_sigframe {
28 	struct siginfo __user *pinfo;
29 	void __user *puc;
30 	struct siginfo info;
31 	struct ucontext uc;
32 	unsigned long retcode[RETCODE_SIZE >> 2];
33 };
34 
restore_sigcontext(struct pt_regs * regs,struct sigcontext __user * sc)35 static int restore_sigcontext(struct pt_regs *regs,
36 			      struct sigcontext __user *sc)
37 {
38 	int err = 0;
39 
40 	/* The access_ok check was done by caller, so use __get_user here */
41 #define COPY(x)  (err |= __get_user(regs->x, &sc->sc_##x))
42 
43 	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
44 	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
45 	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
46 
47 	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
48 	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
49 	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
50 	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
51 	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
52 	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
53 	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
54 	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
55 
56 	COPY(csr); COPY(pc);
57 
58 #undef COPY
59 
60 	return err;
61 }
62 
do_rt_sigreturn(struct pt_regs * regs)63 asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
64 {
65 	struct rt_sigframe __user *frame;
66 	sigset_t set;
67 
68 	/* Always make any pending restarted system calls return -EINTR */
69 	current->restart_block.fn = do_no_restart_syscall;
70 
71 	/*
72 	 * Since we stacked the signal on a dword boundary,
73 	 * 'sp' should be dword aligned here.  If it's
74 	 * not, then the user is trying to mess with us.
75 	 */
76 	if (regs->sp & 7)
77 		goto badframe;
78 
79 	frame = (struct rt_sigframe __user *) ((unsigned long) regs->sp + 8);
80 
81 	if (!access_ok(frame, sizeof(*frame)))
82 		goto badframe;
83 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
84 		goto badframe;
85 
86 	set_current_blocked(&set);
87 
88 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
89 		goto badframe;
90 
91 	return regs->a4;
92 
93 badframe:
94 	force_sig(SIGSEGV);
95 	return 0;
96 }
97 
setup_sigcontext(struct sigcontext __user * sc,struct pt_regs * regs,unsigned long mask)98 static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
99 			    unsigned long mask)
100 {
101 	int err = 0;
102 
103 	err |= __put_user(mask, &sc->sc_mask);
104 
105 	/* The access_ok check was done by caller, so use __put_user here */
106 #define COPY(x) (err |= __put_user(regs->x, &sc->sc_##x))
107 
108 	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
109 	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
110 	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
111 
112 	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
113 	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
114 	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
115 	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
116 	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
117 	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
118 	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
119 	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
120 
121 	COPY(csr); COPY(pc);
122 
123 #undef COPY
124 
125 	return err;
126 }
127 
get_sigframe(struct ksignal * ksig,struct pt_regs * regs,unsigned long framesize)128 static inline void __user *get_sigframe(struct ksignal *ksig,
129 					struct pt_regs *regs,
130 					unsigned long framesize)
131 {
132 	unsigned long sp = sigsp(regs->sp, ksig);
133 
134 	/*
135 	 * No matter what happens, 'sp' must be dword
136 	 * aligned. Otherwise, nasty things will happen
137 	 */
138 	return (void __user *)((sp - framesize) & ~7);
139 }
140 
setup_rt_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)141 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
142 			  struct pt_regs *regs)
143 {
144 	struct rt_sigframe __user *frame;
145 	unsigned long __user *retcode;
146 	int err = 0;
147 
148 	frame = get_sigframe(ksig, regs, sizeof(*frame));
149 
150 	if (!access_ok(frame, sizeof(*frame)))
151 		return -EFAULT;
152 
153 	err |= __put_user(&frame->info, &frame->pinfo);
154 	err |= __put_user(&frame->uc, &frame->puc);
155 	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
156 
157 	/* Clear all the bits of the ucontext we don't use.  */
158 	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
159 
160 	err |= setup_sigcontext(&frame->uc.uc_mcontext,	regs, set->sig[0]);
161 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
162 
163 	/* Set up to return from userspace */
164 	retcode = (unsigned long __user *) &frame->retcode;
165 
166 	/* The access_ok check was done above, so use __put_user here */
167 #define COPY(x) (err |= __put_user(x, retcode++))
168 
169 	COPY(0x0000002AUL | (__NR_rt_sigreturn << 7));
170 				/* MVK __NR_rt_sigreturn,B0 */
171 	COPY(0x10000000UL);	/* SWE */
172 	COPY(0x00006000UL);	/* NOP 4 */
173 	COPY(0x00006000UL);	/* NOP 4 */
174 	COPY(0x00006000UL);	/* NOP 4 */
175 	COPY(0x00006000UL);	/* NOP 4 */
176 	COPY(0x00006000UL);	/* NOP 4 */
177 	COPY(0x00006000UL);	/* NOP 4 */
178 	COPY(0x00006000UL);	/* NOP 4 */
179 
180 #undef COPY
181 
182 	if (err)
183 		return -EFAULT;
184 
185 	flush_icache_range((unsigned long) &frame->retcode,
186 			   (unsigned long) &frame->retcode + RETCODE_SIZE);
187 
188 	retcode = (unsigned long __user *) &frame->retcode;
189 
190 	/* Change user context to branch to signal handler */
191 	regs->sp = (unsigned long) frame - 8;
192 	regs->b3 = (unsigned long) retcode;
193 	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
194 
195 	/* Give the signal number to the handler */
196 	regs->a4 = ksig->sig;
197 
198 	/*
199 	 * For realtime signals we must also set the second and third
200 	 * arguments for the signal handler.
201 	 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
202 	 */
203 	regs->b4 = (unsigned long)&frame->info;
204 	regs->a6 = (unsigned long)&frame->uc;
205 
206 	return 0;
207 }
208 
209 static inline void
handle_restart(struct pt_regs * regs,struct k_sigaction * ka,int has_handler)210 handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
211 {
212 	switch (regs->a4) {
213 	case -ERESTARTNOHAND:
214 		if (!has_handler)
215 			goto do_restart;
216 		regs->a4 = -EINTR;
217 		break;
218 
219 	case -ERESTARTSYS:
220 		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
221 			regs->a4 = -EINTR;
222 			break;
223 		}
224 		fallthrough;
225 	case -ERESTARTNOINTR:
226 do_restart:
227 		regs->a4 = regs->orig_a4;
228 		regs->pc -= 4;
229 		break;
230 	}
231 }
232 
233 /*
234  * handle the actual delivery of a signal to userspace
235  */
handle_signal(struct ksignal * ksig,struct pt_regs * regs,int syscall)236 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
237 			  int syscall)
238 {
239 	int ret;
240 
241 	/* Are we from a system call? */
242 	if (syscall) {
243 		/* If so, check system call restarting.. */
244 		switch (regs->a4) {
245 		case -ERESTART_RESTARTBLOCK:
246 		case -ERESTARTNOHAND:
247 			regs->a4 = -EINTR;
248 			break;
249 
250 		case -ERESTARTSYS:
251 			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
252 				regs->a4 = -EINTR;
253 				break;
254 			}
255 
256 			fallthrough;
257 		case -ERESTARTNOINTR:
258 			regs->a4 = regs->orig_a4;
259 			regs->pc -= 4;
260 		}
261 	}
262 
263 	/* Set up the stack frame */
264 	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
265 	signal_setup_done(ret, ksig, 0);
266 }
267 
268 /*
269  * handle a potential signal
270  */
do_signal(struct pt_regs * regs,int syscall)271 static void do_signal(struct pt_regs *regs, int syscall)
272 {
273 	struct ksignal ksig;
274 
275 	/* we want the common case to go fast, which is why we may in certain
276 	 * cases get here from kernel mode */
277 	if (!user_mode(regs))
278 		return;
279 
280 	if (get_signal(&ksig)) {
281 		handle_signal(&ksig, regs, syscall);
282 		return;
283 	}
284 
285 	/* did we come from a system call? */
286 	if (syscall) {
287 		/* restart the system call - no handlers present */
288 		switch (regs->a4) {
289 		case -ERESTARTNOHAND:
290 		case -ERESTARTSYS:
291 		case -ERESTARTNOINTR:
292 			regs->a4 = regs->orig_a4;
293 			regs->pc -= 4;
294 			break;
295 
296 		case -ERESTART_RESTARTBLOCK:
297 			regs->a4 = regs->orig_a4;
298 			regs->b0 = __NR_restart_syscall;
299 			regs->pc -= 4;
300 			break;
301 		}
302 	}
303 
304 	/* if there's no signal to deliver, we just put the saved sigmask
305 	 * back */
306 	restore_saved_sigmask();
307 }
308 
309 /*
310  * notification of userspace execution resumption
311  * - triggered by current->work.notify_resume
312  */
do_notify_resume(struct pt_regs * regs,u32 thread_info_flags,int syscall)313 asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
314 				 int syscall)
315 {
316 	/* deal with pending signal delivery */
317 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
318 		do_signal(regs, syscall);
319 
320 	if (thread_info_flags & (1 << TIF_NOTIFY_RESUME))
321 		tracehook_notify_resume(regs);
322 }
323