aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/syscall.c6
-rw-r--r--arch/mips/kernel/vdso.c112
3 files changed, 118 insertions, 2 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index ef20957ca14b..7a6ac501cbb5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ 7obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
8 ptrace.o reset.o setup.o signal.o syscall.o \ 8 ptrace.o reset.o setup.o signal.o syscall.o \
9 time.o topology.o traps.o unaligned.o watch.o 9 time.o topology.o traps.o unaligned.o watch.o vdso.o
10 10
11ifdef CONFIG_FUNCTION_TRACER 11ifdef CONFIG_FUNCTION_TRACER
12CFLAGS_REMOVE_ftrace.o = -pg 12CFLAGS_REMOVE_ftrace.o = -pg
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 9587abc67f35..dd81b0f87518 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,
79 int do_color_align; 79 int do_color_align;
80 unsigned long task_size; 80 unsigned long task_size;
81 81
82 task_size = STACK_TOP; 82#ifdef CONFIG_32BIT
83 task_size = TASK_SIZE;
84#else /* Must be CONFIG_64BIT*/
85 task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE;
86#endif
83 87
84 if (len > task_size) 88 if (len > task_size)
85 return -ENOMEM; 89 return -ENOMEM;
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
new file mode 100644
index 000000000000..b773c1112b14
--- /dev/null
+++ b/arch/mips/kernel/vdso.c
@@ -0,0 +1,112 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2009, 2010 Cavium Networks, Inc.
7 */
8
9
10#include <linux/kernel.h>
11#include <linux/err.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/init.h>
15#include <linux/binfmts.h>
16#include <linux/elf.h>
17#include <linux/vmalloc.h>
18#include <linux/unistd.h>
19
20#include <asm/vdso.h>
21#include <asm/uasm.h>
22
23/*
24 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
25 */
26#define __NR_O32_sigreturn 4119
27#define __NR_O32_rt_sigreturn 4193
28#define __NR_N32_rt_sigreturn 6211
29
30static struct page *vdso_page;
31
32static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
33{
34 uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */
35 uasm_i_syscall(&tramp, 0);
36}
37
38static int __init init_vdso(void)
39{
40 struct mips_vdso *vdso;
41
42 vdso_page = alloc_page(GFP_KERNEL);
43 if (!vdso_page)
44 panic("Cannot allocate vdso");
45
46 vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
47 if (!vdso)
48 panic("Cannot map vdso");
49 clear_page(vdso);
50
51 install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
52#ifdef CONFIG_32BIT
53 install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
54#else
55 install_trampoline(vdso->n32_rt_signal_trampoline,
56 __NR_N32_rt_sigreturn);
57 install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
58 install_trampoline(vdso->o32_rt_signal_trampoline,
59 __NR_O32_rt_sigreturn);
60#endif
61
62 vunmap(vdso);
63
64 pr_notice("init_vdso successfull\n");
65
66 return 0;
67}
68device_initcall(init_vdso);
69
70static unsigned long vdso_addr(unsigned long start)
71{
72 return STACK_TOP;
73}
74
75int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
76{
77 int ret;
78 unsigned long addr;
79 struct mm_struct *mm = current->mm;
80
81 down_write(&mm->mmap_sem);
82
83 addr = vdso_addr(mm->start_stack);
84
85 addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
86 if (IS_ERR_VALUE(addr)) {
87 ret = addr;
88 goto up_fail;
89 }
90
91 ret = install_special_mapping(mm, addr, PAGE_SIZE,
92 VM_READ|VM_EXEC|
93 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
94 VM_ALWAYSDUMP,
95 &vdso_page);
96
97 if (ret)
98 goto up_fail;
99
100 mm->context.vdso = (void *)addr;
101
102up_fail:
103 up_write(&mm->mmap_sem);
104 return ret;
105}
106
107const char *arch_vma_name(struct vm_area_struct *vma)
108{
109 if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
110 return "[vdso]";
111 return NULL;
112}