signal.c 17.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *  linux/arch/arm/kernel/signal.c
 *
4
 *  Copyright (C) 1995-2009 Russell King
L
Linus Torvalds 已提交
5 6 7 8 9 10
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/errno.h>
11
#include <linux/random.h>
L
Linus Torvalds 已提交
12 13
#include <linux/signal.h>
#include <linux/personality.h>
14
#include <linux/uaccess.h>
15
#include <linux/tracehook.h>
L
Linus Torvalds 已提交
16

17
#include <asm/elf.h>
L
Linus Torvalds 已提交
18
#include <asm/cacheflush.h>
19
#include <asm/traps.h>
L
Linus Torvalds 已提交
20 21
#include <asm/ucontext.h>
#include <asm/unistd.h>
22
#include <asm/vfp.h>
L
Linus Torvalds 已提交
23 24 25 26

/*
 * For ARM syscalls, we encode the syscall number into the instruction.
 */
27 28
#define SWI_SYS_SIGRETURN	(0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
#define SWI_SYS_RT_SIGRETURN	(0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
L
Linus Torvalds 已提交
29

30 31 32 33 34 35
/*
 * With EABI, the syscall number has to be loaded into r7.
 */
#define MOV_R7_NR_SIGRETURN	(0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#define MOV_R7_NR_RT_SIGRETURN	(0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))

L
Linus Torvalds 已提交
36 37 38 39 40 41 42
/*
 * For Thumb syscalls, we pass the syscall number via r7.  We therefore
 * need two 16-bit instructions.
 */
#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))

43
static const unsigned long sigreturn_codes[7] = {
44 45
	MOV_R7_NR_SIGRETURN,    SWI_SYS_SIGRETURN,    SWI_THUMB_SIGRETURN,
	MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
L
Linus Torvalds 已提交
46 47
};

48 49
static unsigned long signal_return_offset;

50
#ifdef CONFIG_CRUNCH
51
static int preserve_crunch_context(struct crunch_sigframe __user *frame)
52 53 54 55 56 57 58 59 60 61 62 63
{
	char kbuf[sizeof(*frame) + 8];
	struct crunch_sigframe *kframe;

	/* the crunch context must be 64 bit aligned */
	kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
	kframe->magic = CRUNCH_MAGIC;
	kframe->size = CRUNCH_STORAGE_SIZE;
	crunch_task_copy(current_thread_info(), &kframe->storage);
	return __copy_to_user(frame, kframe, sizeof(*frame));
}

64
static int restore_crunch_context(struct crunch_sigframe __user *frame)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
{
	char kbuf[sizeof(*frame) + 8];
	struct crunch_sigframe *kframe;

	/* the crunch context must be 64 bit aligned */
	kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
	if (__copy_from_user(kframe, frame, sizeof(*frame)))
		return -1;
	if (kframe->magic != CRUNCH_MAGIC ||
	    kframe->size != CRUNCH_STORAGE_SIZE)
		return -1;
	crunch_task_restore(current_thread_info(), &kframe->storage);
	return 0;
}
#endif

L
Linus Torvalds 已提交
81 82 83 84
#ifdef CONFIG_IWMMXT

static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
{
85 86
	char kbuf[sizeof(*frame) + 8];
	struct iwmmxt_sigframe *kframe;
L
Linus Torvalds 已提交
87 88

	/* the iWMMXt context must be 64 bit aligned */
89
	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
90 91
	kframe->magic = IWMMXT_MAGIC;
	kframe->size = IWMMXT_STORAGE_SIZE;
92 93
	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
	return __copy_to_user(frame, kframe, sizeof(*frame));
L
Linus Torvalds 已提交
94 95 96 97
}

