diff options
Diffstat (limited to 'arch/mips/kernel')
| -rw-r--r-- | arch/mips/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/mips/kernel/cpufreq/loongson2_clock.c | 4 | ||||
| -rw-r--r-- | arch/mips/kernel/irq.c | 1 | ||||
| -rw-r--r-- | arch/mips/kernel/linux32.c | 18 | ||||
| -rw-r--r-- | arch/mips/kernel/process.c | 8 | ||||
| -rw-r--r-- | arch/mips/kernel/ptrace.c | 30 | ||||
| -rw-r--r-- | arch/mips/kernel/rtlx.c | 1 | ||||
| -rw-r--r-- | arch/mips/kernel/scall64-n32.S | 4 | ||||
| -rw-r--r-- | arch/mips/kernel/scall64-o32.S | 2 | ||||
| -rw-r--r-- | arch/mips/kernel/signal-common.h | 5 | ||||
| -rw-r--r-- | arch/mips/kernel/signal.c | 86 | ||||
| -rw-r--r-- | arch/mips/kernel/signal32.c | 55 | ||||
| -rw-r--r-- | arch/mips/kernel/signal_n32.c | 26 | ||||
| -rw-r--r-- | arch/mips/kernel/smtc.c | 3 | ||||
| -rw-r--r-- | arch/mips/kernel/syscall.c | 138 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 18 | ||||
| -rw-r--r-- | arch/mips/kernel/vdso.c | 112 | 
17 files changed, 183 insertions, 330 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index ef20957ca14..7a6ac501cbb 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -6,7 +6,7 @@ extra-y		:= head.o init_task.o vmlinux.lds  obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \  		   ptrace.o reset.o setup.o signal.o syscall.o \ -		   time.o topology.o traps.o unaligned.o watch.o +		   time.o topology.o traps.o unaligned.o watch.o vdso.o  ifdef CONFIG_FUNCTION_TRACER  CFLAGS_REMOVE_ftrace.o = -pg diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c index d7ca256e33e..cefc6e259ba 100644 --- a/arch/mips/kernel/cpufreq/loongson2_clock.c +++ b/arch/mips/kernel/cpufreq/loongson2_clock.c @@ -164,3 +164,7 @@ void loongson2_cpu_wait(void)  	spin_unlock_irqrestore(&loongson2_wait_lock, flags);  }  EXPORT_SYMBOL_GPL(loongson2_cpu_wait); + +MODULE_AUTHOR("Yanhua <yanh@lemote.com>"); +MODULE_DESCRIPTION("cpufreq driver for Loongson 2F"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 981f86c2616..c6345f579a8 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -15,7 +15,6 @@  #include <linux/kernel_stat.h>  #include <linux/module.h>  #include <linux/proc_fs.h> -#include <linux/slab.h>  #include <linux/mm.h>  #include <linux/random.h>  #include <linux/sched.h> diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index bde79ef602e..c2dab140dc9 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -15,7 +15,6 @@  #include <linux/time.h>  #include <linux/times.h>  #include <linux/poll.h> -#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/filter.h>  #include <linux/shm.h> @@ -34,6 +33,7 @@  #include <linux/compat.h>  #include <linux/vfs.h>  #include <linux/ipc.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/scm.h> @@ -249,22 +249,6 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,  }  #endif -SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name) -{ -	int ret = 0; - -	down_read(&uts_sem); -	if (copy_to_user(name, utsname(), sizeof *name)) -		ret = -EFAULT; -	up_read(&uts_sem); - -	if (current->personality == PER_LINUX32 && !ret) -		if (copy_to_user(name->machine, "mips\0\0\0", 8)) -			ret = -EFAULT; - -	return ret; -} -  SYSCALL_DEFINE1(32_personality, unsigned long, personality)  {  	int ret; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index f3d73e1831c..99960940d4a 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -17,7 +17,6 @@  #include <linux/stddef.h>  #include <linux/unistd.h>  #include <linux/ptrace.h> -#include <linux/slab.h>  #include <linux/mman.h>  #include <linux/personality.h>  #include <linux/sys.h> @@ -64,8 +63,13 @@ void __noreturn cpu_idle(void)  			smtc_idle_loop_hook();  #endif -			if (cpu_wait) + +			if (cpu_wait) { +				/* Don't trace irqs off for idle */ +				stop_critical_timings();  				(*cpu_wait)(); +				start_critical_timings(); +			}  		}  #ifdef CONFIG_HOTPLUG_CPU  		if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 054861ccb4d..c51b95ff864 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -493,36 +493,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)  		ret = ptrace_setfpregs(child, (__u32 __user *) data);  		break; -	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ -	case PTRACE_CONT: { /* restart after signal. */ -		ret = -EIO; -		if (!valid_signal(data)) -			break; -		if (request == PTRACE_SYSCALL) { -			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -		} -		else { -			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -		} -		child->exit_code = data; -		wake_up_process(child); -		ret = 0; -		break; -	} - -	/* -	 * make the child exit.  Best I can do is send it a sigkill. -	 * perhaps it should be put in the status that it wants to -	 * exit. -	 */ -	case PTRACE_KILL: -		ret = 0; -		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */ -			break; -		child->exit_code = SIGKILL; -		wake_up_process(child); -		break; -  	case PTRACE_GET_THREAD_AREA:  		ret = put_user(task_thread_info(child)->tp_value,  				(unsigned long __user *) data); diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index dcaed1bbbfe..26f9b9ab19c 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -23,7 +23,6 @@  #include <linux/fs.h>  #include <linux/init.h>  #include <asm/uaccess.h> -#include <linux/slab.h>  #include <linux/list.h>  #include <linux/vmalloc.h>  #include <linux/elf.h> diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 66b5a48676d..a5297e2a353 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -181,7 +181,7 @@ EXPORT(sysn32_call_table)  	PTR	sys_exit  	PTR	compat_sys_wait4  	PTR	sys_kill			/* 6060 */ -	PTR	sys_32_newuname +	PTR	sys_newuname  	PTR	sys_semget  	PTR	sys_semop  	PTR	sys_n32_semctl @@ -385,7 +385,7 @@ EXPORT(sysn32_call_table)  	PTR	sys_fchmodat  	PTR	sys_faccessat  	PTR	compat_sys_pselect6 -	PTR	sys_ppoll			/* 6265 */ +	PTR	compat_sys_ppoll		/* 6265 */  	PTR	sys_unshare  	PTR	sys_splice  	PTR	sys_sync_file_range diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 515f9eab2b2..813689ef238 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -325,7 +325,7 @@ sys_call_table:  	PTR	sys32_sigreturn  	PTR	sys32_clone			/* 4120 */  	PTR	sys_setdomainname -	PTR	sys_32_newuname +	PTR	sys_newuname  	PTR	sys_ni_syscall			/* sys_modify_ldt */  	PTR	compat_sys_adjtimex  	PTR	sys_mprotect			/* 4125 */ diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index 6c8e8c4246f..10263b40598 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h @@ -26,11 +26,6 @@   */  extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,  				 size_t frame_size); -/* - * install trampoline code to get back from the sig handler - */ -extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); -  /* Check and clear pending FPU exceptions in saved CSR */  extern int fpcsr_pending(unsigned int __user *fpcsr); diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index d0c68b5d717..2099d5a4c4b 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -32,6 +32,7 @@  #include <asm/ucontext.h>  #include <asm/cpu-features.h>  #include <asm/war.h> +#include <asm/vdso.h>  #include "signal-common.h" @@ -44,47 +45,20 @@ extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);  extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);  extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); -/* - * Horribly complicated - with the bloody RM9000 workarounds enabled - * the signal trampolines is moving to the end of the structure so we can - * increase the alignment without breaking software compatibility. - */ -#if ICACHE_REFILLS_WORKAROUND_WAR == 0 -  struct sigframe {  	u32 sf_ass[4];		/* argument save space for o32 */ -	u32 sf_code[2];		/* signal trampoline */ +	u32 sf_pad[2];		/* Was: signal trampoline */  	struct sigcontext sf_sc;  	sigset_t sf_mask;  };  struct rt_sigframe {  	u32 rs_ass[4];		/* argument save space for o32 */ -	u32 rs_code[2];		/* signal trampoline */ +	u32 rs_pad[2];		/* Was: signal trampoline */  	struct siginfo rs_info;  	struct ucontext rs_uc;  }; -#else - -struct sigframe { -	u32 sf_ass[4];			/* argument save space for o32 */ -	u32 sf_pad[2]; -	struct sigcontext sf_sc;	/* hw context */ -	sigset_t sf_mask; -	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */ -}; - -struct rt_sigframe { -	u32 rs_ass[4];			/* argument save space for o32 */ -	u32 rs_pad[2]; -	struct siginfo rs_info; -	struct ucontext rs_uc; -	u32 rs_code[8] ____cacheline_aligned;	/* signal trampoline */ -}; - -#endif -  /*   * Helper routines   */ @@ -266,32 +240,6 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,  	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));  } -int install_sigtramp(unsigned int __user *tramp, unsigned int syscall) -{ -	int err; - -	/* -	 * Set up the return code ... -	 * -	 *         li      v0, __NR__foo_sigreturn -	 *         syscall -	 */ - -	err = __put_user(0x24020000 + syscall, tramp + 0); -	err |= __put_user(0x0000000c         , tramp + 1); -	if (ICACHE_REFILLS_WORKAROUND_WAR) { -		err |= __put_user(0, tramp + 2); -		err |= __put_user(0, tramp + 3); -		err |= __put_user(0, tramp + 4); -		err |= __put_user(0, tramp + 5); -		err |= __put_user(0, tramp + 6); -		err |= __put_user(0, tramp + 7); -	} -	flush_cache_sigtramp((unsigned long) tramp); - -	return err; -} -  /*   * Atomically swap in the new signal mask, and wait for a signal.   */ @@ -484,8 +432,8 @@ badframe:  }  #ifdef CONFIG_TRAD_SIGNALS -static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, -	int signr, sigset_t *set) +static int setup_frame(void *sig_return, struct k_sigaction *ka, +		       struct pt_regs *regs, int signr, sigset_t *set)  {  	struct sigframe __user *frame;  	int err = 0; @@ -494,8 +442,6 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))  		goto give_sigsegv; -	err |= install_sigtramp(frame->sf_code, __NR_sigreturn); -  	err |= setup_sigcontext(regs, &frame->sf_sc);  	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));  	if (err) @@ -515,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,  	regs->regs[ 5] = 0;  	regs->regs[ 6] = (unsigned long) &frame->sf_sc;  	regs->regs[29] = (unsigned long) frame; -	regs->regs[31] = (unsigned long) frame->sf_code; +	regs->regs[31] = (unsigned long) sig_return;  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", @@ -529,8 +475,9 @@ give_sigsegv:  }  #endif -static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, -	int signr, sigset_t *set, siginfo_t *info) +static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, +			  struct pt_regs *regs,	int signr, sigset_t *set, +			  siginfo_t *info)  {  	struct rt_sigframe __user *frame;  	int err = 0; @@ -539,8 +486,6 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))  		goto give_sigsegv; -	err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn); -  	/* Create siginfo.  */  	err |= copy_siginfo_to_user(&frame->rs_info, info); @@ -573,7 +518,7 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,  	regs->regs[ 5] = (unsigned long) &frame->rs_info;  	regs->regs[ 6] = (unsigned long) &frame->rs_uc;  	regs->regs[29] = (unsigned long) frame; -	regs->regs[31] = (unsigned long) frame->rs_code; +	regs->regs[31] = (unsigned long) sig_return;  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", @@ -590,8 +535,11 @@ give_sigsegv:  struct mips_abi mips_abi = {  #ifdef CONFIG_TRAD_SIGNALS  	.setup_frame	= setup_frame, +	.signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),  #endif  	.setup_rt_frame	= setup_rt_frame, +	.rt_signal_return_offset = +		offsetof(struct mips_vdso, rt_signal_trampoline),  	.restart	= __NR_restart_syscall  }; @@ -599,6 +547,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,  	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)  {  	int ret; +	struct mips_abi *abi = current->thread.abi; +	void *vdso = current->mm->context.vdso;  	switch(regs->regs[0]) {  	case ERESTART_RESTARTBLOCK: @@ -619,9 +569,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,  	regs->regs[0] = 0;		/* Don't deal with this again.  */  	if (sig_uses_siginfo(ka)) -		ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); +		ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, +					  ka, regs, sig, oldset, info);  	else -		ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); +		ret = abi->setup_frame(vdso + abi->signal_return_offset, +				       ka, regs, sig, oldset);  	spin_lock_irq(¤t->sighand->siglock);  	sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 03abaf048f0..a0ed0e052b2 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -32,6 +32,7 @@  #include <asm/system.h>  #include <asm/fpu.h>  #include <asm/war.h> +#include <asm/vdso.h>  #include "signal-common.h" @@ -47,8 +48,6 @@ extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user  /*   * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...   */ -#define __NR_O32_sigreturn		4119 -#define __NR_O32_rt_sigreturn		4193  #define __NR_O32_restart_syscall        4253  /* 32-bit compatibility types */ @@ -77,47 +76,20 @@ struct ucontext32 {  	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */  }; -/* - * Horribly complicated - with the bloody RM9000 workarounds enabled - * the signal trampolines is moving to the end of the structure so we can - * increase the alignment without breaking software compatibility. - */ -#if ICACHE_REFILLS_WORKAROUND_WAR == 0 -  struct sigframe32 {  	u32 sf_ass[4];		/* argument save space for o32 */ -	u32 sf_code[2];		/* signal trampoline */ +	u32 sf_pad[2];		/* Was: signal trampoline */  	struct sigcontext32 sf_sc;  	compat_sigset_t sf_mask;  };  struct rt_sigframe32 {  	u32 rs_ass[4];			/* argument save space for o32 */ -	u32 rs_code[2];			/* signal trampoline */ +	u32 rs_pad[2];			/* Was: signal trampoline */  	compat_siginfo_t rs_info;  	struct ucontext32 rs_uc;  }; -#else  /* ICACHE_REFILLS_WORKAROUND_WAR */ - -struct sigframe32 { -	u32 sf_ass[4];			/* argument save space for o32 */ -	u32 sf_pad[2]; -	struct sigcontext32 sf_sc;	/* hw context */ -	compat_sigset_t sf_mask; -	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */ -}; - -struct rt_sigframe32 { -	u32 rs_ass[4];			/* argument save space for o32 */ -	u32 rs_pad[2]; -	compat_siginfo_t rs_info; -	struct ucontext32 rs_uc; -	u32 rs_code[8] __attribute__((aligned(32)));	/* signal trampoline */ -}; - -#endif	/* !ICACHE_REFILLS_WORKAROUND_WAR */ -  /*   * sigcontext handlers   */ @@ -598,8 +570,8 @@ badframe:  	force_sig(SIGSEGV, current);  } -static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, -	int signr, sigset_t *set) +static int setup_frame_32(void *sig_return, struct k_sigaction *ka, +			  struct pt_regs *regs, int signr, sigset_t *set)  {  	struct sigframe32 __user *frame;  	int err = 0; @@ -608,8 +580,6 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))  		goto give_sigsegv; -	err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn); -  	err |= setup_sigcontext32(regs, &frame->sf_sc);  	err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); @@ -630,7 +600,7 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,  	regs->regs[ 5] = 0;  	regs->regs[ 6] = (unsigned long) &frame->sf_sc;  	regs->regs[29] = (unsigned long) frame; -	regs->regs[31] = (unsigned long) frame->sf_code; +	regs->regs[31] = (unsigned long) sig_return;  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", @@ -644,8 +614,9 @@ give_sigsegv:  	return -EFAULT;  } -static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, -	int signr, sigset_t *set, siginfo_t *info) +static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, +			     struct pt_regs *regs, int signr, sigset_t *set, +			     siginfo_t *info)  {  	struct rt_sigframe32 __user *frame;  	int err = 0; @@ -655,8 +626,6 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))  		goto give_sigsegv; -	err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn); -  	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */  	err |= copy_siginfo_to_user32(&frame->rs_info, info); @@ -690,7 +659,7 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,  	regs->regs[ 5] = (unsigned long) &frame->rs_info;  	regs->regs[ 6] = (unsigned long) &frame->rs_uc;  	regs->regs[29] = (unsigned long) frame; -	regs->regs[31] = (unsigned long) frame->rs_code; +	regs->regs[31] = (unsigned long) sig_return;  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", @@ -709,7 +678,11 @@ give_sigsegv:   */  struct mips_abi mips_abi_32 = {  	.setup_frame	= setup_frame_32, +	.signal_return_offset = +		offsetof(struct mips_vdso, o32_signal_trampoline),  	.setup_rt_frame	= setup_rt_frame_32, +	.rt_signal_return_offset = +		offsetof(struct mips_vdso, o32_rt_signal_trampoline),  	.restart	= __NR_O32_restart_syscall  }; diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index bb277e82d42..2c5df818c65 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -39,13 +39,13 @@  #include <asm/fpu.h>  #include <asm/cpu-features.h>  #include <asm/war.h> +#include <asm/vdso.h>  #include "signal-common.h"  /*   * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...   */ -#define __NR_N32_rt_sigreturn		6211  #define __NR_N32_restart_syscall	6214  extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); @@ -67,27 +67,13 @@ struct ucontextn32 {  	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */  }; -#if ICACHE_REFILLS_WORKAROUND_WAR == 0 - -struct rt_sigframe_n32 { -	u32 rs_ass[4];			/* argument save space for o32 */ -	u32 rs_code[2];			/* signal trampoline */ -	struct compat_siginfo rs_info; -	struct ucontextn32 rs_uc; -}; - -#else  /* ICACHE_REFILLS_WORKAROUND_WAR */ -  struct rt_sigframe_n32 {  	u32 rs_ass[4];			/* argument save space for o32 */ -	u32 rs_pad[2]; +	u32 rs_pad[2];			/* Was: signal trampoline */  	struct compat_siginfo rs_info;  	struct ucontextn32 rs_uc; -	u32 rs_code[8] ____cacheline_aligned;		/* signal trampoline */  }; -#endif	/* !ICACHE_REFILLS_WORKAROUND_WAR */ -  extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);  asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) @@ -173,7 +159,7 @@ badframe:  	force_sig(SIGSEGV, current);  } -static int setup_rt_frame_n32(struct k_sigaction * ka, +static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,  	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)  {  	struct rt_sigframe_n32 __user *frame; @@ -184,8 +170,6 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))  		goto give_sigsegv; -	install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn); -  	/* Create siginfo.  */  	err |= copy_siginfo_to_user32(&frame->rs_info, info); @@ -219,7 +203,7 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,  	regs->regs[ 5] = (unsigned long) &frame->rs_info;  	regs->regs[ 6] = (unsigned long) &frame->rs_uc;  	regs->regs[29] = (unsigned long) frame; -	regs->regs[31] = (unsigned long) frame->rs_code; +	regs->regs[31] = (unsigned long) sig_return;  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", @@ -235,5 +219,7 @@ give_sigsegv:  struct mips_abi mips_abi_n32 = {  	.setup_rt_frame	= setup_rt_frame_n32, +	.rt_signal_return_offset = +		offsetof(struct mips_vdso, n32_rt_signal_trampoline),  	.restart	= __NR_N32_restart_syscall  }; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 23499b5bd9c..a95dea5459c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -26,6 +26,7 @@  #include <linux/kernel_stat.h>  #include <linux/module.h>  #include <linux/ftrace.h> +#include <linux/slab.h>  #include <asm/cpu.h>  #include <asm/processor.h> @@ -181,7 +182,7 @@ static int vpemask[2][8] = {  	{0, 0, 0, 0, 0, 0, 0, 1}  };  int tcnoprog[NR_CPUS]; -static atomic_t idle_hook_initialized = {0}; +static atomic_t idle_hook_initialized = ATOMIC_INIT(0);  static int clock_hang_reported[NR_CPUS];  #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 3f7f466190b..dd81b0f8751 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -19,7 +19,6 @@  #include <linux/string.h>  #include <linux/syscalls.h>  #include <linux/file.h> -#include <linux/slab.h>  #include <linux/utsname.h>  #include <linux/unistd.h>  #include <linux/sem.h> @@ -29,6 +28,7 @@  #include <linux/module.h>  #include <linux/ipc.h>  #include <linux/uaccess.h> +#include <linux/slab.h>  #include <asm/asm.h>  #include <asm/branch.h> @@ -79,7 +79,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,  	int do_color_align;  	unsigned long task_size; -	task_size = STACK_TOP; +#ifdef CONFIG_32BIT +	task_size = TASK_SIZE; +#else /* Must be CONFIG_64BIT*/ +	task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE; +#endif  	if (len > task_size)  		return -ENOMEM; @@ -215,48 +219,6 @@ out:  	return error;  } -/* - * Compacrapability ... - */ -SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) -{ -	if (name && !copy_to_user(name, utsname(), sizeof (*name))) -		return 0; -	return -EFAULT; -} - -/* - * Compacrapability ... - */ -SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) -{ -	int error; - -	if (!name) -		return -EFAULT; -	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) -		return -EFAULT; - -	error = __copy_to_user(&name->sysname, &utsname()->sysname, -			       __OLD_UTS_LEN); -	error -= __put_user(0, name->sysname + __OLD_UTS_LEN); -	error -= __copy_to_user(&name->nodename, &utsname()->nodename, -				__OLD_UTS_LEN); -	error -= __put_user(0, name->nodename + __OLD_UTS_LEN); -	error -= __copy_to_user(&name->release, &utsname()->release, -				__OLD_UTS_LEN); -	error -= __put_user(0, name->release + __OLD_UTS_LEN); -	error -= __copy_to_user(&name->version, &utsname()->version, -				__OLD_UTS_LEN); -	error -= __put_user(0, name->version + __OLD_UTS_LEN); -	error -= __copy_to_user(&name->machine, &utsname()->machine, -				__OLD_UTS_LEN); -	error = __put_user(0, name->machine + __OLD_UTS_LEN); -	error = error ? -EFAULT : 0; - -	return error; -} -  SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)  {  	struct thread_info *ti = task_thread_info(current); @@ -407,94 +369,6 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs)  }  /* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second, -	unsigned long, third, void __user *, ptr, long, fifth) -{ -	int version, ret; - -	version = call >> 16; /* hack for backward compatibility */ -	call &= 0xffff; - -	switch (call) { -	case SEMOP: -		return sys_semtimedop(first, (struct sembuf __user *)ptr, -		                      second, NULL); -	case SEMTIMEDOP: -		return sys_semtimedop(first, (struct sembuf __user *)ptr, -				      second, -				      (const struct timespec __user *)fifth); -	case SEMGET: -		return sys_semget(first, second, third); -	case SEMCTL: { -		union semun fourth; -		if (!ptr) -			return -EINVAL; -		if (get_user(fourth.__pad, (void __user *__user *) ptr)) -			return -EFAULT; -		return sys_semctl(first, second, third, fourth); -	} - -	case MSGSND: -		return sys_msgsnd(first, (struct msgbuf __user *) ptr, -				  second, third); -	case MSGRCV: -		switch (version) { -		case 0: { -			struct ipc_kludge tmp; -			if (!ptr) -				return -EINVAL; - -			if (copy_from_user(&tmp, -					   (struct ipc_kludge __user *) ptr, -					   sizeof(tmp))) -				return -EFAULT; -			return sys_msgrcv(first, tmp.msgp, second, -					  tmp.msgtyp, third); -		} -		default: -			return sys_msgrcv(first, -					  (struct msgbuf __user *) ptr, -					  second, fifth, third); -		} -	case MSGGET: -		return sys_msgget((key_t) first, second); -	case MSGCTL: -		return sys_msgctl(first, second, -				  (struct msqid_ds __user *) ptr); - -	case SHMAT: -		switch (version) { -		default: { -			unsigned long raddr; -			ret = do_shmat(first, (char __user *) ptr, second, -				       &raddr); -			if (ret) -				return ret; -			return put_user(raddr, (unsigned long __user *) third); -		} -		case 1:	/* iBCS2 emulator entry point */ -			if (!segment_eq(get_fs(), get_ds())) -				return -EINVAL; -			return do_shmat(first, (char __user *) ptr, second, -				        (unsigned long *) third); -		} -	case SHMDT: -		return sys_shmdt((char __user *)ptr); -	case SHMGET: -		return sys_shmget(first, second, third); -	case SHMCTL: -		return sys_shmctl(first, second, -				  (struct shmid_ds __user *) ptr); -	default: -		return -ENOSYS; -	} -} - -/*   * No implemented yet ...   */  SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 4e00f9bc23e..d612c6dcb74 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -352,9 +352,10 @@ void show_registers(const struct pt_regs *regs)  static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, const struct pt_regs * regs) +void __noreturn die(const char * str, struct pt_regs * regs)  {  	static int die_counter; +	int sig = SIGSEGV;  #ifdef CONFIG_MIPS_MT_SMTC  	unsigned long dvpret = dvpe();  #endif /* CONFIG_MIPS_MT_SMTC */ @@ -365,6 +366,10 @@ void __noreturn die(const char * str, const struct pt_regs * regs)  #ifdef CONFIG_MIPS_MT_SMTC  	mips_mt_regdump(dvpret);  #endif /* CONFIG_MIPS_MT_SMTC */ + +	if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) +		sig = 0; +  	printk("%s[#%d]:\n", str, ++die_counter);  	show_registers(regs);  	add_taint(TAINT_DIE); @@ -379,7 +384,7 @@ void __noreturn die(const char * str, const struct pt_regs * regs)  		panic("Fatal exception");  	} -	do_exit(SIGSEGV); +	do_exit(sig);  }  extern struct exception_table_entry __start___dbe_table[]; @@ -1557,12 +1562,7 @@ static char panic_null_cerr[] __cpuinitdata =  void __cpuinit set_uncached_handler(unsigned long offset, void *addr,  	unsigned long size)  { -#ifdef CONFIG_32BIT -	unsigned long uncached_ebase = KSEG1ADDR(ebase); -#endif -#ifdef CONFIG_64BIT -	unsigned long uncached_ebase = TO_UNCAC(ebase); -#endif +	unsigned long uncached_ebase = CKSEG1ADDR(ebase);  	if (!addr)  		panic(panic_null_cerr); @@ -1599,7 +1599,7 @@ void __init trap_init(void)  		ebase = (unsigned long)  			__alloc_bootmem(size, 1 << fls(size), 0);  	} else { -		ebase = CAC_BASE; +		ebase = CKSEG0;  		if (cpu_has_mips_r2)  			ebase += (read_c0_ebase() & 0x3ffff000);  	} diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c new file mode 100644 index 00000000000..b773c1112b1 --- /dev/null +++ b/arch/mips/kernel/vdso.c @@ -0,0 +1,112 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2009, 2010 Cavium Networks, Inc. + */ + + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/binfmts.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/unistd.h> + +#include <asm/vdso.h> +#include <asm/uasm.h> + +/* + * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... + */ +#define __NR_O32_sigreturn		4119 +#define __NR_O32_rt_sigreturn		4193 +#define __NR_N32_rt_sigreturn		6211 + +static struct page *vdso_page; + +static void __init install_trampoline(u32 *tramp, unsigned int sigreturn) +{ +	uasm_i_addiu(&tramp, 2, 0, sigreturn);	/* li v0, sigreturn */ +	uasm_i_syscall(&tramp, 0); +} + +static int __init init_vdso(void) +{ +	struct mips_vdso *vdso; + +	vdso_page = alloc_page(GFP_KERNEL); +	if (!vdso_page) +		panic("Cannot allocate vdso"); + +	vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL); +	if (!vdso) +		panic("Cannot map vdso"); +	clear_page(vdso); + +	install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn); +#ifdef CONFIG_32BIT +	install_trampoline(vdso->signal_trampoline, __NR_sigreturn); +#else +	install_trampoline(vdso->n32_rt_signal_trampoline, +			   __NR_N32_rt_sigreturn); +	install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn); +	install_trampoline(vdso->o32_rt_signal_trampoline, +			   __NR_O32_rt_sigreturn); +#endif + +	vunmap(vdso); + +	pr_notice("init_vdso successfull\n"); + +	return 0; +} +device_initcall(init_vdso); + +static unsigned long vdso_addr(unsigned long start) +{ +	return STACK_TOP; +} + +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) +{ +	int ret; +	unsigned long addr; +	struct mm_struct *mm = current->mm; + +	down_write(&mm->mmap_sem); + +	addr = vdso_addr(mm->start_stack); + +	addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0); +	if (IS_ERR_VALUE(addr)) { +		ret = addr; +		goto up_fail; +	} + +	ret = install_special_mapping(mm, addr, PAGE_SIZE, +				      VM_READ|VM_EXEC| +				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| +				      VM_ALWAYSDUMP, +				      &vdso_page); + +	if (ret) +		goto up_fail; + +	mm->context.vdso = (void *)addr; + +up_fail: +	up_write(&mm->mmap_sem); +	return ret; +} + +const char *arch_vma_name(struct vm_area_struct *vma) +{ +	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) +		return "[vdso]"; +	return NULL; +}  |