From 5a0e3ad6af8660be21ca98a971cd00f331318c05 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Mar 2010 17:04:11 +0900 Subject: include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo Guess-its-ok-by: Christoph Lameter Cc: Ingo Molnar Cc: Lee Schermerhorn --- arch/mips/kernel/irq.c | 1 - arch/mips/kernel/linux32.c | 2 +- arch/mips/kernel/process.c | 1 - arch/mips/kernel/rtlx.c | 1 - arch/mips/kernel/smtc.c | 1 + arch/mips/kernel/syscall.c | 2 +- 6 files changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel') 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 #include #include -#include #include #include #include diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index a39d0597a37..c2dab140dc9 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index f3d73e1831c..463b71b90a0 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include 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 #include #include -#include #include #include #include diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 23499b5bd9c..25e825aea32 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index e96b1c30c7a..9587abc67f3 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include -- cgit From 7a7ac952d5217b2f568e5ef91ac39b572e166f24 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 10 Mar 2010 00:27:28 +0800 Subject: MIPS: Trace: Don't trace irqsoff for the idle process Like x86 did in arch/x86/kernel/{process_32.c,process_64.c}, also don't trace irqsoff for idle. If there's no useful work to be done, we don't care about the irqsoff duration. If we trace the idle process, the max duration of irqsoff will be the idle time and make the irqsoff tracer useless. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Patchwork: http://patchwork.linux-mips.org/patch/1044/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 463b71b90a0..99960940d4a 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -63,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) && -- cgit From 52553664033078102f5f430c861ccd0863b1b708 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sat, 27 Feb 2010 12:02:51 -0500 Subject: MIPS: Initialize an atomic_t properly with ATOMIC_INIT(0). Signed-off-by: Robert P. J. Day To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1008/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 25e825aea32..a95dea5459c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -182,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 */ -- cgit From 582b65e4d3f9664f87661359af99def304bc68bb Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 10 Mar 2010 00:53:21 +0800 Subject: MIPS: Loongson: Add module info to the loongson2_clock driver This patch fixes a kernel warning when loading the the loongson2_clock driver: "Feb 25 23:42:27 localhost kernel: [ 4.965000] loongson2_clock: module license 'unspecified' taints kernel." Signed-off-by: Wu Zhangjin Reported-by: Liu Shiwei Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1045/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpufreq/loongson2_clock.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/mips/kernel') 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 "); +MODULE_DESCRIPTION("cpufreq driver for Loongson 2F"); +MODULE_LICENSE("GPL"); -- cgit From c52d0d30aef84aa8893b34e5254716c8ab5c4472 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 18 Feb 2010 16:13:04 -0800 Subject: MIPS: Preliminary VDSO This is a preliminary patch to add a vdso to all user processes. Still missing are ELF headers and .eh_frame information. But it is enough to allow us to move signal trampolines off of the stack. Note that emulation of branch delay slots in the FPU emulator still requires the stack. We allocate a single page (the vdso) and write all possible signal trampolines into it. The stack is moved down by one page and the vdso is mapped into this space. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/975/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/syscall.c | 6 ++- arch/mips/kernel/vdso.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 arch/mips/kernel/vdso.c (limited to 'arch/mips/kernel') 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/syscall.c b/arch/mips/kernel/syscall.c index 9587abc67f3..dd81b0f8751 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -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; 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Including 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; +} -- cgit From d814c28ceca8f659c0012eaec8e21eee43710716 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 18 Feb 2010 16:13:05 -0800 Subject: MIPS: Move signal trampolines off of the stack. This is a follow on to the vdso patch. Since all processes now have signal trampolines permanently mapped, we can use those instead of putting the trampoline on the stack and invalidating the corresponding icache across all CPUs. We also get rid of a bunch of ICACHE_REFILLS_WORKAROUND_WAR code. [Ralf: GDB 7.1 which has the necessary modifications to allow backtracing over signal frames will supposedly be released tomorrow. The old signal frame format obsoleted by this patch exists in two variations, for sane processors and for those requiring ICACHE_REFILLS_WORKAROUND_WAR. So there was never a GDB which did support backtracing over signal frames on all MIPS systems. This convinved me this series should be applied and pushed upstream as soon as possible.] Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/974/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/signal-common.h | 5 --- arch/mips/kernel/signal.c | 86 +++++++++------------------------------- arch/mips/kernel/signal32.c | 55 +++++++------------------ arch/mips/kernel/signal_n32.c | 26 +++--------- 4 files changed, 39 insertions(+), 133 deletions(-) (limited to 'arch/mips/kernel') 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 #include #include +#include #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 #include #include +#include #include "signal-common.h" @@ -47,8 +48,6 @@ extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user /* * Including 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 #include #include +#include #include "signal-common.h" /* * Including 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 }; -- cgit From f6be75d03c8870be91e6e2a195648ece04b6bb16 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 6 Apr 2010 13:29:50 -0700 Subject: MIPS: Calculate proper ebase value for 64-bit kernels The ebase is relative to CKSEG0 not CAC_BASE. On a 32-bit kernel they are the same thing, for a 64-bit kernel they are not. It happens to kind of work on a 64-bit kernel as they both reference the same physical memory. However since the CPU uses the CKSEG0 base, determining if a J instruction will reach always gives the wrong result unless we use the same number the CPU uses. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1093/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 4e00f9bc23e..1a4dd657ccb 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -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); } -- cgit