Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e00d349e authored by Russell King's avatar Russell King
Browse files

[PATCH] ARM: Move signal return code into vector page



Move the signal return code into the vector page instead of placing
it on the user mode stack, which will allow us to avoid flushing
the instruction cache on signals, as well as eventually allowing
non-exec stack.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 05216219
Loading
Loading
Loading
Loading
+19 −10
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <asm/unistd.h>
#include <asm/unistd.h>


#include "ptrace.h"
#include "ptrace.h"
#include "signal.h"


#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))


@@ -35,7 +36,7 @@
#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#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))
#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))


static const unsigned long retcodes[4] = {
const unsigned long sigreturn_codes[4] = {
	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
};
};
@@ -500,9 +501,16 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
		if (ka->sa.sa_flags & SA_SIGINFO)
		if (ka->sa.sa_flags & SA_SIGINFO)
			idx += 2;
			idx += 2;


		if (__put_user(retcodes[idx], rc))
		if (__put_user(sigreturn_codes[idx], rc))
			return 1;
			return 1;


		if (cpsr & MODE32_BIT) {
			/*
			 * 32-bit code can use the new high-page
			 * signal return code support.
			 */
			retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
		} else {
			/*
			/*
			 * Ensure that the instruction cache sees
			 * Ensure that the instruction cache sees
			 * the return code written onto the stack.
			 * the return code written onto the stack.
@@ -512,6 +520,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,


			retcode = ((unsigned long)rc) + thumb;
			retcode = ((unsigned long)rc) + thumb;
		}
		}
	}


	regs->ARM_r0 = usig;
	regs->ARM_r0 = usig;
	regs->ARM_sp = (unsigned long)frame;
	regs->ARM_sp = (unsigned long)frame;
+12 −0
Original line number Original line Diff line number Diff line
/*
 *  linux/arch/arm/kernel/signal.h
 *
 *  Copyright (C) 2005 Russell King.
 *
 * 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.
 */
#define KERN_SIGRETURN_CODE	0xffff0500

extern const unsigned long sigreturn_codes[4];
+9 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@
#include <asm/traps.h>
#include <asm/traps.h>


#include "ptrace.h"
#include "ptrace.h"
#include "signal.h"


const char *processor_modes[]=
const char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -683,6 +684,14 @@ void __init trap_init(void)
	memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
	memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
	memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
	memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
	memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
	memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);

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

	flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
	flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
}