diff options
24 files changed, 1218 insertions, 1 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8116a3328a19..37bb37334dec 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -43,6 +43,9 @@ config GENERIC_HWEIGHT | |||
43 | config GENERIC_TIME | 43 | config GENERIC_TIME |
44 | def_bool y | 44 | def_bool y |
45 | 45 | ||
46 | config GENERIC_TIME_VSYSCALL | ||
47 | def_bool y | ||
48 | |||
46 | config GENERIC_CLOCKEVENTS | 49 | config GENERIC_CLOCKEVENTS |
47 | def_bool y | 50 | def_bool y |
48 | 51 | ||
diff --git a/arch/s390/include/asm/auxvec.h b/arch/s390/include/asm/auxvec.h index 0d340720fd99..a1f153e89133 100644 --- a/arch/s390/include/asm/auxvec.h +++ b/arch/s390/include/asm/auxvec.h | |||
@@ -1,4 +1,6 @@ | |||
1 | #ifndef __ASMS390_AUXVEC_H | 1 | #ifndef __ASMS390_AUXVEC_H |
2 | #define __ASMS390_AUXVEC_H | 2 | #define __ASMS390_AUXVEC_H |
3 | 3 | ||
4 | #define AT_SYSINFO_EHDR 33 | ||
5 | |||
4 | #endif | 6 | #endif |
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 261785ab5b22..d480f39d65e6 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h | |||
@@ -120,6 +120,10 @@ typedef s390_compat_regs compat_elf_gregset_t; | |||
120 | #include <asm/system.h> /* for save_access_regs */ | 120 | #include <asm/system.h> /* for save_access_regs */ |
121 | #include <asm/mmu_context.h> | 121 | #include <asm/mmu_context.h> |
122 | 122 | ||
123 | #include <asm/vdso.h> | ||
124 | |||
125 | extern unsigned int vdso_enabled; | ||
126 | |||
123 | /* | 127 | /* |
124 | * This is used to ensure we don't load something for the wrong architecture. | 128 | * This is used to ensure we don't load something for the wrong architecture. |
125 | */ | 129 | */ |
@@ -191,4 +195,16 @@ do { \ | |||
191 | current->mm->context.noexec == 0; \ | 195 | current->mm->context.noexec == 0; \ |
192 | }) | 196 | }) |
193 | 197 | ||
198 | #define ARCH_DLINFO \ | ||
199 | do { \ | ||
200 | if (vdso_enabled) \ | ||
201 | NEW_AUX_ENT(AT_SYSINFO_EHDR, \ | ||
202 | (unsigned long)current->mm->context.vdso_base); \ | ||
203 | } while (0) | ||
204 | |||
205 | struct linux_binprm; | ||
206 | |||
207 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 | ||
208 | int arch_setup_additional_pages(struct linux_binprm *, int); | ||
209 | |||
194 | #endif | 210 | #endif |
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index d2b4ff831477..3b59216e6284 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h | |||
@@ -6,6 +6,7 @@ typedef struct { | |||
6 | struct list_head pgtable_list; | 6 | struct list_head pgtable_list; |
7 | unsigned long asce_bits; | 7 | unsigned long asce_bits; |
8 | unsigned long asce_limit; | 8 | unsigned long asce_limit; |
9 | unsigned long vdso_base; | ||
9 | int noexec; | 10 | int noexec; |
10 | int has_pgste; /* The mmu context has extended page tables */ | 11 | int has_pgste; /* The mmu context has extended page tables */ |
11 | int alloc_pgste; /* cloned contexts will have extended page tables */ | 12 | int alloc_pgste; /* cloned contexts will have extended page tables */ |
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 991ba939408c..32e8f6aa4384 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
@@ -152,4 +152,6 @@ void arch_alloc_page(struct page *page, int order); | |||
152 | #include <asm-generic/memory_model.h> | 152 | #include <asm-generic/memory_model.h> |
153 | #include <asm-generic/page.h> | 153 | #include <asm-generic/page.h> |
154 | 154 | ||
155 | #define __HAVE_ARCH_GATE_AREA 1 | ||
156 | |||
155 | #endif /* _S390_PAGE_H */ | 157 | #endif /* _S390_PAGE_H */ |
diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h new file mode 100644 index 000000000000..a44f4fe16a35 --- /dev/null +++ b/arch/s390/include/asm/vdso.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef __S390_VDSO_H__ | ||
2 | #define __S390_VDSO_H__ | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | /* Default link addresses for the vDSOs */ | ||
7 | #define VDSO32_LBASE 0 | ||
8 | #define VDSO64_LBASE 0 | ||
9 | |||
10 | #define VDSO_VERSION_STRING LINUX_2.6.26 | ||
11 | |||
12 | #ifndef __ASSEMBLY__ | ||
13 | |||
14 | /* | ||
15 | * Note about this structure: | ||
16 | * | ||
17 | * NEVER USE THIS IN USERSPACE CODE DIRECTLY. The layout of this | ||
18 | * structure is supposed to be known only to the function in the vdso | ||
19 | * itself and may change without notice. | ||
20 | */ | ||
21 | |||
22 | struct vdso_data { | ||
23 | __u64 tb_update_count; /* Timebase atomicity ctr 0x00 */ | ||
24 | __u64 xtime_tod_stamp; /* TOD clock for xtime 0x08 */ | ||
25 | __u64 xtime_clock_sec; /* Kernel time 0x10 */ | ||
26 | __u64 xtime_clock_nsec; /* 0x18 */ | ||
27 | __u64 wtom_clock_sec; /* Wall to monotonic clock 0x20 */ | ||
28 | __u64 wtom_clock_nsec; /* 0x28 */ | ||
29 | __u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */ | ||
30 | __u32 tz_dsttime; /* Type of dst correction 0x34 */ | ||
31 | }; | ||
32 | |||
33 | extern struct vdso_data *vdso_data; | ||
34 | |||
35 | #endif /* __ASSEMBLY__ */ | ||
36 | |||
37 | #endif /* __KERNEL__ */ | ||
38 | |||
39 | #endif /* __S390_VDSO_H__ */ | ||
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 50f657e77344..235b9484a4dc 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -14,7 +14,8 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | |||
14 | 14 | ||
15 | obj-y := bitmap.o traps.o time.o process.o base.o early.o \ | 15 | obj-y := bitmap.o traps.o time.o process.o base.o early.o \ |
16 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 16 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
17 | s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o | 17 | s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ |
18 | vdso.o | ||
18 | 19 | ||
19 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 20 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
20 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 21 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) |
@@ -39,3 +40,7 @@ S390_KEXEC_OBJS := machine_kexec.o crash.o | |||
39 | S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) | 40 | S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) |
40 | obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) | 41 | obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) |
41 | 42 | ||
43 | # vdso | ||
44 | obj-$(CONFIG_64BIT) += vdso64/ | ||
45 | obj-$(CONFIG_32BIT) += vdso32/ | ||
46 | obj-$(CONFIG_COMPAT) += vdso32/ | ||
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 3d144e6020c6..e641f60bac99 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/kbuild.h> | 8 | #include <linux/kbuild.h> |
9 | #include <asm/vdso.h> | ||
9 | 10 | ||
10 | int main(void) | 11 | int main(void) |
11 | { | 12 | { |
@@ -38,5 +39,19 @@ int main(void) | |||
38 | DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); | 39 | DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); |
39 | DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs)); | 40 | DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs)); |
40 | DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1)); | 41 | DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1)); |
42 | BLANK(); | ||
43 | /* timeval/timezone offsets for use by vdso */ | ||
44 | DEFINE(__VDSO_UPD_COUNT, offsetof(struct vdso_data, tb_update_count)); | ||
45 | DEFINE(__VDSO_XTIME_STAMP, offsetof(struct vdso_data, xtime_tod_stamp)); | ||
46 | DEFINE(__VDSO_XTIME_SEC, offsetof(struct vdso_data, xtime_clock_sec)); | ||
47 | DEFINE(__VDSO_XTIME_NSEC, offsetof(struct vdso_data, xtime_clock_nsec)); | ||
48 | DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec)); | ||
49 | DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); | ||
50 | DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest)); | ||
51 | /* constants used by the vdso */ | ||
52 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | ||
53 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | ||
54 | DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); | ||
55 | |||
41 | return 0; | 56 | return 0; |
42 | } | 57 | } |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index eccefbbff887..b73bbf31f432 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/delay.h> | 36 | #include <asm/delay.h> |
37 | #include <asm/s390_ext.h> | 37 | #include <asm/s390_ext.h> |
38 | #include <asm/div64.h> | 38 | #include <asm/div64.h> |
39 | #include <asm/vdso.h> | ||
39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
40 | #include <asm/irq_regs.h> | 41 | #include <asm/irq_regs.h> |
41 | #include <asm/timer.h> | 42 | #include <asm/timer.h> |
@@ -223,6 +224,36 @@ static struct clocksource clocksource_tod = { | |||
223 | }; | 224 | }; |
224 | 225 | ||
225 | 226 | ||
227 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) | ||
228 | { | ||
229 | if (clock != &clocksource_tod) | ||
230 | return; | ||
231 | |||
232 | /* Make userspace gettimeofday spin until we're done. */ | ||
233 | ++vdso_data->tb_update_count; | ||
234 | smp_wmb(); | ||
235 | vdso_data->xtime_tod_stamp = clock->cycle_last; | ||
236 | vdso_data->xtime_clock_sec = xtime.tv_sec; | ||
237 | vdso_data->xtime_clock_nsec = xtime.tv_nsec; | ||
238 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | ||
239 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | ||
240 | smp_wmb(); | ||
241 | ++vdso_data->tb_update_count; | ||
242 | } | ||
243 | |||
244 | extern struct timezone sys_tz; | ||
245 | |||
246 | void update_vsyscall_tz(void) | ||
247 | { | ||
248 | /* Make userspace gettimeofday spin until we're done. */ | ||
249 | ++vdso_data->tb_update_count; | ||
250 | smp_wmb(); | ||
251 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | ||
252 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; | ||
253 | smp_wmb(); | ||
254 | ++vdso_data->tb_update_count; | ||
255 | } | ||
256 | |||
226 | /* | 257 | /* |
227 | * Initialize the TOD clock and the CPU timer of | 258 | * Initialize the TOD clock and the CPU timer of |
228 | * the boot cpu. | 259 | * the boot cpu. |
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c new file mode 100644 index 000000000000..10a6ccef4412 --- /dev/null +++ b/arch/s390/kernel/vdso.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * vdso setup for s390 | ||
3 | * | ||
4 | * Copyright IBM Corp. 2008 | ||
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License (version 2 only) | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/unistd.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/user.h> | ||
22 | #include <linux/elf.h> | ||
23 | #include <linux/security.h> | ||
24 | #include <linux/bootmem.h> | ||
25 | |||
26 | #include <asm/pgtable.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/mmu.h> | ||
30 | #include <asm/mmu_context.h> | ||
31 | #include <asm/sections.h> | ||
32 | #include <asm/vdso.h> | ||
33 | |||
34 | /* Max supported size for symbol names */ | ||
35 | #define MAX_SYMNAME 64 | ||
36 | |||
37 | #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) | ||
38 | extern char vdso32_start, vdso32_end; | ||
39 | static void *vdso32_kbase = &vdso32_start; | ||
40 | static unsigned int vdso32_pages; | ||
41 | static struct page **vdso32_pagelist; | ||
42 | #endif | ||
43 | |||
44 | #ifdef CONFIG_64BIT | ||
45 | extern char vdso64_start, vdso64_end; | ||
46 | static void *vdso64_kbase = &vdso64_start; | ||
47 | static unsigned int vdso64_pages; | ||
48 | static struct page **vdso64_pagelist; | ||
49 | #endif /* CONFIG_64BIT */ | ||
50 | |||
51 | /* | ||
52 | * Should the kernel map a VDSO page into processes and pass its | ||
53 | * address down to glibc upon exec()? | ||
54 | */ | ||
55 | unsigned int __read_mostly vdso_enabled = 1; | ||
56 | |||
57 | static int __init vdso_setup(char *s) | ||
58 | { | ||
59 | vdso_enabled = simple_strtoul(s, NULL, 0); | ||
60 | return 1; | ||
61 | } | ||
62 | __setup("vdso=", vdso_setup); | ||
63 | |||
64 | /* | ||
65 | * The vdso data page | ||
66 | */ | ||
67 | static union { | ||
68 | struct vdso_data data; | ||
69 | u8 page[PAGE_SIZE]; | ||
70 | } vdso_data_store __attribute__((__section__(".data.page_aligned"))); | ||
71 | struct vdso_data *vdso_data = &vdso_data_store.data; | ||
72 | |||
73 | /* | ||
74 | * This is called from binfmt_elf, we create the special vma for the | ||
75 | * vDSO and insert it into the mm struct tree | ||
76 | */ | ||
77 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | ||
78 | { | ||
79 | struct mm_struct *mm = current->mm; | ||
80 | struct page **vdso_pagelist; | ||
81 | unsigned long vdso_pages; | ||
82 | unsigned long vdso_base; | ||
83 | int rc; | ||
84 | |||
85 | if (!vdso_enabled) | ||
86 | return 0; | ||
87 | /* | ||
88 | * Only map the vdso for dynamically linked elf binaries. | ||
89 | */ | ||
90 | if (!uses_interp) | ||
91 | return 0; | ||
92 | |||
93 | vdso_base = mm->mmap_base; | ||
94 | #ifdef CONFIG_64BIT | ||
95 | vdso_pagelist = vdso64_pagelist; | ||
96 | vdso_pages = vdso64_pages; | ||
97 | #ifdef CONFIG_COMPAT | ||
98 | if (test_thread_flag(TIF_31BIT)) { | ||
99 | vdso_pagelist = vdso32_pagelist; | ||
100 | vdso_pages = vdso32_pages; | ||
101 | } | ||
102 | #endif | ||
103 | #else | ||
104 | vdso_pagelist = vdso32_pagelist; | ||
105 | vdso_pages = vdso32_pages; | ||
106 | #endif | ||
107 | |||
108 | /* | ||
109 | * vDSO has a problem and was disabled, just don't "enable" it for | ||
110 | * the process | ||
111 | */ | ||
112 | if (vdso_pages == 0) | ||
113 | return 0; | ||
114 | |||
115 | current->mm->context.vdso_base = 0; | ||
116 | |||
117 | /* | ||
118 | * pick a base address for the vDSO in process space. We try to put | ||
119 | * it at vdso_base which is the "natural" base for it, but we might | ||
120 | * fail and end up putting it elsewhere. | ||
121 | */ | ||
122 | down_write(&mm->mmap_sem); | ||
123 | vdso_base = get_unmapped_area(NULL, vdso_base, | ||
124 | vdso_pages << PAGE_SHIFT, 0, 0); | ||
125 | if (IS_ERR_VALUE(vdso_base)) { | ||
126 | rc = vdso_base; | ||
127 | goto out_up; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * our vma flags don't have VM_WRITE so by default, the process | ||
132 | * isn't allowed to write those pages. | ||
133 | * gdb can break that with ptrace interface, and thus trigger COW | ||
134 | * on those pages but it's then your responsibility to never do that | ||
135 | * on the "data" page of the vDSO or you'll stop getting kernel | ||
136 | * updates and your nice userland gettimeofday will be totally dead. | ||
137 | * It's fine to use that for setting breakpoints in the vDSO code | ||
138 | * pages though | ||
139 | * | ||
140 | * Make sure the vDSO gets into every core dump. | ||
141 | * Dumping its contents makes post-mortem fully interpretable later | ||
142 | * without matching up the same kernel and hardware config to see | ||
143 | * what PC values meant. | ||
144 | */ | ||
145 | rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT, | ||
146 | VM_READ|VM_EXEC| | ||
147 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| | ||
148 | VM_ALWAYSDUMP, | ||
149 | vdso_pagelist); | ||
150 | if (rc) | ||
151 | goto out_up; | ||
152 | |||
153 | /* Put vDSO base into mm struct */ | ||
154 | current->mm->context.vdso_base = vdso_base; | ||
155 | |||
156 | up_write(&mm->mmap_sem); | ||
157 | return 0; | ||
158 | |||
159 | out_up: | ||
160 | up_write(&mm->mmap_sem); | ||
161 | return rc; | ||
162 | } | ||
163 | |||
164 | const char *arch_vma_name(struct vm_area_struct *vma) | ||
165 | { | ||
166 | if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base) | ||
167 | return "[vdso]"; | ||
168 | return NULL; | ||
169 | } | ||
170 | |||
171 | static int __init vdso_init(void) | ||
172 | { | ||
173 | int i; | ||
174 | |||
175 | #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) | ||
176 | /* Calculate the size of the 32 bit vDSO */ | ||
177 | vdso32_pages = ((&vdso32_end - &vdso32_start | ||
178 | + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; | ||
179 | |||
180 | /* Make sure pages are in the correct state */ | ||
181 | vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 1), | ||
182 | GFP_KERNEL); | ||
183 | BUG_ON(vdso32_pagelist == NULL); | ||
184 | for (i = 0; i < vdso32_pages - 1; i++) { | ||
185 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
186 | ClearPageReserved(pg); | ||
187 | get_page(pg); | ||
188 | vdso32_pagelist[i] = pg; | ||
189 | } | ||
190 | vdso32_pagelist[vdso32_pages - 1] = virt_to_page(vdso_data); | ||
191 | vdso32_pagelist[vdso32_pages] = NULL; | ||
192 | #endif | ||
193 | |||
194 | #ifdef CONFIG_64BIT | ||
195 | /* Calculate the size of the 64 bit vDSO */ | ||
196 | vdso64_pages = ((&vdso64_end - &vdso64_start | ||
197 | + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; | ||
198 | |||
199 | /* Make sure pages are in the correct state */ | ||
200 | vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 1), | ||
201 | GFP_KERNEL); | ||
202 | BUG_ON(vdso64_pagelist == NULL); | ||
203 | for (i = 0; i < vdso64_pages - 1; i++) { | ||
204 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
205 | ClearPageReserved(pg); | ||
206 | get_page(pg); | ||
207 | vdso64_pagelist[i] = pg; | ||
208 | } | ||
209 | vdso64_pagelist[vdso64_pages - 1] = virt_to_page(vdso_data); | ||
210 | vdso64_pagelist[vdso64_pages] = NULL; | ||
211 | #endif /* CONFIG_64BIT */ | ||
212 | |||
213 | get_page(virt_to_page(vdso_data)); | ||
214 | |||
215 | smp_wmb(); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | arch_initcall(vdso_init); | ||
220 | |||
221 | int in_gate_area_no_task(unsigned long addr) | ||
222 | { | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | int in_gate_area(struct task_struct *task, unsigned long addr) | ||
227 | { | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | ||
232 | { | ||
233 | return NULL; | ||
234 | } | ||
diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile new file mode 100644 index 000000000000..ca78ad60ba24 --- /dev/null +++ b/arch/s390/kernel/vdso32/Makefile | |||
@@ -0,0 +1,55 @@ | |||
1 | # List of files in the vdso, has to be asm only for now | ||
2 | |||
3 | obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o | ||
4 | |||
5 | # Build rules | ||
6 | |||
7 | targets := $(obj-vdso32) vdso32.so vdso32.so.dbg | ||
8 | obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) | ||
9 | |||
10 | KBUILD_AFLAGS_31 := $(filter-out -m64,$(KBUILD_AFLAGS)) | ||
11 | KBUILD_AFLAGS_31 += -m31 -s | ||
12 | |||
13 | KBUILD_CFLAGS_31 := $(filter-out -m64,$(KBUILD_CFLAGS)) | ||
14 | KBUILD_CFLAGS_31 += -m31 -fPIC -shared -fno-common -fno-builtin | ||
15 | KBUILD_CFLAGS_31 += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ | ||
16 | $(call ld-option, -Wl$(comma)--hash-style=sysv) | ||
17 | |||
18 | $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_31) | ||
19 | $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_31) | ||
20 | |||
21 | obj-y += vdso32_wrapper.o | ||
22 | extra-y += vdso32.lds | ||
23 | CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) | ||
24 | |||
25 | # Force dependency (incbin is bad) | ||
26 | $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so | ||
27 | |||
28 | # link rule for the .so file, .lds has to be first | ||
29 | $(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) | ||
30 | $(call if_changed,vdso32ld) | ||
31 | |||
32 | # strip rule for the .so file | ||
33 | $(obj)/%.so: OBJCOPYFLAGS := -S | ||
34 | $(obj)/%.so: $(obj)/%.so.dbg FORCE | ||
35 | $(call if_changed,objcopy) | ||
36 | |||
37 | # assembly rules for the .S files | ||
38 | $(obj-vdso32): %.o: %.S | ||
39 | $(call if_changed_dep,vdso32as) | ||
40 | |||
41 | # actual build commands | ||
42 | quiet_cmd_vdso32ld = VDSO32L $@ | ||
43 | cmd_vdso32ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ | ||
44 | quiet_cmd_vdso32as = VDSO32A $@ | ||
45 | cmd_vdso32as = $(CC) $(a_flags) -c -o $@ $< | ||
46 | |||
47 | # install commands for the unstripped file | ||
48 | quiet_cmd_vdso_install = INSTALL $@ | ||
49 | cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ | ||
50 | |||
51 | vdso32.so: $(obj)/vdso32.so.dbg | ||
52 | @mkdir -p $(MODLIB)/vdso | ||
53 | $(call cmd,vdso_install) | ||
54 | |||
55 | vdso_install: vdso32.so | ||
diff --git a/arch/s390/kernel/vdso32/clock_getres.S b/arch/s390/kernel/vdso32/clock_getres.S new file mode 100644 index 000000000000..9532c4e6a9d2 --- /dev/null +++ b/arch/s390/kernel/vdso32/clock_getres.S | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Userland implementation of clock_getres() for 32 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | .text | ||
17 | .align 4 | ||
18 | .globl __kernel_clock_getres | ||
19 | .type __kernel_clock_getres,@function | ||
20 | __kernel_clock_getres: | ||
21 | .cfi_startproc | ||
22 | chi %r2,CLOCK_REALTIME | ||
23 | je 0f | ||
24 | chi %r2,CLOCK_MONOTONIC | ||
25 | jne 3f | ||
26 | 0: ltr %r3,%r3 | ||
27 | jz 2f /* res == NULL */ | ||
28 | basr %r1,0 | ||
29 | 1: l %r0,4f-1b(%r1) | ||
30 | xc 0(4,%r3),0(%r3) /* set tp->tv_sec to zero */ | ||
31 | st %r0,4(%r3) /* store tp->tv_usec */ | ||
32 | 2: lhi %r2,0 | ||
33 | br %r14 | ||
34 | 3: lhi %r1,__NR_clock_getres /* fallback to svc */ | ||
35 | svc 0 | ||
36 | br %r14 | ||
37 | 4: .long CLOCK_REALTIME_RES | ||
38 | .cfi_endproc | ||
39 | .size __kernel_clock_getres,.-__kernel_clock_getres | ||
diff --git a/arch/s390/kernel/vdso32/clock_gettime.S b/arch/s390/kernel/vdso32/clock_gettime.S new file mode 100644 index 000000000000..4a98909a8310 --- /dev/null +++ b/arch/s390/kernel/vdso32/clock_gettime.S | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Userland implementation of clock_gettime() for 32 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | .text | ||
17 | .align 4 | ||
18 | .globl __kernel_clock_gettime | ||
19 | .type __kernel_clock_gettime,@function | ||
20 | __kernel_clock_gettime: | ||
21 | .cfi_startproc | ||
22 | basr %r5,0 | ||
23 | 0: al %r5,21f-0b(%r5) /* get &_vdso_data */ | ||
24 | chi %r2,CLOCK_REALTIME | ||
25 | je 10f | ||
26 | chi %r2,CLOCK_MONOTONIC | ||
27 | jne 19f | ||
28 | |||
29 | /* CLOCK_MONOTONIC */ | ||
30 | ltr %r3,%r3 | ||
31 | jz 9f /* tp == NULL */ | ||
32 | 1: l %r4,__VDSO_UPD_COUNT+4(%r5) /* load update counter */ | ||
33 | tml %r4,0x0001 /* pending update ? loop */ | ||
34 | jnz 1b | ||
35 | stck 24(%r15) /* Store TOD clock */ | ||
36 | lm %r0,%r1,24(%r15) | ||
37 | s %r0,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
38 | sl %r1,__VDSO_XTIME_STAMP+4(%r5) | ||
39 | brc 3,2f | ||
40 | ahi %r0,-1 | ||
41 | 2: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ | ||
42 | lr %r2,%r0 | ||
43 | lhi %r0,1000 | ||
44 | ltr %r1,%r1 | ||
45 | mr %r0,%r0 | ||
46 | jnm 3f | ||
47 | ahi %r0,1000 | ||
48 | 3: alr %r0,%r2 | ||
49 | srdl %r0,12 | ||
50 | al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ | ||
51 | al %r1,__VDSO_XTIME_NSEC+4(%r5) | ||
52 | brc 12,4f | ||
53 | ahi %r0,1 | ||
54 | 4: l %r2,__VDSO_XTIME_SEC+4(%r5) | ||
55 | al %r0,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */ | ||
56 | al %r1,__VDSO_WTOM_NSEC+4(%r5) | ||
57 | brc 12,5f | ||
58 | ahi %r0,1 | ||
59 | 5: al %r2,__VDSO_WTOM_SEC+4(%r5) | ||
60 | cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */ | ||
61 | jne 1b | ||
62 | basr %r5,0 | ||
63 | 6: ltr %r0,%r0 | ||
64 | jnz 7f | ||
65 | cl %r1,20f-6b(%r5) | ||
66 | jl 8f | ||
67 | 7: ahi %r2,1 | ||
68 | sl %r1,20f-6b(%r5) | ||
69 | brc 3,6b | ||
70 | ahi %r0,-1 | ||
71 | j 6b | ||
72 | 8: st %r2,0(%r3) /* store tp->tv_sec */ | ||
73 | st %r1,4(%r3) /* store tp->tv_nsec */ | ||
74 | 9: lhi %r2,0 | ||
75 | br %r14 | ||
76 | |||
77 | /* CLOCK_REALTIME */ | ||
78 | 10: ltr %r3,%r3 /* tp == NULL */ | ||
79 | jz 18f | ||
80 | 11: l %r4,__VDSO_UPD_COUNT+4(%r5) /* load update counter */ | ||
81 | tml %r4,0x0001 /* pending update ? loop */ | ||
82 | jnz 11b | ||
83 | stck 24(%r15) /* Store TOD clock */ | ||
84 | lm %r0,%r1,24(%r15) | ||
85 | s %r0,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
86 | sl %r1,__VDSO_XTIME_STAMP+4(%r5) | ||
87 | brc 3,12f | ||
88 | ahi %r0,-1 | ||
89 | 12: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ | ||
90 | lr %r2,%r0 | ||
91 | lhi %r0,1000 | ||
92 | ltr %r1,%r1 | ||
93 | mr %r0,%r0 | ||
94 | jnm 13f | ||
95 | ahi %r0,1000 | ||
96 | 13: alr %r0,%r2 | ||
97 | srdl %r0,12 | ||
98 | al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ | ||
99 | al %r1,__VDSO_XTIME_NSEC+4(%r5) | ||
100 | brc 12,14f | ||
101 | ahi %r0,1 | ||
102 | 14: l %r2,__VDSO_XTIME_SEC+4(%r5) | ||
103 | cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */ | ||
104 | jne 11b | ||
105 | basr %r5,0 | ||
106 | 15: ltr %r0,%r0 | ||
107 | jnz 16f | ||
108 | cl %r1,20f-15b(%r5) | ||
109 | jl 17f | ||
110 | 16: ahi %r2,1 | ||
111 | sl %r1,20f-15b(%r5) | ||
112 | brc 3,15b | ||
113 | ahi %r0,-1 | ||
114 | j 15b | ||
115 | 17: st %r2,0(%r3) /* store tp->tv_sec */ | ||
116 | st %r1,4(%r3) /* store tp->tv_nsec */ | ||
117 | 18: lhi %r2,0 | ||
118 | br %r14 | ||
119 | |||
120 | /* Fallback to system call */ | ||
121 | 19: lhi %r1,__NR_clock_gettime | ||
122 | svc 0 | ||
123 | br %r14 | ||
124 | |||
125 | 20: .long 1000000000 | ||
126 | 21: .long _vdso_data - 0b | ||
127 | .cfi_endproc | ||
128 | .size __kernel_clock_gettime,.-__kernel_clock_gettime | ||
diff --git a/arch/s390/kernel/vdso32/gettimeofday.S b/arch/s390/kernel/vdso32/gettimeofday.S new file mode 100644 index 000000000000..c32f29c3d70c --- /dev/null +++ b/arch/s390/kernel/vdso32/gettimeofday.S | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Userland implementation of gettimeofday() for 32 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | #include <asm/vdso.h> | ||
17 | #include <asm/asm-offsets.h> | ||
18 | #include <asm/unistd.h> | ||
19 | |||
20 | .text | ||
21 | .align 4 | ||
22 | .globl __kernel_gettimeofday | ||
23 | .type __kernel_gettimeofday,@function | ||
24 | __kernel_gettimeofday: | ||
25 | .cfi_startproc | ||
26 | basr %r5,0 | ||
27 | 0: al %r5,13f-0b(%r5) /* get &_vdso_data */ | ||
28 | 1: ltr %r3,%r3 /* check if tz is NULL */ | ||
29 | je 2f | ||
30 | mvc 0(8,%r3),__VDSO_TIMEZONE(%r5) | ||
31 | 2: ltr %r2,%r2 /* check if tv is NULL */ | ||
32 | je 10f | ||
33 | l %r4,__VDSO_UPD_COUNT+4(%r5) /* load update counter */ | ||
34 | tml %r4,0x0001 /* pending update ? loop */ | ||
35 | jnz 1b | ||
36 | stck 24(%r15) /* Store TOD clock */ | ||
37 | lm %r0,%r1,24(%r15) | ||
38 | s %r0,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
39 | sl %r1,__VDSO_XTIME_STAMP+4(%r5) | ||
40 | brc 3,3f | ||
41 | ahi %r0,-1 | ||
42 | 3: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ | ||
43 | st %r0,24(%r15) | ||
44 | lhi %r0,1000 | ||
45 | ltr %r1,%r1 | ||
46 | mr %r0,%r0 | ||
47 | jnm 4f | ||
48 | ahi %r0,1000 | ||
49 | 4: al %r0,24(%r15) | ||
50 | srdl %r0,12 | ||
51 | al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ | ||
52 | al %r1,__VDSO_XTIME_NSEC+4(%r5) | ||
53 | brc 12,5f | ||
54 | ahi %r0,1 | ||
55 | 5: mvc 24(4,%r15),__VDSO_XTIME_SEC+4(%r5) | ||
56 | cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */ | ||
57 | jne 1b | ||
58 | l %r4,24(%r15) /* get tv_sec from stack */ | ||
59 | basr %r5,0 | ||
60 | 6: ltr %r0,%r0 | ||
61 | jnz 7f | ||
62 | cl %r1,11f-6b(%r5) | ||
63 | jl 8f | ||
64 | 7: ahi %r4,1 | ||
65 | sl %r1,11f-6b(%r5) | ||
66 | brc 3,6b | ||
67 | ahi %r0,-1 | ||
68 | j 6b | ||
69 | 8: st %r4,0(%r2) /* store tv->tv_sec */ | ||
70 | ltr %r1,%r1 | ||
71 | m %r0,12f-6b(%r5) | ||
72 | jnm 9f | ||
73 | al %r0,12f-6b(%r5) | ||
74 | 9: srl %r0,6 | ||
75 | st %r0,4(%r2) /* store tv->tv_usec */ | ||
76 | 10: slr %r2,%r2 | ||
77 | br %r14 | ||
78 | 11: .long 1000000000 | ||
79 | 12: .long 274877907 | ||
80 | 13: .long _vdso_data - 0b | ||
81 | .cfi_endproc | ||
82 | .size __kernel_gettimeofday,.-__kernel_gettimeofday | ||
diff --git a/arch/s390/kernel/vdso32/note.S b/arch/s390/kernel/vdso32/note.S new file mode 100644 index 000000000000..79a071e4357e --- /dev/null +++ b/arch/s390/kernel/vdso32/note.S | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. | ||
3 | * Here we can supply some information useful to userland. | ||
4 | */ | ||
5 | |||
6 | #include <linux/uts.h> | ||
7 | #include <linux/version.h> | ||
8 | #include <linux/elfnote.h> | ||
9 | |||
10 | ELFNOTE_START(Linux, 0, "a") | ||
11 | .long LINUX_VERSION_CODE | ||
12 | ELFNOTE_END | ||
diff --git a/arch/s390/kernel/vdso32/vdso32.lds.S b/arch/s390/kernel/vdso32/vdso32.lds.S new file mode 100644 index 000000000000..a8c379fa1247 --- /dev/null +++ b/arch/s390/kernel/vdso32/vdso32.lds.S | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * This is the infamous ld script for the 32 bits vdso | ||
3 | * library | ||
4 | */ | ||
5 | #include <asm/vdso.h> | ||
6 | |||
7 | OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") | ||
8 | OUTPUT_ARCH(s390:31-bit) | ||
9 | ENTRY(_start) | ||
10 | |||
11 | SECTIONS | ||
12 | { | ||
13 | . = VDSO32_LBASE + SIZEOF_HEADERS; | ||
14 | |||
15 | .hash : { *(.hash) } :text | ||
16 | .gnu.hash : { *(.gnu.hash) } | ||
17 | .dynsym : { *(.dynsym) } | ||
18 | .dynstr : { *(.dynstr) } | ||
19 | .gnu.version : { *(.gnu.version) } | ||
20 | .gnu.version_d : { *(.gnu.version_d) } | ||
21 | .gnu.version_r : { *(.gnu.version_r) } | ||
22 | |||
23 | .note : { *(.note.*) } :text :note | ||
24 | |||
25 | . = ALIGN(16); | ||
26 | .text : { | ||
27 | *(.text .stub .text.* .gnu.linkonce.t.*) | ||
28 | } :text | ||
29 | PROVIDE(__etext = .); | ||
30 | PROVIDE(_etext = .); | ||
31 | PROVIDE(etext = .); | ||
32 | |||
33 | /* | ||
34 | * Other stuff is appended to the text segment: | ||
35 | */ | ||
36 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | ||
37 | .rodata1 : { *(.rodata1) } | ||
38 | |||
39 | .dynamic : { *(.dynamic) } :text :dynamic | ||
40 | |||
41 | .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
42 | .eh_frame : { KEEP (*(.eh_frame)) } :text | ||
43 | .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } | ||
44 | |||
45 | .rela.dyn ALIGN(8) : { *(.rela.dyn) } | ||
46 | .got ALIGN(8) : { *(.got .toc) } | ||
47 | |||
48 | _end = .; | ||
49 | PROVIDE(end = .); | ||
50 | |||
51 | /* | ||
52 | * Stabs debugging sections are here too. | ||
53 | */ | ||
54 | .stab 0 : { *(.stab) } | ||
55 | .stabstr 0 : { *(.stabstr) } | ||
56 | .stab.excl 0 : { *(.stab.excl) } | ||
57 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
58 | .stab.index 0 : { *(.stab.index) } | ||
59 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
60 | .comment 0 : { *(.comment) } | ||
61 | |||
62 | /* | ||
63 | * DWARF debug sections. | ||
64 | * Symbols in the DWARF debugging sections are relative to the | ||
65 | * beginning of the section so we begin them at 0. | ||
66 | */ | ||
67 | /* DWARF 1 */ | ||
68 | .debug 0 : { *(.debug) } | ||
69 | .line 0 : { *(.line) } | ||
70 | /* GNU DWARF 1 extensions */ | ||
71 | .debug_srcinfo 0 : { *(.debug_srcinfo) } | ||
72 | .debug_sfnames 0 : { *(.debug_sfnames) } | ||
73 | /* DWARF 1.1 and DWARF 2 */ | ||
74 | .debug_aranges 0 : { *(.debug_aranges) } | ||
75 | .debug_pubnames 0 : { *(.debug_pubnames) } | ||
76 | /* DWARF 2 */ | ||
77 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } | ||
78 | .debug_abbrev 0 : { *(.debug_abbrev) } | ||
79 | .debug_line 0 : { *(.debug_line) } | ||
80 | .debug_frame 0 : { *(.debug_frame) } | ||
81 | .debug_str 0 : { *(.debug_str) } | ||
82 | .debug_loc 0 : { *(.debug_loc) } | ||
83 | .debug_macinfo 0 : { *(.debug_macinfo) } | ||
84 | /* SGI/MIPS DWARF 2 extensions */ | ||
85 | .debug_weaknames 0 : { *(.debug_weaknames) } | ||
86 | .debug_funcnames 0 : { *(.debug_funcnames) } | ||
87 | .debug_typenames 0 : { *(.debug_typenames) } | ||
88 | .debug_varnames 0 : { *(.debug_varnames) } | ||
89 | /* DWARF 3 */ | ||
90 | .debug_pubtypes 0 : { *(.debug_pubtypes) } | ||
91 | .debug_ranges 0 : { *(.debug_ranges) } | ||
92 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } | ||
93 | |||
94 | . = ALIGN(4096); | ||
95 | PROVIDE(_vdso_data = .); | ||
96 | |||
97 | /DISCARD/ : { | ||
98 | *(.note.GNU-stack) | ||
99 | *(.branch_lt) | ||
100 | *(.data .data.* .gnu.linkonce.d.* .sdata*) | ||
101 | *(.bss .sbss .dynbss .dynsbss) | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Very old versions of ld do not recognize this name token; use the constant. | ||
107 | */ | ||
108 | #define PT_GNU_EH_FRAME 0x6474e550 | ||
109 | |||
110 | /* | ||
111 | * We must supply the ELF program headers explicitly to get just one | ||
112 | * PT_LOAD segment, and set the flags explicitly to make segments read-only. | ||
113 | */ | ||
114 | PHDRS | ||
115 | { | ||
116 | text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ | ||
117 | dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
118 | note PT_NOTE FLAGS(4); /* PF_R */ | ||
119 | eh_frame_hdr PT_GNU_EH_FRAME; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * This controls what symbols we export from the DSO. | ||
124 | */ | ||
125 | VERSION | ||
126 | { | ||
127 | VDSO_VERSION_STRING { | ||
128 | global: | ||
129 | /* | ||
130 | * Has to be there for the kernel to find | ||
131 | */ | ||
132 | __kernel_gettimeofday; | ||
133 | __kernel_clock_gettime; | ||
134 | __kernel_clock_getres; | ||
135 | |||
136 | local: *; | ||
137 | }; | ||
138 | } | ||
diff --git a/arch/s390/kernel/vdso32/vdso32_wrapper.S b/arch/s390/kernel/vdso32/vdso32_wrapper.S new file mode 100644 index 000000000000..61639a89e70b --- /dev/null +++ b/arch/s390/kernel/vdso32/vdso32_wrapper.S | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <asm/page.h> | ||
3 | |||
4 | .section ".data.page_aligned" | ||
5 | |||
6 | .globl vdso32_start, vdso32_end | ||
7 | .balign PAGE_SIZE | ||
8 | vdso32_start: | ||
9 | .incbin "arch/s390/kernel/vdso32/vdso32.so" | ||
10 | .balign PAGE_SIZE | ||
11 | vdso32_end: | ||
12 | |||
13 | .previous | ||
diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile new file mode 100644 index 000000000000..6fc8e829258c --- /dev/null +++ b/arch/s390/kernel/vdso64/Makefile | |||
@@ -0,0 +1,55 @@ | |||
1 | # List of files in the vdso, has to be asm only for now | ||
2 | |||
3 | obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o | ||
4 | |||
5 | # Build rules | ||
6 | |||
7 | targets := $(obj-vdso64) vdso64.so vdso64.so.dbg | ||
8 | obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) | ||
9 | |||
10 | KBUILD_AFLAGS_64 := $(filter-out -m64,$(KBUILD_AFLAGS)) | ||
11 | KBUILD_AFLAGS_64 += -m64 -s | ||
12 | |||
13 | KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS)) | ||
14 | KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin | ||
15 | KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ | ||
16 | $(call ld-option, -Wl$(comma)--hash-style=sysv) | ||
17 | |||
18 | $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64) | ||
19 | $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64) | ||
20 | |||
21 | obj-y += vdso64_wrapper.o | ||
22 | extra-y += vdso64.lds | ||
23 | CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) | ||
24 | |||
25 | # Force dependency (incbin is bad) | ||
26 | $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so | ||
27 | |||
28 | # link rule for the .so file, .lds has to be first | ||
29 | $(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) | ||
30 | $(call if_changed,vdso64ld) | ||
31 | |||
32 | # strip rule for the .so file | ||
33 | $(obj)/%.so: OBJCOPYFLAGS := -S | ||
34 | $(obj)/%.so: $(obj)/%.so.dbg FORCE | ||
35 | $(call if_changed,objcopy) | ||
36 | |||
37 | # assembly rules for the .S files | ||
38 | $(obj-vdso64): %.o: %.S | ||
39 | $(call if_changed_dep,vdso64as) | ||
40 | |||
41 | # actual build commands | ||
42 | quiet_cmd_vdso64ld = VDSO64L $@ | ||
43 | cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ | ||
44 | quiet_cmd_vdso64as = VDSO64A $@ | ||
45 | cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< | ||
46 | |||
47 | # install commands for the unstripped file | ||
48 | quiet_cmd_vdso_install = INSTALL $@ | ||
49 | cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ | ||
50 | |||
51 | vdso64.so: $(obj)/vdso64.so.dbg | ||
52 | @mkdir -p $(MODLIB)/vdso | ||
53 | $(call cmd,vdso_install) | ||
54 | |||
55 | vdso_install: vdso64.so | ||
diff --git a/arch/s390/kernel/vdso64/clock_getres.S b/arch/s390/kernel/vdso64/clock_getres.S new file mode 100644 index 000000000000..488e31a3c0e7 --- /dev/null +++ b/arch/s390/kernel/vdso64/clock_getres.S | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Userland implementation of clock_getres() for 64 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | .text | ||
17 | .align 4 | ||
18 | .globl __kernel_clock_getres | ||
19 | .type __kernel_clock_getres,@function | ||
20 | __kernel_clock_getres: | ||
21 | .cfi_startproc | ||
22 | cghi %r2,CLOCK_REALTIME | ||
23 | je 0f | ||
24 | cghi %r2,CLOCK_MONOTONIC | ||
25 | jne 2f | ||
26 | 0: ltgr %r3,%r3 | ||
27 | jz 1f /* res == NULL */ | ||
28 | larl %r1,3f | ||
29 | lg %r0,0(%r1) | ||
30 | xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */ | ||
31 | stg %r0,8(%r3) /* store tp->tv_usec */ | ||
32 | 1: lghi %r2,0 | ||
33 | br %r14 | ||
34 | 2: lghi %r1,__NR_clock_getres /* fallback to svc */ | ||
35 | svc 0 | ||
36 | br %r14 | ||
37 | 3: .quad CLOCK_REALTIME_RES | ||
38 | .cfi_endproc | ||
39 | .size __kernel_clock_getres,.-__kernel_clock_getres | ||
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S new file mode 100644 index 000000000000..738a410b7eb2 --- /dev/null +++ b/arch/s390/kernel/vdso64/clock_gettime.S | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * Userland implementation of clock_gettime() for 64 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | .text | ||
17 | .align 4 | ||
18 | .globl __kernel_clock_gettime | ||
19 | .type __kernel_clock_gettime,@function | ||
20 | __kernel_clock_gettime: | ||
21 | .cfi_startproc | ||
22 | larl %r5,_vdso_data | ||
23 | cghi %r2,CLOCK_REALTIME | ||
24 | je 4f | ||
25 | cghi %r2,CLOCK_MONOTONIC | ||
26 | jne 9f | ||
27 | |||
28 | /* CLOCK_MONOTONIC */ | ||
29 | ltgr %r3,%r3 | ||
30 | jz 3f /* tp == NULL */ | ||
31 | 0: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */ | ||
32 | tmll %r4,0x0001 /* pending update ? loop */ | ||
33 | jnz 0b | ||
34 | stck 48(%r15) /* Store TOD clock */ | ||
35 | lg %r1,48(%r15) | ||
36 | sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
37 | mghi %r1,1000 | ||
38 | srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ | ||
39 | alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */ | ||
40 | lg %r0,__VDSO_XTIME_SEC(%r5) | ||
41 | alg %r1,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */ | ||
42 | alg %r0,__VDSO_WTOM_SEC(%r5) | ||
43 | clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ | ||
44 | jne 0b | ||
45 | larl %r5,10f | ||
46 | 1: clg %r1,0(%r5) | ||
47 | jl 2f | ||
48 | slg %r1,0(%r5) | ||
49 | aghi %r0,1 | ||
50 | j 1b | ||
51 | 2: stg %r0,0(%r3) /* store tp->tv_sec */ | ||
52 | stg %r1,8(%r3) /* store tp->tv_nsec */ | ||
53 | 3: lghi %r2,0 | ||
54 | br %r14 | ||
55 | |||
56 | /* CLOCK_REALTIME */ | ||
57 | 4: ltr %r3,%r3 /* tp == NULL */ | ||
58 | jz 8f | ||
59 | 5: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */ | ||
60 | tmll %r4,0x0001 /* pending update ? loop */ | ||
61 | jnz 5b | ||
62 | stck 48(%r15) /* Store TOD clock */ | ||
63 | lg %r1,48(%r15) | ||
64 | sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
65 | mghi %r1,1000 | ||
66 | srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ | ||
67 | alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */ | ||
68 | lg %r0,__VDSO_XTIME_SEC(%r5) | ||
69 | clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ | ||
70 | jne 5b | ||
71 | larl %r5,10f | ||
72 | 6: clg %r1,0(%r5) | ||
73 | jl 7f | ||
74 | slg %r1,0(%r5) | ||
75 | aghi %r0,1 | ||
76 | j 6b | ||
77 | 7: stg %r0,0(%r3) /* store tp->tv_sec */ | ||
78 | stg %r1,8(%r3) /* store tp->tv_nsec */ | ||
79 | 8: lghi %r2,0 | ||
80 | br %r14 | ||
81 | |||
82 | /* Fallback to system call */ | ||
83 | 9: lghi %r1,__NR_clock_gettime | ||
84 | svc 0 | ||
85 | br %r14 | ||
86 | |||
87 | 10: .quad 1000000000 | ||
88 | .cfi_endproc | ||
89 | .size __kernel_clock_gettime,.-__kernel_clock_gettime | ||
diff --git a/arch/s390/kernel/vdso64/gettimeofday.S b/arch/s390/kernel/vdso64/gettimeofday.S new file mode 100644 index 000000000000..f873e75634e1 --- /dev/null +++ b/arch/s390/kernel/vdso64/gettimeofday.S | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Userland implementation of gettimeofday() for 64 bits processes in a | ||
3 | * s390 kernel for use in the vDSO | ||
4 | * | ||
5 | * Copyright IBM Corp. 2008 | ||
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License (version 2 only) | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <asm/vdso.h> | ||
13 | #include <asm/asm-offsets.h> | ||
14 | #include <asm/unistd.h> | ||
15 | |||
16 | .text | ||
17 | .align 4 | ||
18 | .globl __kernel_gettimeofday | ||
19 | .type __kernel_gettimeofday,@function | ||
20 | __kernel_gettimeofday: | ||
21 | .cfi_startproc | ||
22 | larl %r5,_vdso_data | ||
23 | 0: ltgr %r3,%r3 /* check if tz is NULL */ | ||
24 | je 1f | ||
25 | mvc 0(8,%r3),__VDSO_TIMEZONE(%r5) | ||
26 | 1: ltgr %r2,%r2 /* check if tv is NULL */ | ||
27 | je 4f | ||
28 | lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */ | ||
29 | tmll %r4,0x0001 /* pending update ? loop */ | ||
30 | jnz 0b | ||
31 | stck 48(%r15) /* Store TOD clock */ | ||
32 | lg %r1,48(%r15) | ||
33 | sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ | ||
34 | mghi %r1,1000 | ||
35 | srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ | ||
36 | alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime.tv_nsec */ | ||
37 | lg %r0,__VDSO_XTIME_SEC(%r5) /* xtime.tv_sec */ | ||
38 | clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ | ||
39 | jne 0b | ||
40 | larl %r5,5f | ||
41 | 2: clg %r1,0(%r5) | ||
42 | jl 3f | ||
43 | slg %r1,0(%r5) | ||
44 | aghi %r0,1 | ||
45 | j 2b | ||
46 | 3: stg %r0,0(%r2) /* store tv->tv_sec */ | ||
47 | slgr %r0,%r0 /* tv_nsec -> tv_usec */ | ||
48 | ml %r0,8(%r5) | ||
49 | srlg %r0,%r0,6 | ||
50 | stg %r0,8(%r2) /* store tv->tv_usec */ | ||
51 | 4: lghi %r2,0 | ||
52 | br %r14 | ||
53 | 5: .quad 1000000000 | ||
54 | .long 274877907 | ||
55 | .cfi_endproc | ||
56 | .size __kernel_gettimeofday,.-__kernel_gettimeofday | ||
diff --git a/arch/s390/kernel/vdso64/note.S b/arch/s390/kernel/vdso64/note.S new file mode 100644 index 000000000000..79a071e4357e --- /dev/null +++ b/arch/s390/kernel/vdso64/note.S | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. | ||
3 | * Here we can supply some information useful to userland. | ||
4 | */ | ||
5 | |||
6 | #include <linux/uts.h> | ||
7 | #include <linux/version.h> | ||
8 | #include <linux/elfnote.h> | ||
9 | |||
10 | ELFNOTE_START(Linux, 0, "a") | ||
11 | .long LINUX_VERSION_CODE | ||
12 | ELFNOTE_END | ||
diff --git a/arch/s390/kernel/vdso64/vdso64.lds.S b/arch/s390/kernel/vdso64/vdso64.lds.S new file mode 100644 index 000000000000..9f5979d102a9 --- /dev/null +++ b/arch/s390/kernel/vdso64/vdso64.lds.S | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * This is the infamous ld script for the 64 bits vdso | ||
3 | * library | ||
4 | */ | ||
5 | #include <asm/vdso.h> | ||
6 | |||
7 | OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") | ||
8 | OUTPUT_ARCH(s390:64-bit) | ||
9 | ENTRY(_start) | ||
10 | |||
11 | SECTIONS | ||
12 | { | ||
13 | . = VDSO64_LBASE + SIZEOF_HEADERS; | ||
14 | |||
15 | .hash : { *(.hash) } :text | ||
16 | .gnu.hash : { *(.gnu.hash) } | ||
17 | .dynsym : { *(.dynsym) } | ||
18 | .dynstr : { *(.dynstr) } | ||
19 | .gnu.version : { *(.gnu.version) } | ||
20 | .gnu.version_d : { *(.gnu.version_d) } | ||
21 | .gnu.version_r : { *(.gnu.version_r) } | ||
22 | |||
23 | .note : { *(.note.*) } :text :note | ||
24 | |||
25 | . = ALIGN(16); | ||
26 | .text : { | ||
27 | *(.text .stub .text.* .gnu.linkonce.t.*) | ||
28 | } :text | ||
29 | PROVIDE(__etext = .); | ||
30 | PROVIDE(_etext = .); | ||
31 | PROVIDE(etext = .); | ||
32 | |||
33 | /* | ||
34 | * Other stuff is appended to the text segment: | ||
35 | */ | ||
36 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | ||
37 | .rodata1 : { *(.rodata1) } | ||
38 | |||
39 | .dynamic : { *(.dynamic) } :text :dynamic | ||
40 | |||
41 | .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
42 | .eh_frame : { KEEP (*(.eh_frame)) } :text | ||
43 | .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } | ||
44 | |||
45 | .rela.dyn ALIGN(8) : { *(.rela.dyn) } | ||
46 | .got ALIGN(8) : { *(.got .toc) } | ||
47 | |||
48 | _end = .; | ||
49 | PROVIDE(end = .); | ||
50 | |||
51 | /* | ||
52 | * Stabs debugging sections are here too. | ||
53 | */ | ||
54 | .stab 0 : { *(.stab) } | ||
55 | .stabstr 0 : { *(.stabstr) } | ||
56 | .stab.excl 0 : { *(.stab.excl) } | ||
57 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
58 | .stab.index 0 : { *(.stab.index) } | ||
59 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
60 | .comment 0 : { *(.comment) } | ||
61 | |||
62 | /* | ||
63 | * DWARF debug sections. | ||
64 | * Symbols in the DWARF debugging sections are relative to the | ||
65 | * beginning of the section so we begin them at 0. | ||
66 | */ | ||
67 | /* DWARF 1 */ | ||
68 | .debug 0 : { *(.debug) } | ||
69 | .line 0 : { *(.line) } | ||
70 | /* GNU DWARF 1 extensions */ | ||
71 | .debug_srcinfo 0 : { *(.debug_srcinfo) } | ||
72 | .debug_sfnames 0 : { *(.debug_sfnames) } | ||
73 | /* DWARF 1.1 and DWARF 2 */ | ||
74 | .debug_aranges 0 : { *(.debug_aranges) } | ||
75 | .debug_pubnames 0 : { *(.debug_pubnames) } | ||
76 | /* DWARF 2 */ | ||
77 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } | ||
78 | .debug_abbrev 0 : { *(.debug_abbrev) } | ||
79 | .debug_line 0 : { *(.debug_line) } | ||
80 | .debug_frame 0 : { *(.debug_frame) } | ||
81 | .debug_str 0 : { *(.debug_str) } | ||
82 | .debug_loc 0 : { *(.debug_loc) } | ||
83 | .debug_macinfo 0 : { *(.debug_macinfo) } | ||
84 | /* SGI/MIPS DWARF 2 extensions */ | ||
85 | .debug_weaknames 0 : { *(.debug_weaknames) } | ||
86 | .debug_funcnames 0 : { *(.debug_funcnames) } | ||
87 | .debug_typenames 0 : { *(.debug_typenames) } | ||
88 | .debug_varnames 0 : { *(.debug_varnames) } | ||
89 | /* DWARF 3 */ | ||
90 | .debug_pubtypes 0 : { *(.debug_pubtypes) } | ||
91 | .debug_ranges 0 : { *(.debug_ranges) } | ||
92 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } | ||
93 | |||
94 | . = ALIGN(4096); | ||
95 | PROVIDE(_vdso_data = .); | ||
96 | |||
97 | /DISCARD/ : { | ||
98 | *(.note.GNU-stack) | ||
99 | *(.branch_lt) | ||
100 | *(.data .data.* .gnu.linkonce.d.* .sdata*) | ||
101 | *(.bss .sbss .dynbss .dynsbss) | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Very old versions of ld do not recognize this name token; use the constant. | ||
107 | */ | ||
108 | #define PT_GNU_EH_FRAME 0x6474e550 | ||
109 | |||
110 | /* | ||
111 | * We must supply the ELF program headers explicitly to get just one | ||
112 | * PT_LOAD segment, and set the flags explicitly to make segments read-only. | ||
113 | */ | ||
114 | PHDRS | ||
115 | { | ||
116 | text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ | ||
117 | dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
118 | note PT_NOTE FLAGS(4); /* PF_R */ | ||
119 | eh_frame_hdr PT_GNU_EH_FRAME; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * This controls what symbols we export from the DSO. | ||
124 | */ | ||
125 | VERSION | ||
126 | { | ||
127 | VDSO_VERSION_STRING { | ||
128 | global: | ||
129 | /* | ||
130 | * Has to be there for the kernel to find | ||
131 | */ | ||
132 | __kernel_gettimeofday; | ||
133 | __kernel_clock_gettime; | ||
134 | __kernel_clock_getres; | ||
135 | |||
136 | local: *; | ||
137 | }; | ||
138 | } | ||
diff --git a/arch/s390/kernel/vdso64/vdso64_wrapper.S b/arch/s390/kernel/vdso64/vdso64_wrapper.S new file mode 100644 index 000000000000..d8e2ac14d564 --- /dev/null +++ b/arch/s390/kernel/vdso64/vdso64_wrapper.S | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <asm/page.h> | ||
3 | |||
4 | .section ".data.page_aligned" | ||
5 | |||
6 | .globl vdso64_start, vdso64_end | ||
7 | .balign PAGE_SIZE | ||
8 | vdso64_start: | ||
9 | .incbin "arch/s390/kernel/vdso64/vdso64.so" | ||
10 | .balign PAGE_SIZE | ||
11 | vdso64_end: | ||
12 | |||
13 | .previous | ||