static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
{
98 99 100 101 102 103 104
	char kbuf[sizeof(*frame) + 8];
	struct iwmmxt_sigframe *kframe;

	/* the iWMMXt context must be 64 bit aligned */
	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
	if (__copy_from_user(kframe, frame, sizeof(*frame)))
		return -1;
105 106
	if (kframe->magic != IWMMXT_MAGIC ||
	    kframe->size != IWMMXT_STORAGE_SIZE)
107 108 109
		return -1;
	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
	return 0;
L
Linus Torvalds 已提交
110 111 112 113
}

#endif

114 115 116 117 118 119 120 121 122 123 124
#ifdef CONFIG_VFP

static int preserve_vfp_context(struct vfp_sigframe __user *frame)
{
	const unsigned long magic = VFP_MAGIC;
	const unsigned long size = VFP_STORAGE_SIZE;
	int err = 0;

	__put_user_error(magic, &frame->magic, err);
	__put_user_error(size, &frame->size, err);

125 126 127 128
	if (err)
		return -EFAULT;

	return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
}

static int restore_vfp_context(struct vfp_sigframe __user *frame)
{
	unsigned long magic;
	unsigned long size;
	int err = 0;

	__get_user_error(magic, &frame->magic, err);
	__get_user_error(size, &frame->size, err);

	if (err)
		return -EFAULT;
	if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
		return -EINVAL;

145
	return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc);
146 147 148 149
}

#endif

L
Linus Torvalds 已提交
150 151 152 153
/*
 * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
 */
struct sigframe {
154
	struct ucontext uc;
155
	unsigned long retcode[2];
L
Linus Torvalds 已提交
156 157 158 159
};

struct rt_sigframe {
	struct siginfo info;
160
	struct sigframe sig;
L
Linus Torvalds 已提交
161 162
};

163
static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
L
Linus Torvalds 已提交
164
{
165
	struct aux_sigframe __user *aux;
166 167 168 169
	sigset_t set;
	int err;

	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
170
	if (err == 0)
171
		set_current_blocked(&set);
L
Linus Torvalds 已提交
172

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
	__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
	__get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
	__get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
	__get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
	__get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
	__get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
	__get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
	__get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
	__get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
	__get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
	__get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
	__get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
	__get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
	__get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
	__get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
	__get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
L
Linus Torvalds 已提交
190 191 192

	err |= !valid_user_regs(regs);

193
	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
194 195 196 197
#ifdef CONFIG_CRUNCH
	if (err == 0)
		err |= restore_crunch_context(&aux->crunch);
#endif
L
Linus Torvalds 已提交
198 199 200 201 202
#ifdef CONFIG_IWMMXT
	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
		err |= restore_iwmmxt_context(&aux->iwmmxt);
#endif
#ifdef CONFIG_VFP
203 204
	if (err == 0)
		err |= restore_vfp_context(&aux->vfp);
L
Linus Torvalds 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
#endif

	return err;
}

asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
	struct sigframe __user *frame;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (regs->ARM_sp & 7)
		goto badframe;

	frame = (struct sigframe __user *)regs->ARM_sp;

	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
		goto badframe;

230
	if (restore_sigframe(regs, frame))
L
Linus Torvalds 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
		goto badframe;

	return regs->ARM_r0;

badframe:
	force_sig(SIGSEGV, current);
	return 0;
}

asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
{
	struct rt_sigframe __user *frame;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (regs->ARM_sp & 7)
		goto badframe;

	frame = (struct rt_sigframe __user *)regs->ARM_sp;

	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
		goto badframe;

260
	if (restore_sigframe(regs, &frame->sig))
L
Linus Torvalds 已提交
261 262
		goto badframe;

A
Al Viro 已提交
263
	if (restore_altstack(&frame->sig.uc.uc_stack))
L
Linus Torvalds 已提交
264 265 266 267 268 269 270 271 272 273
		goto badframe;

	return regs->ARM_r0;

badframe:
	force_sig(SIGSEGV, current);
	return 0;
}

