Root/target/linux/coldfire/patches/012-Add-vDSO-support-for-Coldfire-platform.patch

1From 1ba9968246337836bf0acdbf7733a628da5c5e42 Mon Sep 17 00:00:00 2001
2From: Alison Wang <b18965@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:42 +0800
4Subject: [PATCH 12/52] Add vDSO support for Coldfire platform
5
6This patch adds vDSO support for Coldfire platform.
7
8Signed-off-by: Alison Wang <b18965@freescale.com>
9---
10 arch/m68k/coldfire/common/entry.S | 36 ++++++++++
11 arch/m68k/coldfire/vdso/Makefile | 46 +++++++++++++
12 arch/m68k/coldfire/vdso/vdso-bin.S | 14 ++++
13 arch/m68k/coldfire/vdso/vdso-lib.S | 57 ++++++++++++++++
14 arch/m68k/coldfire/vdso/vdso-note.S | 27 ++++++++
15 arch/m68k/coldfire/vdso/vdso.c | 124 +++++++++++++++++++++++++++++++++++
16 arch/m68k/coldfire/vdso/vdso.lds.S | 89 +++++++++++++++++++++++++
17 arch/m68k/include/asm/auxvec.h | 9 +++
18 arch/m68k/mm/init.c | 3 +
19 9 files changed, 405 insertions(+), 0 deletions(-)
20 create mode 100644 arch/m68k/coldfire/vdso/Makefile
21 create mode 100644 arch/m68k/coldfire/vdso/vdso-bin.S
22 create mode 100644 arch/m68k/coldfire/vdso/vdso-lib.S
23 create mode 100644 arch/m68k/coldfire/vdso/vdso-note.S
24 create mode 100644 arch/m68k/coldfire/vdso/vdso.c
25 create mode 100644 arch/m68k/coldfire/vdso/vdso.lds.S
26
27--- a/arch/m68k/coldfire/common/entry.S
28+++ b/arch/m68k/coldfire/common/entry.S
29@@ -69,6 +69,9 @@ ENTRY(buserr)
30     movew #0x2700,%sr /* lock interrupts */
31 #endif
32     SAVE_ALL_INT
33+#ifdef CONFIG_VDSO
34+ jsr check_vdso_atomic_cmpxchg_32
35+#endif
36 #ifdef CONFIG_COLDFIRE_FOO
37     movew PT_0FF_SR(%sp),%d3 /* get original %sr */
38     oril #0x2000,%d3 /* set supervisor mode in it */
39@@ -82,6 +85,9 @@ ENTRY(buserr)
40 
41 ENTRY(trap)
42     SAVE_ALL_INT
43+#ifdef CONFIG_VDSO
44+ jsr check_vdso_atomic_cmpxchg_32
45+#endif
46     GET_CURRENT(%d0)
47     movel %sp,%sp@- /* stack frame pointer argument */
48     jsr trap_c
49@@ -213,6 +219,9 @@ do_delayed_trace:
50  */
51 ENTRY(inthandler)
52     SAVE_ALL_INT
53+#ifdef CONFIG_VDSO
54+ jsr check_vdso_atomic_cmpxchg_32
55+#endif
56     GET_CURRENT(%d0)
57     movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
58     addil #0x10000,%d0
59@@ -398,8 +407,35 @@ resume:
60     movew %a1@(TASK_THREAD+THREAD_SR),%d0
61     movew %d0,%sr
62 
63+#ifdef CONFIG_VDSO
64+ /* save thread pointer */
65+ lea _vdso_tp,%a0
66+ movel (%a0),%a0
67+ movel %a1@(TASK_INFO+TINFO_TP_VALUE),(%a0)
68+#endif
69     rts
70 
71+#ifdef CONFIG_VDSO
72+/* if interrupted PC is between 0x5fffe40c to 0x5ffffe412 */
73+/* then set PC back to 0x5fffe40c (start addr of __kernel_atomic_cmpxchg_32) */
74+/* note: these absolute addresses depend on vdso-lib.S and vdso.lds.S */
75+ENTRY(check_vdso_atomic_cmpxchg_32)
76+ movel %sp@(PT_OFF_PC),%d0
77+ cmpil #0x5fffe414,%d0 /* __kernel_atomic_cmpxchg_32: line 4 */
78+ ble label1
79+ cmpil #0x5fffe412,%d0 /* __kernel_atomic_cmpxchg_32: line 3 */
80+ beql label0
81+ cmpil #0x5fffe40e,%d0 /* __kernel_atomic_cmpxchg_32: line 2 */
82+ beql label0
83+ jra label1
84+label0:
85+ /* __kernel_atomic_cmpxchg_32: line 1 */
86+ movel #0x5fffe40c,%d0
87+ movel %d0,%sp@(PT_OFF_PC)
88+label1:
89+ rts
90+#endif
91+
92 .data
93 ALIGN
94 sys_call_table:
95--- /dev/null
96+++ b/arch/m68k/coldfire/vdso/Makefile
97@@ -0,0 +1,46 @@
98+#
99+# Makefile for arch/m68k/coldfire/vdso with special rules
100+# for building the DSO lib
101+#
102+# Based on arch/sh/kernel/vsyscall/Makefile
103+#
104+# Kurt Mahan <kmahan@freescale.com>
105+#
106+
107+obj-y := vdso.o vdso-bin.o
108+
109+$(obj)/vdso-bin.o: $(obj)/vdso.lds $(obj)/vdso-lib.so
110+
111+#
112+# The DSO Lib
113+#
114+
115+# special linker script for building DSO images
116+quiet_cmd_vdso = VDSO $@
117+ cmd_vdso = $(LD) -nostdlib --eh-frame-hdr $(SYSCFLAGS_$(@F)) \
118+ -T $(obj)/vdso.lds $^ -o $@
119+
120+vdso-flags = -shared -s -soname=linux-gate.so.1
121+
122+SYSCFLAGS_vdso-lib.so = $(vdso-flags)
123+
124+$(obj)/vdso-lib.so: $(obj)/vdso-lib.o $(obj)/vdso-note.o
125+ $(call if_changed,vdso)
126+
127+$(obj)/vdso.lds: $(srctree)/arch/m68k/coldfire/vdso/vdso.lds.S
128+ cp $< $@
129+
130+#
131+# Create a special relocatable object that should mirror the
132+# symbol table and layout of the linked DSO lib. With ld -R
133+# these symbols can be refered to in the kernel code rather
134+# than as hand-coded addresses
135+#
136+# extra-y += vdso-syms.o
137+# $(obj)/built-in.o: $(obj)/vdso-syms.o
138+# $(obj)/built-in.o: ld_flags += -R (obj)/vdso-syms.o
139+
140+# SYSCFLAGS_vdso-syms.o = -r
141+# $(obj)/vdso-syms.o: $(src)/vdso.lds \
142+# $(obj)/vdso-lib.o $(obj)/vdso-note.o FORCE
143+# $(call if_changed,vdso)
144--- /dev/null
145+++ b/arch/m68k/coldfire/vdso/vdso-bin.S
146@@ -0,0 +1,14 @@
147+/*
148+ * Setup vdso lib (.so) as binary image.
149+ */
150+
151+#include <linux/init.h>
152+
153+__INITDATA
154+
155+ .globl vdso_bin_start, vdso_bin_end
156+vdso_bin_start:
157+ .incbin "arch/m68k/coldfire/vdso/vdso-lib.so"
158+vdso_bin_end:
159+
160+__FINIT
161--- /dev/null
162+++ b/arch/m68k/coldfire/vdso/vdso-lib.S
163@@ -0,0 +1,57 @@
164+/*
165+ * VDSO userspace code
166+ *
167+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
168+ * Kurt Mahan <kmahan@freescale.com>
169+ *
170+ * This is free software; you can redistribute it and/or modify
171+ * it under the terms of the GNU General Public License as published by
172+ * the Free Software Foundation; either version 2 of the License, or
173+ * (at your option) any later version.
174+ */
175+
176+#include <linux/linkage.h>
177+#include <asm/unistd.h>
178+
179+ .text
180+/*
181+ * Read the thread pointer into A0 (and D0, for compatibility).
182+ */
183+ENTRY(__kernel_read_tp)
184+ .cfi_startproc
185+ lea kuser_vdso_tp,%a0
186+ movel (%a0), %d0
187+ movel %d0,%a0
188+ rts
189+ .cfi_endproc
190+ .size __kernel_read_tp,.-__kernel_read_tp
191+
192+/*
193+ * Atomic compare exchange. Can not clobber any registers
194+ * other than conditional codes.
195+ */
196+ENTRY(__kernel_atomic_cmpxchg_32)
197+ .cfi_startproc
198+ cmpl (%a0),%d0
199+ bne label0
200+ movel %d1, (%a0)
201+ jmp label1
202+label0:
203+ movel (%a0),%d0
204+label1:
205+ rts
206+ .cfi_endproc
207+ .size __kernel_atomic_cmpxchg_32,.-__kernel_atomic_cmpxchg_32
208+
209+/*
210+ * Atomic memory barrier. Can not clobber any registers
211+ * other than condition codes.
212+ */
213+ENTRY(__kernel_atomic_barrier)
214+ .cfi_startproc
215+ /* no code needed for uniprocs */
216+ rts
217+ .cfi_endproc
218+ .size __kernel_atomic_barrier,.-__kernel_atomic_barrier
219+
220+ .previous
221--- /dev/null
222+++ b/arch/m68k/coldfire/vdso/vdso-note.S
223@@ -0,0 +1,27 @@
224+/*
225+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
226+ * Here we can supply some information useful to userland.
227+ *
228+ * Based on arch/sh/kernel/vsyscall/vsyscall-note.S
229+ */
230+
231+#include <linux/uts.h>
232+#include <linux/version.h>
233+
234+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \
235+ .section name, flags; \
236+ .balign 4; \
237+ .long 1f - 0f; /* name length */ \
238+ .long 3f - 2f; /* data length */ \
239+ .long type; /* note type */ \
240+0: .asciz vendor; /* vendor name */ \
241+1: .balign 4; \
242+2:
243+
244+#define ASM_ELF_NOTE_END \
245+3: .balign 4; /* pad out section */ \
246+ .previous
247+
248+ ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
249+ .long LINUX_VERSION_CODE
250+ ASM_ELF_NOTE_END
251--- /dev/null
252+++ b/arch/m68k/coldfire/vdso/vdso.c
253@@ -0,0 +1,124 @@
254+/*
255+ * arch/m68k/coldfire/vdso/vdso.c
256+ *
257+ * Based on arch/sh/kernel/vsyscall/vsyscall.c
258+ *
259+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
260+ * Kurt Mahan <kmahan@freescale.com>
261+ *
262+ * This is free software; you can redistribute it and/or modify
263+ * it under the terms of the GNU General Public License as published by
264+ * the Free Software Foundation; either version 2 of the License, or
265+ * (at your option) any later version.
266+ */
267+
268+#include <linux/mm.h>
269+#include <linux/slab.h>
270+#include <linux/kernel.h>
271+#include <linux/init.h>
272+#include <linux/gfp.h>
273+#include <linux/module.h>
274+#include <linux/elf.h>
275+#include <linux/sched.h>
276+#include <linux/err.h>
277+
278+/* Mapping vDSO at the default address (what would've been returned
279+ * if VDSO_MBASE was 0) makes it impossible to extend data segment
280+ * (through brk()) for static binaries. The vDSO fits into one page,
281+ * so map it just before TASK_UNMAPPED_BASE.
282+ */
283+#define VDSO_MBASE (TASK_UNMAPPED_BASE - PAGE_SIZE)
284+#define VDSO_VAR_OFFSET 4096
285+
286+unsigned int vdso_enabled = 1;
287+EXPORT_SYMBOL_GPL(vdso_enabled);
288+
289+static struct page *vdso_pages[1];
290+
291+/* _vdso_var_start: vdso_page_start + offset_4K */
292+/* it's used to save key values from kernel */
293+void *_vdso_var_start;
294+void *_vdso_tp;
295+
296+extern const char vdso_bin_start, vdso_bin_end;
297+
298+int __init vdso_init(void)
299+{
300+ void *vdso_page = (void *)get_zeroed_page(GFP_ATOMIC);
301+ vdso_pages[0] = virt_to_page(vdso_page);
302+
303+ _vdso_var_start = (void *)(vdso_page + VDSO_VAR_OFFSET);
304+ _vdso_tp = _vdso_var_start;
305+
306+ printk(KERN_INFO "** VDSO_INIT\n");
307+
308+ /* copy dso bin in */
309+ memcpy(vdso_page,
310+ &vdso_bin_start, &vdso_bin_end - &vdso_bin_start);
311+
312+ return 0;
313+}
314+
315+/* setup VMA at program startup for the vdso page */
316+int arch_setup_additional_pages(struct linux_binprm *bprm,
317+ int executable_stack)
318+{
319+ struct mm_struct *mm = current->mm;
320+ unsigned long addr;
321+ int ret;
322+
323+ current->mm->context.vdso = 0;
324+
325+ down_write(&mm->mmap_sem);
326+ addr = get_unmapped_area(NULL, VDSO_MBASE, PAGE_SIZE, 0, 0);
327+ if (IS_ERR_VALUE(addr)) {
328+ ret = addr;
329+ goto up_fail;
330+ }
331+
332+ ret = install_special_mapping(mm, addr, PAGE_SIZE,
333+ VM_READ | VM_EXEC |
334+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |
335+ VM_ALWAYSDUMP,
336+ vdso_pages);
337+
338+ if (unlikely(ret))
339+ goto up_fail;
340+
341+ current->mm->context.vdso = (void *)addr;
342+
343+up_fail:
344+#ifdef DEBUG
345+ printk(KERN_DEBUG "arch_setup_additional_pages: addr: %lx; ret: %d\n",
346+ addr, ret);
347+#endif
348+
349+ up_write(&mm->mmap_sem);
350+ return ret;
351+}
352+
353+/*
354+ * check vma name
355+ */
356+const char *arch_vma_name(struct vm_area_struct *vma)
357+{
358+ if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
359+ return "[vdso]";
360+
361+ return NULL;
362+}
363+
364+struct vm_area_struct *get_gate_vma(struct task_struct *task)
365+{
366+ return NULL;
367+}
368+
369+int in_gate_area(struct task_struct *task, unsigned long address)
370+{
371+ return 0;
372+}
373+
374+int in_gate_area_no_task(unsigned long address)
375+{
376+ return 0;
377+}
378--- /dev/null
379+++ b/arch/m68k/coldfire/vdso/vdso.lds.S
380@@ -0,0 +1,89 @@
381+/*
382+ * Linker script for vdso DSO. The vdso page is an ELF shared
383+ * object prelinked to its virtual address, and with only one read-only
384+ * segment (that fits in one page). This script controls its layout.
385+ *
386+ * Based on arch/sh/kernel/vsyscall/vsyscall.lds.S
387+ *
388+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
389+ * Kurt Mahan <kmahan@freescale.com>
390+ *
391+ * This is free software; you can redistribute it and/or modify
392+ * it under the terms of the GNU General Public License as published by
393+ * the Free Software Foundation; either version 2 of the License, or
394+ * (at your option) any later version.
395+ */
396+
397+OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
398+OUTPUT_ARCH(m68k)
399+
400+/* The ELF entry point can be used to set the AT_SYSINFO value. */
401+ENTRY(__kernel_read_tp);
402+ENTRY(__kernel_atomic_cmpxchg_32);
403+ENTRY(__kernel_atomic_barrier);
404+
405+SECTIONS
406+{
407+ . = 0x5fffe000 + SIZEOF_HEADERS;
408+
409+ .hash : { *(.hash) } :text
410+ .gnu.hash : { *(.gnu.hash) }
411+ .dynsym : { *(.dynsym) }
412+ .dynstr : { *(.dynstr) }
413+ .gnu.version : { *(.gnu.version) }
414+ .gnu.version_d : { *(.gnu.version_d) }
415+ .gnu.version_r : { *(.gnu.version_r) }
416+
417+ /*
418+ * This linker script is used both with -r and with -shared.
419+ * For the layouts to match, we need to skip more than enough
420+ * space for the dynamic symbol table et al. If this amount
421+ * is insufficient, ld -shared will barf. Just increase it here.
422+ */
423+ . = 0x5fffe000 + 0x400;
424+
425+ .text : { *(.text) } :text
426+ .note : { *(.note.*) } :text :note
427+ .eh_frame_hdr : { *(.eh_frame_hdr ) } :text :eh_frame_hdr
428+ .eh_frame : {
429+ KEEP (*(.eh_frame))
430+ LONG (0)
431+ } :text
432+ .dynamic : { *(.dynamic) } :text :dynamic
433+ .useless : {
434+ *(.got.plt) *(.got)
435+ *(.data .data.* .gnu.linkonce.d.*)
436+ *(.dynbss)
437+ *(.bss .bss.* .gnu.linkonce.b.*)
438+ } :text
439+
440+ . = 0x5fffe000 + 0x1000;
441+ kuser_vdso_tp = .;
442+}
443+
444+/*
445+ * We must supply the ELF program headers explicitly to get just one
446+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
447+ */
448+PHDRS
449+{
450+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
451+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
452+ note PT_NOTE FLAGS(4); /* PF_R */
453+ eh_frame_hdr PT_GNU_EH_FRAME;
454+}
455+
456+/*
457+ * This controls what symbols we export from the DSO.
458+ */
459+VERSION
460+{
461+ LINUX_2.6 {
462+ global:
463+ __kernel_read_tp;
464+ __kernel_atomic_cmpxchg_32;
465+ __kernel_atomic_barrier;
466+
467+ local: *;
468+ };
469+}
470--- a/arch/m68k/include/asm/auxvec.h
471+++ b/arch/m68k/include/asm/auxvec.h
472@@ -1,4 +1,13 @@
473 #ifndef __ASMm68k_AUXVEC_H
474 #define __ASMm68k_AUXVEC_H
475+/*
476+ * Architecture-neutral AT_ values in 0-17, leave some room
477+ * for more of them.
478+ */
479+
480+#ifdef CONFIG_VDSO
481+/* Entry point to the vdso page */
482+#define AT_SYSINFO_EHDR 33
483+#endif
484 
485 #endif
486--- a/arch/m68k/mm/init.c
487+++ b/arch/m68k/mm/init.c
488@@ -39,6 +39,9 @@
489 #include <asm/sections.h>
490 #include <asm/tlb.h>
491 
492+#ifdef CONFIG_VDSO
493+int vdso_init(void);
494+#endif
495 
496 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
497 
498

Archive Download this file



interactive