012-Add-vDSO-support-for-Coldfire-platform.patch 13 KB

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