static int
274
setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
L
Linus Torvalds 已提交
275
{
276
	struct aux_sigframe __user *aux;
L
Linus Torvalds 已提交
277 278
	int err = 0;

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
	__put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
	__put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
	__put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
	__put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
	__put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
	__put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
	__put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
	__put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
	__put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
	__put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
	__put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
	__put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
	__put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
	__put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
	__put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
	__put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);

	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);

	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
L
Linus Torvalds 已提交
303

304
	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
305 306 307 308
#ifdef CONFIG_CRUNCH
	if (err == 0)
		err |= preserve_crunch_context(&aux->crunch);
#endif
L
Linus Torvalds 已提交
309 310 311 312 313
#ifdef CONFIG_IWMMXT
	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
		err |= preserve_iwmmxt_context(&aux->iwmmxt);
#endif
#ifdef CONFIG_VFP
314 315
	if (err == 0)
		err |= preserve_vfp_context(&aux->vfp);
L
Linus Torvalds 已提交
316
#endif
317
	__put_user_error(0, &aux->end_magic, err);
L
Linus Torvalds 已提交
318 319 320 321 322

	return err;
}

static inline void __user *
323
get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
L
Linus Torvalds 已提交
324
{
325
	unsigned long sp = sigsp(regs->ARM_sp, ksig);
L
Linus Torvalds 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
	void __user *frame;

	/*
	 * ATPCS B01 mandates 8-byte alignment
	 */
	frame = (void __user *)((sp - framesize) & ~7);

	/*
	 * Check that we can actually write to the signal frame.
	 */
	if (!access_ok(VERIFY_WRITE, frame, framesize))
		frame = NULL;

	return frame;
}

342 343 344 345 346 347 348 349 350 351 352
/*
 * translate the signal
 */
static inline int map_sig(int sig)
{
	struct thread_info *thread = current_thread_info();
	if (sig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
		sig = thread->exec_domain->signal_invmap[sig];
	return sig;
}

L
Linus Torvalds 已提交
353
static int
354 355
setup_return(struct pt_regs *regs, struct ksignal *ksig,
	     unsigned long __user *rc, void __user *frame)
L
Linus Torvalds 已提交
356
{
357
	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
L
Linus Torvalds 已提交
358 359
	unsigned long retcode;
	int thumb = 0;
360 361 362
	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);

	cpsr |= PSR_ENDSTATE;
L
Linus Torvalds 已提交
363 364 365 366

	/*
	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
	 */
367
	if (ksig->ka.sa.sa_flags & SA_THIRTYTWO)
L
Linus Torvalds 已提交
368 369 370 371 372 373 374 375 376 377
		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;

#ifdef CONFIG_ARM_THUMB
	if (elf_hwcap & HWCAP_THUMB) {
		/*
		 * The LSB of the handler determines if we're going to
		 * be using THUMB or ARM mode for this signal handler.
		 */
		thumb = handler & 1;

378
		if (thumb) {
L
Linus Torvalds 已提交
379
			cpsr |= PSR_T_BIT;
380 381 382 383 384
#if __LINUX_ARM_ARCH__ >= 7
			/* clear the If-Then Thumb-2 execution state */
			cpsr &= ~PSR_IT_MASK;
#endif
		} else
L
Linus Torvalds 已提交
385 386 387 388
			cpsr &= ~PSR_T_BIT;
	}
#endif

389 390
	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
		retcode = (unsigned long)ksig->ka.sa.sa_restorer;
L
Linus Torvalds 已提交
391
	} else {
392
		unsigned int idx = thumb << 1;
L
Linus Torvalds 已提交
393

394
		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
395
			idx += 3;
L
Linus Torvalds 已提交
396

397 398 399 400
		/*
		 * Put the sigreturn code on the stack no matter which return
		 * mechanism we use in order to remain ABI compliant
		 */
401 402
		if (__put_user(sigreturn_codes[idx],   rc) ||
		    __put_user(sigreturn_codes[idx+1], rc+1))
L
Linus Torvalds 已提交
403 404
			return 1;

405
		if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) {
406 407
			struct mm_struct *mm = current->mm;

408
			/*
409 410 411
			 * 32-bit code can use the signal return page
			 * except when the MPU has protected the vectors
			 * page from PL0
412
			 */
413 414
			retcode = mm->context.sigpage + signal_return_offset +
				  (idx << 2) + thumb;
415 416 417 418 419 420
		} else {
			/*
			 * Ensure that the instruction cache sees
			 * the return code written onto the stack.
			 */
			flush_icache_range((unsigned long)rc,
421
					   (unsigned long)(rc + 2));
422 423 424

			retcode = ((unsigned long)rc) + thumb;
		}
