aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-08-07 15:33:32 -0400
committerChris Metcalf <cmetcalf@tilera.com>2013-08-13 16:26:21 -0400
commit4a556f4f56da3110b27e265b79f0e7582115445c (patch)
treef5af0b865c867160855e4722b49d7e850dddf944
parent0c1d1917c547c8e787fb58e20e2de577453c980c (diff)
tile: implement gettimeofday() via vDSO
This change creates the framework for vDSO calls, makes the existing rt_sigreturn() mechanism use it, and adds a fast gettimeofday(). Now that we need to expose the vDSO address to userspace, we add AT_SYSINFO_EHDR to the set of aux entries provided to userspace. (You can disable any extra vDSO support by booting with vdso=0, but the rt_sigreturn vDSO page will still be provided.) Note that glibc has supported the tile vDSO since release 2.17. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
-rw-r--r--arch/tile/Kconfig3
-rw-r--r--arch/tile/include/asm/elf.h5
-rw-r--r--arch/tile/include/asm/mmu.h1
-rw-r--r--arch/tile/include/asm/page.h8
-rw-r--r--arch/tile/include/asm/processor.h6
-rw-r--r--arch/tile/include/asm/sections.h4
-rw-r--r--arch/tile/include/asm/vdso.h49
-rw-r--r--arch/tile/include/uapi/asm/auxvec.h3
-rw-r--r--arch/tile/kernel/Makefile4
-rw-r--r--arch/tile/kernel/compat_signal.c3
-rw-r--r--arch/tile/kernel/entry.S16
-rw-r--r--arch/tile/kernel/signal.c3
-rw-r--r--arch/tile/kernel/stack.c5
-rw-r--r--arch/tile/kernel/time.c37
-rw-r--r--arch/tile/kernel/vdso.c212
-rw-r--r--arch/tile/kernel/vdso/Makefile118
-rw-r--r--arch/tile/kernel/vdso/vdso.S28
-rw-r--r--arch/tile/kernel/vdso/vdso.lds.S87
-rw-r--r--arch/tile/kernel/vdso/vdso32.S28
-rw-r--r--arch/tile/kernel/vdso/vgettimeofday.c107
-rw-r--r--arch/tile/kernel/vdso/vrt_sigreturn.S30
-rw-r--r--arch/tile/mm/elf.c37
22 files changed, 732 insertions, 62 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 1126b9d2f4cc..7b87318ee690 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -64,6 +64,9 @@ config HUGETLB_SUPER_PAGES
64 depends on HUGETLB_PAGE && TILEGX 64 depends on HUGETLB_PAGE && TILEGX
65 def_bool y 65 def_bool y
66 66
67config GENERIC_TIME_VSYSCALL
68 def_bool y
69
67# FIXME: tilegx can implement a more efficient rwsem. 70# FIXME: tilegx can implement a more efficient rwsem.
68config RWSEM_GENERIC_SPINLOCK 71config RWSEM_GENERIC_SPINLOCK
69 def_bool y 72 def_bool y
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index ff8a93408823..31d854f1b83b 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -132,6 +132,11 @@ extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
132struct linux_binprm; 132struct linux_binprm;
133extern int arch_setup_additional_pages(struct linux_binprm *bprm, 133extern int arch_setup_additional_pages(struct linux_binprm *bprm,
134 int executable_stack); 134 int executable_stack);
135#define ARCH_DLINFO \
136do { \
137 NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \
138} while (0)
139
135#ifdef CONFIG_COMPAT 140#ifdef CONFIG_COMPAT
136 141
137#define COMPAT_ELF_PLATFORM "tilegx-m32" 142#define COMPAT_ELF_PLATFORM "tilegx-m32"
diff --git a/arch/tile/include/asm/mmu.h b/arch/tile/include/asm/mmu.h
index e2c789096795..0cab1182bde1 100644
--- a/arch/tile/include/asm/mmu.h
+++ b/arch/tile/include/asm/mmu.h
@@ -22,6 +22,7 @@ struct mm_context {
22 * semaphore but atomically, but it is conservatively set. 22 * semaphore but atomically, but it is conservatively set.
23 */ 23 */
24 unsigned long priority_cached; 24 unsigned long priority_cached;
25 unsigned long vdso_base;
25}; 26};
26 27
27typedef struct mm_context mm_context_t; 28typedef struct mm_context mm_context_t;
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index dd033a4fd627..b4f96c0024df 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -39,6 +39,12 @@
39#define HPAGE_MASK (~(HPAGE_SIZE - 1)) 39#define HPAGE_MASK (~(HPAGE_SIZE - 1))
40 40
41/* 41/*
42 * We do define AT_SYSINFO_EHDR to support vDSO,
43 * but don't use the gate mechanism.
44 */
45#define __HAVE_ARCH_GATE_AREA 1
46
47/*
42 * If the Kconfig doesn't specify, set a maximum zone order that 48 * If the Kconfig doesn't specify, set a maximum zone order that
43 * is enough so that we can create huge pages from small pages given 49 * is enough so that we can create huge pages from small pages given
44 * the respective sizes of the two page types. See <linux/mmzone.h>. 50 * the respective sizes of the two page types. See <linux/mmzone.h>.
@@ -246,7 +252,7 @@ static inline __attribute_const__ int get_order(unsigned long size)
246 252
247#endif /* __tilegx__ */ 253#endif /* __tilegx__ */
248 254
249#ifndef __ASSEMBLY__ 255#if !defined(__ASSEMBLY__) && !defined(VDSO_BUILD)
250 256
251#ifdef CONFIG_HIGHMEM 257#ifdef CONFIG_HIGHMEM
252 258
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index fed1c044fec8..461322b473b5 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -180,10 +180,10 @@ struct thread_struct {
180#define TASK_SIZE TASK_SIZE_MAX 180#define TASK_SIZE TASK_SIZE_MAX
181#endif 181#endif
182 182
183/* We provide a minimal "vdso" a la x86; just the sigreturn code for now. */ 183#define VDSO_BASE ((unsigned long)current->active_mm->context.vdso_base)
184#define VDSO_BASE (TASK_SIZE - PAGE_SIZE) 184#define VDSO_SYM(x) (VDSO_BASE + (unsigned long)(x))
185 185
186#define STACK_TOP VDSO_BASE 186#define STACK_TOP TASK_SIZE
187 187
188/* STACK_TOP_MAX is used temporarily in execve and should not check COMPAT. */ 188/* STACK_TOP_MAX is used temporarily in execve and should not check COMPAT. */
189#define STACK_TOP_MAX TASK_SIZE_MAX 189#define STACK_TOP_MAX TASK_SIZE_MAX
diff --git a/arch/tile/include/asm/sections.h b/arch/tile/include/asm/sections.h
index cc95276ef9c9..5d5d3b739a6b 100644
--- a/arch/tile/include/asm/sections.h
+++ b/arch/tile/include/asm/sections.h
@@ -25,6 +25,10 @@ extern char _sinitdata[], _einitdata[];
25/* Write-once data is writable only till the end of initialization. */ 25/* Write-once data is writable only till the end of initialization. */
26extern char __w1data_begin[], __w1data_end[]; 26extern char __w1data_begin[], __w1data_end[];
27 27
28extern char vdso_start[], vdso_end[];
29#ifdef CONFIG_COMPAT
30extern char vdso32_start[], vdso32_end[];
31#endif
28 32
29/* Not exactly sections, but PC comparison points in the code. */ 33/* Not exactly sections, but PC comparison points in the code. */
30extern char __rt_sigreturn[], __rt_sigreturn_end[]; 34extern char __rt_sigreturn[], __rt_sigreturn_end[];
diff --git a/arch/tile/include/asm/vdso.h b/arch/tile/include/asm/vdso.h
new file mode 100644
index 000000000000..9f6a78d665fa
--- /dev/null
+++ b/arch/tile/include/asm/vdso.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#ifndef __TILE_VDSO_H__
16#define __TILE_VDSO_H__
17
18#include <linux/types.h>
19
20/*
21 * Note about the vdso_data structure:
22 *
23 * NEVER USE THEM IN USERSPACE CODE DIRECTLY. The layout of the
24 * structure is supposed to be known only to the function in the vdso
25 * itself and may change without notice.
26 */
27
28struct vdso_data {
29 __u64 tz_update_count; /* Timezone atomicity ctr */
30 __u64 tb_update_count; /* Timebase atomicity ctr */
31 __u64 xtime_tod_stamp; /* TOD clock for xtime */
32 __u64 xtime_clock_sec; /* Kernel time second */
33 __u64 xtime_clock_nsec; /* Kernel time nanosecond */
34 __u64 wtom_clock_sec; /* Wall to monotonic clock second */
35 __u64 wtom_clock_nsec; /* Wall to monotonic clock nanosecond */
36 __u32 mult; /* Cycle to nanosecond multiplier */
37 __u32 shift; /* Cycle to nanosecond divisor (power of two) */
38 __u32 tz_minuteswest; /* Minutes west of Greenwich */
39 __u32 tz_dsttime; /* Type of dst correction */
40};
41
42extern struct vdso_data *vdso_data;
43
44/* __vdso_rt_sigreturn is defined with the addresses in the vdso page. */
45extern void __vdso_rt_sigreturn(void);
46
47extern int setup_vdso_pages(void);
48
49#endif /* __TILE_VDSO_H__ */
diff --git a/arch/tile/include/uapi/asm/auxvec.h b/arch/tile/include/uapi/asm/auxvec.h
index 1d393edb0641..c93e92709f14 100644
--- a/arch/tile/include/uapi/asm/auxvec.h
+++ b/arch/tile/include/uapi/asm/auxvec.h
@@ -15,6 +15,7 @@
15#ifndef _ASM_TILE_AUXVEC_H 15#ifndef _ASM_TILE_AUXVEC_H
16#define _ASM_TILE_AUXVEC_H 16#define _ASM_TILE_AUXVEC_H
17 17
18/* No extensions to auxvec */ 18/* The vDSO location. */
19#define AT_SYSINFO_EHDR 33
19 20
20#endif /* _ASM_TILE_AUXVEC_H */ 21#endif /* _ASM_TILE_AUXVEC_H */
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index 6846c4ef5bf1..5157d1c4b4ed 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := vmlinux.lds head_$(BITS).o
6obj-y := backtrace.o entry.o irq.o messaging.o \ 6obj-y := backtrace.o entry.o irq.o messaging.o \
7 pci-dma.o proc.o process.o ptrace.o reboot.o \ 7 pci-dma.o proc.o process.o ptrace.o reboot.o \
8 setup.o signal.o single_step.o stack.o sys.o \ 8 setup.o signal.o single_step.o stack.o sys.o \
9 sysfs.o time.o traps.o unaligned.o \ 9 sysfs.o time.o traps.o unaligned.o vdso.o \
10 intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o 10 intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o
11 11
12obj-$(CONFIG_HARDWALL) += hardwall.o 12obj-$(CONFIG_HARDWALL) += hardwall.o
@@ -21,3 +21,5 @@ else
21obj-$(CONFIG_PCI) += pci.o 21obj-$(CONFIG_PCI) += pci.o
22endif 22endif
23obj-$(CONFIG_TILE_USB) += usb.o 23obj-$(CONFIG_TILE_USB) += usb.o
24
25obj-y += vdso/
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index d0a052e725be..85e00b2f39bf 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -32,6 +32,7 @@
32#include <asm/ucontext.h> 32#include <asm/ucontext.h>
33#include <asm/sigframe.h> 33#include <asm/sigframe.h>
34#include <asm/syscalls.h> 34#include <asm/syscalls.h>
35#include <asm/vdso.h>
35#include <arch/interrupts.h> 36#include <arch/interrupts.h>
36 37
37struct compat_ucontext { 38struct compat_ucontext {
@@ -227,7 +228,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
227 if (err) 228 if (err)
228 goto give_sigsegv; 229 goto give_sigsegv;
229 230
230 restorer = VDSO_BASE; 231 restorer = VDSO_SYM(&__vdso_rt_sigreturn);
231 if (ka->sa.sa_flags & SA_RESTORER) 232 if (ka->sa.sa_flags & SA_RESTORER)
232 restorer = ptr_to_compat_reg(ka->sa.sa_restorer); 233 restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
233 234
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index f116cb0bce20..3d9175992a20 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -27,22 +27,6 @@ STD_ENTRY(current_text_addr)
27 { move r0, lr; jrp lr } 27 { move r0, lr; jrp lr }
28 STD_ENDPROC(current_text_addr) 28 STD_ENDPROC(current_text_addr)
29 29
30/*
31 * We don't run this function directly, but instead copy it to a page
32 * we map into every user process. See vdso_setup().
33 *
34 * Note that libc has a copy of this function that it uses to compare
35 * against the PC when a stack backtrace ends, so if this code is
36 * changed, the libc implementation(s) should also be updated.
37 */
38 .pushsection .data
39ENTRY(__rt_sigreturn)
40 moveli TREG_SYSCALL_NR_NAME,__NR_rt_sigreturn
41 swint1
42 ENDPROC(__rt_sigreturn)
43 ENTRY(__rt_sigreturn_end)
44 .popsection
45
46STD_ENTRY(dump_stack) 30STD_ENTRY(dump_stack)
47 { move r2, lr; lnk r1 } 31 { move r2, lr; lnk r1 }
48 { move r4, r52; addli r1, r1, dump_stack - . } 32 { move r4, r52; addli r1, r1, dump_stack - . }
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index 9531845bf661..2d1dbf38a9ab 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -33,6 +33,7 @@
33#include <asm/ucontext.h> 33#include <asm/ucontext.h>
34#include <asm/sigframe.h> 34#include <asm/sigframe.h>
35#include <asm/syscalls.h> 35#include <asm/syscalls.h>
36#include <asm/vdso.h>
36#include <arch/interrupts.h> 37#include <arch/interrupts.h>
37 38
38#define DEBUG_SIG 0 39#define DEBUG_SIG 0
@@ -190,7 +191,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
190 if (err) 191 if (err)
191 goto give_sigsegv; 192 goto give_sigsegv;
192 193
193 restorer = VDSO_BASE; 194 restorer = VDSO_SYM(&__vdso_rt_sigreturn);
194 if (ka->sa.sa_flags & SA_RESTORER) 195 if (ka->sa.sa_flags & SA_RESTORER)
195 restorer = (unsigned long) ka->sa.sa_restorer; 196 restorer = (unsigned long) ka->sa.sa_restorer;
196 197
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 176ffe48eee9..a9db923bb9eb 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -29,6 +29,7 @@
29#include <asm/switch_to.h> 29#include <asm/switch_to.h>
30#include <asm/sigframe.h> 30#include <asm/sigframe.h>
31#include <asm/stack.h> 31#include <asm/stack.h>
32#include <asm/vdso.h>
32#include <arch/abi.h> 33#include <arch/abi.h>
33#include <arch/interrupts.h> 34#include <arch/interrupts.h>
34 35
@@ -119,7 +120,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
119/* Is the pc pointing to a sigreturn trampoline? */ 120/* Is the pc pointing to a sigreturn trampoline? */
120static int is_sigreturn(unsigned long pc) 121static int is_sigreturn(unsigned long pc)
121{ 122{
122 return (pc == VDSO_BASE); 123 return current->mm && (pc == VDSO_SYM(&__vdso_rt_sigreturn));
123} 124}
124 125
125/* Return a pt_regs pointer for a valid signal handler frame */ 126/* Return a pt_regs pointer for a valid signal handler frame */
@@ -128,7 +129,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt,
128{ 129{
129 BacktraceIterator *b = &kbt->it; 130 BacktraceIterator *b = &kbt->it;
130 131
131 if (b->pc == VDSO_BASE && b->sp < PAGE_OFFSET && 132 if (is_sigreturn(b->pc) && b->sp < PAGE_OFFSET &&
132 b->sp % sizeof(long) == 0) { 133 b->sp % sizeof(long) == 0) {
133 int retval; 134 int retval;
134 pagefault_disable(); 135 pagefault_disable();
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index 5ac397ec6986..36dc1e1bc0a0 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -23,8 +23,10 @@
23#include <linux/smp.h> 23#include <linux/smp.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/timekeeper_internal.h>
26#include <asm/irq_regs.h> 27#include <asm/irq_regs.h>
27#include <asm/traps.h> 28#include <asm/traps.h>
29#include <asm/vdso.h>
28#include <hv/hypervisor.h> 30#include <hv/hypervisor.h>
29#include <arch/interrupts.h> 31#include <arch/interrupts.h>
30#include <arch/spr_def.h> 32#include <arch/spr_def.h>
@@ -110,7 +112,6 @@ void __init time_init(void)
110 setup_tile_timer(); 112 setup_tile_timer();
111} 113}
112 114
113
114/* 115/*
115 * Define the tile timer clock event device. The timer is driven by 116 * Define the tile timer clock event device. The timer is driven by
116 * the TILE_TIMER_CONTROL register, which consists of a 31-bit down 117 * the TILE_TIMER_CONTROL register, which consists of a 31-bit down
@@ -237,3 +238,37 @@ cycles_t ns2cycles(unsigned long nsecs)
237 struct clock_event_device *dev = &__raw_get_cpu_var(tile_timer); 238 struct clock_event_device *dev = &__raw_get_cpu_var(tile_timer);
238 return ((u64)nsecs * dev->mult) >> dev->shift; 239 return ((u64)nsecs * dev->mult) >> dev->shift;
239} 240}
241
242void update_vsyscall_tz(void)
243{
244 /* Userspace gettimeofday will spin while this value is odd. */
245 ++vdso_data->tz_update_count;
246 smp_wmb();
247 vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
248 vdso_data->tz_dsttime = sys_tz.tz_dsttime;
249 smp_wmb();
250 ++vdso_data->tz_update_count;
251}
252
253void update_vsyscall(struct timekeeper *tk)
254{
255 struct timespec wall_time = tk_xtime(tk);
256 struct timespec *wtm = &tk->wall_to_monotonic;
257 struct clocksource *clock = tk->clock;
258
259 if (clock != &cycle_counter_cs)
260 return;
261
262 /* Userspace gettimeofday will spin while this value is odd. */
263 ++vdso_data->tb_update_count;
264 smp_wmb();
265 vdso_data->xtime_tod_stamp = clock->cycle_last;
266 vdso_data->xtime_clock_sec = wall_time.tv_sec;
267 vdso_data->xtime_clock_nsec = wall_time.tv_nsec;
268 vdso_data->wtom_clock_sec = wtm->tv_sec;
269 vdso_data->wtom_clock_nsec = wtm->tv_nsec;
270 vdso_data->mult = clock->mult;
271 vdso_data->shift = clock->shift;
272 smp_wmb();
273 ++vdso_data->tb_update_count;
274}
diff --git a/arch/tile/kernel/vdso.c b/arch/tile/kernel/vdso.c
new file mode 100644
index 000000000000..1533af24106e
--- /dev/null
+++ b/arch/tile/kernel/vdso.c
@@ -0,0 +1,212 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/binfmts.h>
16#include <linux/compat.h>
17#include <linux/elf.h>
18#include <linux/mm.h>
19#include <linux/pagemap.h>
20
21#include <asm/vdso.h>
22#include <asm/mman.h>
23#include <asm/sections.h>
24
25#include <arch/sim.h>
26
27/* The alignment of the vDSO. */
28#define VDSO_ALIGNMENT PAGE_SIZE
29
30
31static unsigned int vdso_pages;
32static struct page **vdso_pagelist;
33
34#ifdef CONFIG_COMPAT
35static unsigned int vdso32_pages;
36static struct page **vdso32_pagelist;
37#endif
38static int vdso_ready;
39
40/*
41 * The vdso data page.
42 */
43static union {
44 struct vdso_data data;
45 u8 page[PAGE_SIZE];
46} vdso_data_store __page_aligned_data;
47
48struct vdso_data *vdso_data = &vdso_data_store.data;
49
50static unsigned int __read_mostly vdso_enabled = 1;
51
52static struct page **vdso_setup(void *vdso_kbase, unsigned int pages)
53{
54 int i;
55 struct page **pagelist;
56
57 pagelist = kzalloc(sizeof(struct page *) * (pages + 1), GFP_KERNEL);
58 BUG_ON(pagelist == NULL);
59 for (i = 0; i < pages - 1; i++) {
60 struct page *pg = virt_to_page(vdso_kbase + i*PAGE_SIZE);
61 ClearPageReserved(pg);
62 pagelist[i] = pg;
63 }
64 pagelist[pages - 1] = virt_to_page(vdso_data);
65 pagelist[pages] = NULL;
66
67 return pagelist;
68}
69
70static int __init vdso_init(void)
71{
72 int data_pages = sizeof(vdso_data_store) >> PAGE_SHIFT;
73
74 /*
75 * We can disable vDSO support generally, but we need to retain
76 * one page to support the two-bundle (16-byte) rt_sigreturn path.
77 */
78 if (!vdso_enabled) {
79 size_t offset = (unsigned long)&__vdso_rt_sigreturn;
80 static struct page *sigret_page;
81 sigret_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
82 BUG_ON(sigret_page == NULL);
83 vdso_pagelist = &sigret_page;
84 vdso_pages = 1;
85 BUG_ON(offset >= PAGE_SIZE);
86 memcpy(page_address(sigret_page) + offset,
87 vdso_start + offset, 16);
88#ifdef CONFIG_COMPAT
89 vdso32_pages = vdso_pages;
90 vdso32_pagelist = vdso_pagelist;
91#endif
92 vdso_ready = 1;
93 return 0;
94 }
95
96 vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
97 vdso_pages += data_pages;
98 vdso_pagelist = vdso_setup(vdso_start, vdso_pages);
99
100#ifdef CONFIG_COMPAT
101 vdso32_pages = (vdso32_end - vdso32_start) >> PAGE_SHIFT;
102 vdso32_pages += data_pages;
103 vdso32_pagelist = vdso_setup(vdso32_start, vdso32_pages);
104#endif
105
106 smp_wmb();
107 vdso_ready = 1;
108
109 return 0;
110}
111arch_initcall(vdso_init);
112
113const char *arch_vma_name(struct vm_area_struct *vma)
114{
115 if (vma->vm_mm && vma->vm_start == VDSO_BASE)
116 return "[vdso]";
117#ifndef __tilegx__
118 if (vma->vm_start == MEM_USER_INTRPT)
119 return "[intrpt]";
120#endif
121 return NULL;
122}
123
124struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
125{
126 return NULL;
127}
128
129int in_gate_area(struct mm_struct *mm, unsigned long address)
130{
131 return 0;
132}
133
134int in_gate_area_no_mm(unsigned long address)
135{
136 return 0;
137}
138
139int setup_vdso_pages(void)
140{
141 struct page **pagelist;
142 unsigned long pages;
143 struct mm_struct *mm = current->mm;
144 unsigned long vdso_base = 0;
145 int retval = 0;
146
147 if (!vdso_ready)
148 return 0;
149
150 mm->context.vdso_base = 0;
151
152 pagelist = vdso_pagelist;
153 pages = vdso_pages;
154#ifdef CONFIG_COMPAT
155 if (is_compat_task()) {
156 pagelist = vdso32_pagelist;
157 pages = vdso32_pages;
158 }
159#endif
160
161 /*
162 * vDSO has a problem and was disabled, just don't "enable" it for the
163 * process.
164 */
165 if (pages == 0)
166 return 0;
167
168 vdso_base = get_unmapped_area(NULL, vdso_base,
169 (pages << PAGE_SHIFT) +
170 ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
171 0, 0);
172 if (IS_ERR_VALUE(vdso_base)) {
173 retval = vdso_base;
174 return retval;
175 }
176
177 /* Add required alignment. */
178 vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
179
180 /*
181 * Put vDSO base into mm struct. We need to do this before calling
182 * install_special_mapping or the perf counter mmap tracking code
183 * will fail to recognise it as a vDSO (since arch_vma_name fails).
184 */
185 mm->context.vdso_base = vdso_base;
186
187 /*
188 * our vma flags don't have VM_WRITE so by default, the process isn't
189 * allowed to write those pages.
190 * gdb can break that with ptrace interface, and thus trigger COW on
191 * those pages but it's then your responsibility to never do that on
192 * the "data" page of the vDSO or you'll stop getting kernel updates
193 * and your nice userland gettimeofday will be totally dead.
194 * It's fine to use that for setting breakpoints in the vDSO code
195 * pages though
196 */
197 retval = install_special_mapping(mm, vdso_base,
198 pages << PAGE_SHIFT,
199 VM_READ|VM_EXEC |
200 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
201 pagelist);
202 if (retval)
203 mm->context.vdso_base = 0;
204
205 return retval;
206}
207
208static __init int vdso_func(char *s)
209{
210 return kstrtouint(s, 0, &vdso_enabled);
211}
212__setup("vdso=", vdso_func);
diff --git a/arch/tile/kernel/vdso/Makefile b/arch/tile/kernel/vdso/Makefile
new file mode 100644
index 000000000000..e2b7a2f4ee41
--- /dev/null
+++ b/arch/tile/kernel/vdso/Makefile
@@ -0,0 +1,118 @@
1# Symbols present in the vdso
2vdso-syms = rt_sigreturn gettimeofday
3
4# Files to link into the vdso
5obj-vdso = $(patsubst %, v%.o, $(vdso-syms))
6
7# Build rules
8targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
9obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
10
11# vdso32 is only for tilegx -m32 compat task.
12VDSO32-$(CONFIG_COMPAT) := y
13
14obj-y += vdso.o
15obj-$(VDSO32-y) += vdso32.o
16extra-y += vdso.lds
17CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
18
19# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
20CFLAGS_REMOVE_vdso.o = -pg
21CFLAGS_REMOVE_vdso32.o = -pg
22CFLAGS_REMOVE_vrt_sigreturn.o = -pg
23CFLAGS_REMOVE_vrt_sigreturn32.o = -pg
24CFLAGS_REMOVE_vgettimeofday.o = -pg
25CFLAGS_REMOVE_vgettimeofday32.o = -pg
26
27ifdef CONFIG_FEEDBACK_COLLECT
28# vDSO code runs in userspace, not collecting feedback data.
29CFLAGS_REMOVE_vdso.o = -ffeedback-generate
30CFLAGS_REMOVE_vdso32.o = -ffeedback-generate
31CFLAGS_REMOVE_vrt_sigreturn.o = -ffeedback-generate
32CFLAGS_REMOVE_vrt_sigreturn32.o = -ffeedback-generate
33CFLAGS_REMOVE_vgettimeofday.o = -ffeedback-generate
34CFLAGS_REMOVE_vgettimeofday32.o = -ffeedback-generate
35endif
36
37# Disable gcov profiling for VDSO code
38GCOV_PROFILE := n
39
40# Force dependency
41$(obj)/vdso.o: $(obj)/vdso.so
42
43# link rule for the .so file, .lds has to be first
44SYSCFLAGS_vdso.so.dbg = $(c_flags)
45$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
46 $(call if_changed,vdsold)
47
48
49# We also create a special relocatable object that should mirror the symbol
50# table and layout of the linked DSO. With ld -R we can then refer to
51# these symbols in the kernel code rather than hand-coded addresses.
52extra-y += vdso-syms.o
53$(obj)/built-in.o: $(obj)/vdso-syms.o
54$(obj)/built-in.o: ld_flags += -R $(obj)/vdso-syms.o
55
56SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
57 $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
58SYSCFLAGS_vdso_syms.o = -r
59$(obj)/vdso-syms.o: $(src)/vdso.lds $(obj)/vrt_sigreturn.o FORCE
60 $(call if_changed,vdsold)
61
62
63# strip rule for the .so file
64$(obj)/%.so: OBJCOPYFLAGS := -S
65$(obj)/%.so: $(obj)/%.so.dbg FORCE
66 $(call if_changed,objcopy)
67
68# actual build commands
69# The DSO images are built using a special linker script
70# Add -lgcc so tilepro gets static muldi3 and lshrdi3 definitions.
71# Make sure only to export the intended __vdso_xxx symbol offsets.
72quiet_cmd_vdsold = VDSOLD $@
73 cmd_vdsold = $(CC) $(KCFLAGS) -nostdlib $(SYSCFLAGS_$(@F)) \
74 -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp -lgcc && \
75 $(CROSS_COMPILE)objcopy \
76 $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@
77
78# install commands for the unstripped file
79quiet_cmd_vdso_install = INSTALL $@
80 cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
81
82vdso.so: $(obj)/vdso.so.dbg
83 @mkdir -p $(MODLIB)/vdso
84 $(call cmd,vdso_install)
85
86vdso32.so: $(obj)/vdso32.so.dbg
87 $(call cmd,vdso_install)
88
89vdso_install: vdso.so
90vdso32_install: vdso32.so
91
92
93KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
94KBUILD_AFLAGS_32 += -m32 -s
95KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
96KBUILD_CFLAGS_32 += -m32 -fPIC -shared
97
98obj-vdso32 = $(patsubst %, v%32.o, $(vdso-syms))
99obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
100
101targets += $(obj-vdso32) vdso32.so vdso32.so.dbg
102
103$(obj-vdso32:%=%): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
104$(obj-vdso32:%=%): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
105
106$(obj)/vgettimeofday32.o: $(obj)/vgettimeofday.c
107 $(call if_changed,cc_o_c)
108
109$(obj)/vrt_sigreturn32.o: $(obj)/vrt_sigreturn.S
110 $(call if_changed,as_o_S)
111
112# Force dependency
113$(obj)/vdso32.o: $(obj)/vdso32.so
114
115SYSCFLAGS_vdso32.so.dbg = -m32 -shared -s -Wl,-soname=linux-vdso32.so.1 \
116 $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
117$(obj)/vdso32.so.dbg: $(src)/vdso.lds $(obj-vdso32)
118 $(call if_changed,vdsold)
diff --git a/arch/tile/kernel/vdso/vdso.S b/arch/tile/kernel/vdso/vdso.S
new file mode 100644
index 000000000000..3467adb41630
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso.S
@@ -0,0 +1,28 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/init.h>
16#include <linux/linkage.h>
17#include <asm/page.h>
18
19 __PAGE_ALIGNED_DATA
20
21 .global vdso_start, vdso_end
22 .align PAGE_SIZE
23vdso_start:
24 .incbin "arch/tile/kernel/vdso/vdso.so"
25 .align PAGE_SIZE
26vdso_end:
27
28 .previous
diff --git a/arch/tile/kernel/vdso/vdso.lds.S b/arch/tile/kernel/vdso/vdso.lds.S
new file mode 100644
index 000000000000..041cd6c39c83
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso.lds.S
@@ -0,0 +1,87 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#define VDSO_VERSION_STRING LINUX_2.6
16
17
18OUTPUT_ARCH(tile)
19
20/* The ELF entry point can be used to set the AT_SYSINFO value. */
21ENTRY(__vdso_rt_sigreturn);
22
23
24SECTIONS
25{
26 . = SIZEOF_HEADERS;
27
28 .hash : { *(.hash) } :text
29 .gnu.hash : { *(.gnu.hash) }
30 .dynsym : { *(.dynsym) }
31 .dynstr : { *(.dynstr) }
32 .gnu.version : { *(.gnu.version) }
33 .gnu.version_d : { *(.gnu.version_d) }
34 .gnu.version_r : { *(.gnu.version_r) }
35
36 .note : { *(.note.*) } :text :note
37 .dynamic : { *(.dynamic) } :text :dynamic
38
39 .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
40 .eh_frame : { KEEP (*(.eh_frame)) } :text
41
42 .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
43
44 /*
45 * This linker script is used both with -r and with -shared.
46 * For the layouts to match, we need to skip more than enough
47 * space for the dynamic symbol table et al. If this amount
48 * is insufficient, ld -shared will barf. Just increase it here.
49 */
50 . = 0x1000;
51 .text : { *(.text .text.*) } :text
52
53 .data : {
54 *(.got.plt) *(.got)
55 *(.data .data.* .gnu.linkonce.d.*)
56 *(.dynbss)
57 *(.bss .bss.* .gnu.linkonce.b.*)
58 }
59}
60
61
62/*
63 * We must supply the ELF program headers explicitly to get just one
64 * PT_LOAD segment, and set the flags explicitly to make segments read-only.
65 */
66PHDRS
67{
68 text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
69 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
70 note PT_NOTE FLAGS(4); /* PF_R */
71 eh_frame_hdr PT_GNU_EH_FRAME;
72}
73
74
75/*
76 * This controls what userland symbols we export from the vDSO.
77 */
78VERSION
79{
80 VDSO_VERSION_STRING {
81 global:
82 __vdso_rt_sigreturn;
83 __vdso_gettimeofday;
84 gettimeofday;
85 local:*;
86 };
87}
diff --git a/arch/tile/kernel/vdso/vdso32.S b/arch/tile/kernel/vdso/vdso32.S
new file mode 100644
index 000000000000..1d1ac3257e11
--- /dev/null
+++ b/arch/tile/kernel/vdso/vdso32.S
@@ -0,0 +1,28 @@
1/*
2 * Copyright 2013 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/init.h>
16#include <linux/linkage.h>
17#include <asm/page.h>
18
19 __PAGE_ALIGNED_DATA
20
21 .global vdso32_start, vdso32_end
22 .align PAGE_SIZE
23vdso32_start:
24 .incbin "arch/tile/kernel/vdso/vdso32.so"
25 .align PAGE_SIZE
26vdso32_end:
27
28 .previous
diff --git a/arch/tile/kernel/vdso/vgettimeofday.c b/arch/tile/kernel/vdso/vgettimeofday.c
new file mode 100644
index 000000000000..51ec8e46f5f9
--- /dev/null
+++ b/arch/tile/kernel/vdso/vgettimeofday.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#define VDSO_BUILD /* avoid some shift warnings for -m32 in <asm/page.h> */
16#include <linux/time.h>
17#include <asm/timex.h>
18#include <asm/vdso.h>
19
20#if CHIP_HAS_SPLIT_CYCLE()
21static inline cycles_t get_cycles_inline(void)
22{
23 unsigned int high = __insn_mfspr(SPR_CYCLE_HIGH);
24 unsigned int low = __insn_mfspr(SPR_CYCLE_LOW);
25 unsigned int high2 = __insn_mfspr(SPR_CYCLE_HIGH);
26
27 while (unlikely(high != high2)) {
28 low = __insn_mfspr(SPR_CYCLE_LOW);
29 high = high2;
30 high2 = __insn_mfspr(SPR_CYCLE_HIGH);
31 }
32
33 return (((cycles_t)high) << 32) | low;
34}
35#define get_cycles get_cycles_inline
36#endif
37
38/*
39 * Find out the vDSO data page address in the process address space.
40 */
41inline unsigned long get_datapage(void)
42{
43 unsigned long ret;
44
45 /* vdso data page located in the 2nd vDSO page. */
46 asm volatile ("lnk %0" : "=r"(ret));
47 ret &= ~(PAGE_SIZE - 1);
48 ret += PAGE_SIZE;
49
50 return ret;
51}
52
53int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
54{
55 cycles_t cycles;
56 unsigned long count, sec, ns;
57 volatile struct vdso_data *vdso_data;
58
59 vdso_data = (struct vdso_data *)get_datapage();
60 /* The use of the timezone is obsolete, normally tz is NULL. */
61 if (unlikely(tz != NULL)) {
62 while (1) {
63 /* Spin until the update finish. */
64 count = vdso_data->tz_update_count;
65 if (count & 1)
66 continue;
67
68 tz->tz_minuteswest = vdso_data->tz_minuteswest;
69 tz->tz_dsttime = vdso_data->tz_dsttime;
70
71 /* Check whether updated, read again if so. */
72 if (count == vdso_data->tz_update_count)
73 break;
74 }
75 }
76
77 if (unlikely(tv == NULL))
78 return 0;
79
80 while (1) {
81 /* Spin until the update finish. */
82 count = vdso_data->tb_update_count;
83 if (count & 1)
84 continue;
85
86 cycles = (get_cycles() - vdso_data->xtime_tod_stamp);
87 ns = (cycles * vdso_data->mult) >> vdso_data->shift;
88 sec = vdso_data->xtime_clock_sec;
89 ns += vdso_data->xtime_clock_nsec;
90 if (ns >= NSEC_PER_SEC) {
91 ns -= NSEC_PER_SEC;
92 sec += 1;
93 }
94
95 /* Check whether updated, read again if so. */
96 if (count == vdso_data->tb_update_count)
97 break;
98 }
99
100 tv->tv_sec = sec;
101 tv->tv_usec = ns / 1000;
102
103 return 0;
104}
105
106int gettimeofday(struct timeval *tv, struct timezone *tz)
107 __attribute__((weak, alias("__vdso_gettimeofday")));
diff --git a/arch/tile/kernel/vdso/vrt_sigreturn.S b/arch/tile/kernel/vdso/vrt_sigreturn.S
new file mode 100644
index 000000000000..6326caf4a039
--- /dev/null
+++ b/arch/tile/kernel/vdso/vrt_sigreturn.S
@@ -0,0 +1,30 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/linkage.h>
16#include <arch/abi.h>
17#include <asm/unistd.h>
18
19/*
20 * Note that libc has a copy of this function that it uses to compare
21 * against the PC when a stack backtrace ends, so if this code is
22 * changed, the libc implementation(s) should also be updated.
23 */
24ENTRY(__vdso_rt_sigreturn)
25 moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn
26 swint1
27 /* We don't use ENDPROC to avoid tagging this symbol as FUNC,
28 * which confuses the perf tool.
29 */
30 END(__vdso_rt_sigreturn)
diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c
index 1691b81b2b0c..23f044e8a7ab 100644
--- a/arch/tile/mm/elf.c
+++ b/arch/tile/mm/elf.c
@@ -21,6 +21,7 @@
21#include <asm/pgtable.h> 21#include <asm/pgtable.h>
22#include <asm/pgalloc.h> 22#include <asm/pgalloc.h>
23#include <asm/sections.h> 23#include <asm/sections.h>
24#include <asm/vdso.h>
24#include <arch/sim.h> 25#include <arch/sim.h>
25 26
26/* Notify a running simulator, if any, that an exec just occurred. */ 27/* Notify a running simulator, if any, that an exec just occurred. */
@@ -102,37 +103,10 @@ static void sim_notify_interp(unsigned long load_addr)
102} 103}
103 104
104 105
105/* Kernel address of page used to map read-only kernel data into userspace. */
106static void *vdso_page;
107
108/* One-entry array used for install_special_mapping. */
109static struct page *vdso_pages[1];
110
111static int __init vdso_setup(void)
112{
113 vdso_page = (void *)get_zeroed_page(GFP_ATOMIC);
114 memcpy(vdso_page, __rt_sigreturn, __rt_sigreturn_end - __rt_sigreturn);
115 vdso_pages[0] = virt_to_page(vdso_page);
116 return 0;
117}
118device_initcall(vdso_setup);
119
120const char *arch_vma_name(struct vm_area_struct *vma)
121{
122 if (vma->vm_private_data == vdso_pages)
123 return "[vdso]";
124#ifndef __tilegx__
125 if (vma->vm_start == MEM_USER_INTRPT)
126 return "[intrpt]";
127#endif
128 return NULL;
129}
130
131int arch_setup_additional_pages(struct linux_binprm *bprm, 106int arch_setup_additional_pages(struct linux_binprm *bprm,
132 int executable_stack) 107 int executable_stack)
133{ 108{
134 struct mm_struct *mm = current->mm; 109 struct mm_struct *mm = current->mm;
135 unsigned long vdso_base;
136 int retval = 0; 110 int retval = 0;
137 111
138 down_write(&mm->mmap_sem); 112 down_write(&mm->mmap_sem);
@@ -145,14 +119,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
145 if (!notify_exec(mm)) 119 if (!notify_exec(mm))
146 sim_notify_exec(bprm->filename); 120 sim_notify_exec(bprm->filename);
147 121
148 /* 122 retval = setup_vdso_pages();
149 * MAYWRITE to allow gdb to COW and set breakpoints
150 */
151 vdso_base = VDSO_BASE;
152 retval = install_special_mapping(mm, vdso_base, PAGE_SIZE,
153 VM_READ|VM_EXEC|
154 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
155 vdso_pages);
156 123
157#ifndef __tilegx__ 124#ifndef __tilegx__
158 /* 125 /*