L
Linus Torvalds 已提交
425 426
	}

427
	regs->ARM_r0 = map_sig(ksig->sig);
L
Linus Torvalds 已提交
428 429 430 431 432 433 434 435 436
	regs->ARM_sp = (unsigned long)frame;
	regs->ARM_lr = retcode;
	regs->ARM_pc = handler;
	regs->ARM_cpsr = cpsr;

	return 0;
}

static int
437
setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
L
Linus Torvalds 已提交
438
{
439
	struct sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
L
Linus Torvalds 已提交
440 441 442 443 444
	int err = 0;

	if (!frame)
		return 1;

445 446 447 448
	/*
	 * Set uc.uc_flags to a value which sc.trap_no would never have.
	 */
	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
L
Linus Torvalds 已提交
449

450
	err |= setup_sigframe(frame, regs, set);
L
Linus Torvalds 已提交
451
	if (err == 0)
452
		err = setup_return(regs, ksig, frame->retcode, frame);
L
Linus Torvalds 已提交
453 454 455 456 457

	return err;
}

static int
458
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
L
Linus Torvalds 已提交
459
{
460
	struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
L
Linus Torvalds 已提交
461 462 463 464 465
	int err = 0;

	if (!frame)
		return 1;

466
	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
L
Linus Torvalds 已提交
467

468 469
	__put_user_error(0, &frame->sig.uc.uc_flags, err);
	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
L
Linus Torvalds 已提交
470

A
Al Viro 已提交
471
	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp);
472
	err |= setup_sigframe(&frame->sig, regs, set);
L
Linus Torvalds 已提交
473
	if (err == 0)
474
		err = setup_return(regs, ksig, frame->sig.retcode, frame);
L
Linus Torvalds 已提交
475 476 477 478 479 480 481 482

	if (err == 0) {
		/*
		 * For realtime signals we must also set the second and third
		 * arguments for the signal handler.
		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
		 */
		regs->ARM_r1 = (unsigned long)&frame->info;
483
		regs->ARM_r2 = (unsigned long)&frame->sig.uc;
L
Linus Torvalds 已提交
484 485 486 487 488 489 490 491
	}

	return err;
}

/*
 * OK, we're invoking a handler
 */	
492
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
L
Linus Torvalds 已提交
493
{
A
Al Viro 已提交
494
	sigset_t *oldset = sigmask_to_save();
L
Linus Torvalds 已提交
495 496 497 498 499
	int ret;

	/*
	 * Set up the stack frame
	 */
500 501
	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(ksig, oldset, regs);
L
Linus Torvalds 已提交
502
	else
503
		ret = setup_frame(ksig, oldset, regs);
L
Linus Torvalds 已提交
504 505 506 507 508 509

	/*
	 * Check that the resulting registers are actually sane.
	 */
	ret |= !valid_user_regs(regs);

510
	signal_setup_done(ret, ksig, 0);
L
Linus Torvalds 已提交
511 512 513 514 515 516 517 518 519 520 521
}

/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 *
 * Note that we go through the signals twice: once to check the signals that
 * the kernel can handle, and then we build all the user-level signal handling
 * stack-frames in one go after that.
 */
522
static int do_signal(struct pt_regs *regs, int syscall)
L
Linus Torvalds 已提交
523
{
524
	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
525
	struct ksignal ksig;
526
	int restart = 0;
L
Linus Torvalds 已提交
527

528 529 530 531 532 533 534 535 536 537 538 539 540
	/*
	 * If we were from a system call, check for system call restarting...
	 */
	if (syscall) {
		continue_addr = regs->ARM_pc;
		restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
		retval = regs->ARM_r0;

		/*
		 * Prepare for system call restart.  We do this here so that a
		 * debugger will see the already changed PSW.
		 */
		switch (retval) {
541
		case -ERESTART_RESTARTBLOCK:
542
			restart -= 2;
543 544 545
		case -ERESTARTNOHAND:
		case -ERESTARTSYS:
		case -ERESTARTNOINTR:
546
			restart++;
547 548 549 550 551 552 553 554 555 556
			regs->ARM_r0 = regs->ARM_ORIG_r0;
			regs->ARM_pc = restart_addr;
			break;
		}
	}

	/*
	 * Get the signal to deliver.  When running under ptrace, at this
	 * point the debugger may change all our registers ...
	 */
557 558 559 560 561
	/*
	 * Depending on the signal settings we may need to revert the
	 * decision to restart the system call.  But skip this if a
	 * debugger has chosen to restart at a different PC.
	 */
562 563 564
	if (get_signal(&ksig)) {
		/* handler */
		if (unlikely(restart) && regs->ARM_pc == restart_addr) {
565 566
			if (retval == -ERESTARTNOHAND ||
			    retval == -ERESTART_RESTARTBLOCK
567
			    || (retval == -ERESTARTSYS
568
				&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
569 570 571 572
				regs->ARM_r0 = -EINTR;
				regs->ARM_pc = continue_addr;
			}
		}
573 574 575 576 577 578 579 580
		handle_signal(&ksig, regs);
	} else {
		/* no handler */
		restore_saved_sigmask();
		if (unlikely(restart) && regs->ARM_pc == restart_addr) {
			regs->ARM_pc = continue_addr;
			return restart;
		}
L
Linus Torvalds 已提交
581
	}
582
	return 0;
L
Linus Torvalds 已提交
583 584
}

585
asmlinkage int
586
do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
L
Linus Torvalds 已提交
587
{
588 589 590 591 592
	do {
		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
			schedule();
		} else {
			if (unlikely(!user_mode(regs)))
593
				return 0;
594 595
			local_irq_enable();
			if (thread_flags & _TIF_SIGPENDING) {
596 597
				int restart = do_signal(regs, syscall);
				if (unlikely(restart)) {
598 599 600 601 602
					/*
					 * Restart without handlers.
					 * Deal with it without leaving
					 * the kernel space.
					 */
603
					return restart;
604
				}
605 606 607 608 609 610 611 612 613
				syscall = 0;
			} else {
				clear_thread_flag(TIF_NOTIFY_RESUME);
				tracehook_notify_resume(regs);
			}
		}
		local_irq_disable();
		thread_flags = current_thread_info()->flags;
	} while (thread_flags & _TIF_WORK_MASK);
614
	return 0;
L
Linus Torvalds 已提交
615
}
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648

static struct page *signal_page;

struct page *get_signal_page(void)
{
	if (!signal_page) {
		unsigned long ptr;
		unsigned offset;
		void *addr;

		signal_page = alloc_pages(GFP_KERNEL, 0);

		if (!signal_page)
			return NULL;

		addr = page_address(signal_page);

		/* Give the signal return code some randomness */
		offset = 0x200 + (get_random_int() & 0x7fc);
		signal_return_offset = offset;

		/*
		 * Copy signal return handlers into the vector page, and
		 * set sigreturn to be a pointer to these.
		 */
		memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));

		ptr = (unsigned long)addr + offset;
		flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
	}

	return signal_page;
}