Skip to contentSkip to conversation

ARM: VDSO

PATCH Superseded Nathan Lynch 4 participants 20 messages Aug 22, 2014 – Sep 12, 2014

Subsystems (2)

v9 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v9 cover ARM: VDSO

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7. This follows the example of arm64 in conception but significantly differs in some aspects of the implementation (C vs assembly, mainly).

Clocks supported:
- CLOCK_REALTIME
- CLOCK_MONOTONIC
- CLOCK_REALTIME_COARSE
- CLOCK_MONOTONIC_COARSE

This also provides clock_getres (as arm64 does).

getcpu support is planned but not included at this time.

For applications to transparently benefit from this change, ARM-specific support code needs to be added to glibc. I have such a patch, and have verified that glibc's self tests do not detect any regressions. I hope to have that code added to glibc for the 2.21 release.

The VDSO symbols are available for lookup via dlsym even with an unpatched glibc.

Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for clock_getres and coarse clocks is independent of the timer implementation and is provided unconditionally. High-resolution clock support requires changes to the arch timer code, posted here:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/281280.html

The VDSO will function correctly without those changes, but gettimeofday and clock_gettime with CLOCK_REALTIME/CLOCK_MONOTONIC will not be accelerated.

Tested on OMAP5 and i.MX6, verifying that results obtained with the vdso are consistent with those obtained from the kernel. On OMAP5 I observe a 3- to 4-fold speedup for gettimeofday / CLOCK_REALTIME, with even better (if less interesting) speedups for the coarse clock ids and clock_getres.

I've been testing and benchmarking this with some custom test code which I have hosted here:

https://github.com/nlynch-mentor/vdsotest

Unpatched FSF GDB may complain "warning: Could not load shared library symbols for linux-vdso.so.1." This is not an ARM-specific issue. Current Fedora and Debian patch their GDB packages to prevent this warning.

Changes since v8:
- Update to 3.17-rc1.
- Split out arch timer changes into separate series.
- Ensure that VDSO will not attempt to read the counter if access is not enabled; this check can be removed after the arch timer changes are merged. See update_vsyscall and vdso_can_use_arch_timer in patch #5.

Changes since v7:
- Update to next-20140801.
- In arch_setup_additional_pages, fix call to get_unmapped_area - use bytes (not pages) for length argument.
- As x86 does, separate data and text into two VMAs, [vvar] and [vdso] respectively. These have different permissions; [vdso] will allow debuggers to set breakpoints, but [vvar] is read-only and cannot be modified even via ptrace.
- Use _install_special_mapping for signal page, vvar, and vdso mappings.
- Add -DDISABLE_BRANCH_PROFILING.
- Add --no-undefined -Bsymbolic to link options to cause linker to error out on unresolved references, making checkundef script unnecessary.
- Specify max-page-size, common-page-size in linker options so the true alignment is reflected in program header; otherwise gdb gets confused.
- Fix incremental build vs. generated auxvec.h.
- Use appropriate unwind directives in __get_datapage.
- Added vdso_install target and help text. Install build-id symlinks as x86 does.
- Adjust update_vsyscall for changes in struct timekeeper.

Changes since v6:
- Update to 3.16-rc1.
- Remove -lgcc from link step - need to support GCC installations without libgcc.
- Force -O2 compilation to prevent GCC from emitting calls to libgcc math routines.
- Use custom post-processing to clear the EF_ARM_ABI_FLOAT_SOFT flag if set in the ELF header to produce a shared object which is architecturally allowed to be used by both soft- and hard-float code.
- Consolidate common arch timer code instead of duplicating it.
- Prevent the VDSO from attempting CP15 access on memory-only architected timer implementations by renaming the clocksource.

Changes since v5:
- Update to 3.15-rc1.
- Place vdso at a randomized offset above the stack along with the sigpage.
- Properly export asm/auxvec.h.
- Split patch into series for ease of review.

Changes since v4:
- Map data page at the beginning of the VMA to prevent orphan sections at the end of output invalidating the calculated offset.
- Move checkundef into cmd_vdsold to avoid spurious rebuilds.
- Change vdso_init message to pr_debug.
- Add -fno-stack-protector to cflags.

Changes since v3:
- Update to 3.14-rc6.
- Record vdso base in mm context before installing mapping (for the sake of perf_mmap_event).
- Use a more seqcount-like API for critical sections. Using seqcount API directly, however, would leak kernel pointers to userspace when lockdep is enabled.
- Trap instead of looping forever in division-by-zero stubs.

Changes since v2:
- Update to 3.14-rc4.
- Make vDSO configurable, depending on AEABI and MMU.
- Defer shifting of nanosecond component of timespec: fixes observed 1ns inconsistencies for CLOCK_REALTIME, CLOCK_MONOTONIC (see 45a7905fc48f for arm64 equivalent).
- Force reload of seq_count when spinning: without a memory clobber after the load of vdata->seq_count, GCC can generate code like this:

    2f8:   e59c9020        ldr     r9, [ip, #32]
    2fc:   e3190001        tst     r9, #1
    300:   1a000033        bne     3d4 <do_realtime+0x104>
    304:   f57ff05b        dmb     ish
    308:   e59c3034        ldr     r3, [ip, #52]   ; 0x34
    ...
    3d4:   eafffffe        b       3d4 <do_realtime+0x104>

- Build vdso.so with -lgcc: calls to __lshrdi3, __divsi3 sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.
- Do not clear PG_reserved on vdso pages.
- Remove unnecessary get_page calls.
- Simplify ELF signature check during init.
- Use volatile for asm syscall fallbacks.
- Check whether vdso_pagelist is initialized in arm_install_vdso.
- Record clocksource mask in data page.
- Reduce code duplication in do_realtime, do_monotonic.
- Reduce calculations performed in critical sections.
- Simplify coarse clock handling.
- Move datapage load to its own assembly routine.
- Tune vdso_data layout and tweak field names.
- Check vdso shared object for undefined symbols during build.

Changes since v1:
- update to 3.14-rc1
- ensure cache coherency for data page
- Document the kernel-to-userspace protocol for vdso data page updates, and note that the timekeeping core prevents concurrent updates.
- update wall-to-monotonic fields unconditionally
- move vdso_start, vdso_end declarations to vdso.h
- correctly build and run when CONFIG_ARM_ARCH_TIMER=n
- rearrange linker script to avoid overlapping sections when CONFIG_DEBUGINFO=n
- remove use_syscall checks from coarse clock paths
- crib BUG_INSTR (0xe7f001f2) from asm/bug.h for text fill

Nathan Lynch (6):
ARM: use _install_special_mapping for sigpage
ARM: place sigpage at a random offset above stack
ARM: miscellaneous vdso infrastructure, preparation
ARM: add vdso user-space code
ARM: vdso initialization, mapping, and synchronization
ARM: add CONFIG_VDSO Kconfig and Makefile bits

 arch/arm/Makefile                    |   8 +
 arch/arm/include/asm/Kbuild          |   1 -
 arch/arm/include/asm/auxvec.h        |   1 +
 arch/arm/include/asm/elf.h           |   9 +
 arch/arm/include/asm/mmu.h           |   3 +
 arch/arm/include/asm/vdso.h          |  34 ++++
 arch/arm/include/asm/vdso_datapage.h |  60 +++++++
 arch/arm/include/uapi/asm/Kbuild     |   1 +
 arch/arm/include/uapi/asm/auxvec.h   |   7 +
 arch/arm/kernel/Makefile             |   1 +
 arch/arm/kernel/asm-offsets.c        |   5 +
 arch/arm/kernel/process.c            |  71 +++++++-
 arch/arm/kernel/vdso.c               | 207 ++++++++++++++++++++++
 arch/arm/mm/Kconfig                  |  15 ++
 arch/arm/vdso/.gitignore             |   1 +
 arch/arm/vdso/Makefile               |  74 ++++++++
 arch/arm/vdso/datapage.S             |  15 ++
 arch/arm/vdso/vdso.S                 |  35 ++++
 arch/arm/vdso/vdso.lds.S             |  88 ++++++++++
 arch/arm/vdso/vdsomunge.c            | 208 +++++++++++++++++++++++
 arch/arm/vdso/vgettimeofday.c        | 320 +++++++++++++++++++++++++++++++++++
 21 files changed, 1154 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/include/asm/auxvec.h
 create mode 100644 arch/arm/include/asm/vdso.h
 create mode 100644 arch/arm/include/asm/vdso_datapage.h
 create mode 100644 arch/arm/include/uapi/asm/auxvec.h
 create mode 100644 arch/arm/kernel/vdso.c
 create mode 100644 arch/arm/vdso/.gitignore
 create mode 100644 arch/arm/vdso/Makefile
 create mode 100644 arch/arm/vdso/datapage.S
 create mode 100644 arch/arm/vdso/vdso.S
 create mode 100644 arch/arm/vdso/vdso.lds.S
 create mode 100644 arch/arm/vdso/vdsomunge.c
 create mode 100644 arch/arm/vdso/vgettimeofday.c
Signature · 1 line
1.9.3
#1 lore raw

PATCH v9 1/6 ARM: use _install_special_mapping for sigpage

_install_special_mapping allows the VMA to be identifed in /proc/pid/maps without the use of arch_vma_name, providing a slight net reduction in object size:

  text    data     bss     dec     hex filename
  2996      96     144    3236     ca4 arch/arm/kernel/process.o (before)
  2956     104     144    3204     c84 arch/arm/kernel/process.o (after)
---
 arch/arm/kernel/process.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)
arch/arm/kernel/process.c +16 -8
index 81ef686a91ca..46fbbb3701a0 100644
@@ -472,19 +472,23 @@ int in_gate_area_no_mm(unsigned long addr)
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-	return is_gate_vma(vma) ? "[vectors]" :
-		(vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
-		 "[sigpage]" : NULL;
+	return is_gate_vma(vma) ? "[vectors]" : NULL;
 }
 
 static struct page *signal_page;
 extern struct page *get_signal_page(void);
 
+static const struct vm_special_mapping sigpage_mapping = {
+	.name = "[sigpage]",
+	.pages = &signal_page,
+};
+
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
 	unsigned long addr;
-	int ret;
+	int ret = 0;
 
 	if (!signal_page)
 		signal_page = get_signal_page();
@@ -498,12 +502,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 		goto up_fail;
 	}
 
-	ret = install_special_mapping(mm, addr, PAGE_SIZE,
+	vma = _install_special_mapping(mm, addr, PAGE_SIZE,
 		VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
-		&signal_page);
+		&sigpage_mapping);
+
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto up_fail;
+	}
 
-	if (ret == 0)
-		mm->context.sigpage = addr;
+	mm->context.sigpage = addr;
 
  up_fail:
 	up_write(&mm->mmap_sem);
Signature · 1 line
1.9.3
#2 lore raw

PATCH v9 2/6 ARM: place sigpage at a random offset above stack

In reply to Nathan Lynch

The sigpage is currently placed alongside shared libraries etc in the address space. Similar to what x86_64 does for its VDSO, place the sigpage at a randomized offset above the stack so that learning the base address of the sigpage doesn't help expose where shared libraries are loaded in the address space (and vice versa).

---
 arch/arm/kernel/process.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)
arch/arm/kernel/process.c +35 -1
index 46fbbb3701a0..9e0d931dd475 100644
@@ -475,6 +475,38 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 	return is_gate_vma(vma) ? "[vectors]" : NULL;
 }
 
+/* If possible, provide a placement hint at a random offset from the
+ * stack for the signal page.
+ */
+static unsigned long sigpage_addr(const struct mm_struct *mm, unsigned int npages)
+{
+	unsigned long offset;
+	unsigned long first;
+	unsigned long last;
+	unsigned long addr;
+	unsigned int slots;
+
+	first = PAGE_ALIGN(mm->start_stack);
+
+	last = TASK_SIZE - (npages << PAGE_SHIFT);
+
+	/* No room after stack? */
+	if (first > last)
+		return 0;
+
+	/* Just enough room? */
+	if (first == last)
+		return first;
+
+	slots = ((last - first) >> PAGE_SHIFT) + 1;
+
+	offset = get_random_int() % slots;
+
+	addr = first + (offset << PAGE_SHIFT);
+
+	return addr;
+}
+
 static struct page *signal_page;
 extern struct page *get_signal_page(void);
 
@@ -488,6 +520,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long addr;
+	unsigned long hint;
 	int ret = 0;
 
 	if (!signal_page)
@@ -496,7 +529,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 		return -ENOMEM;
 
 	down_write(&mm->mmap_sem);
-	addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+	hint = sigpage_addr(mm, 1);
+	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
Signature · 1 line
1.9.3
#3 lore raw

PATCH v9 3/6 ARM: miscellaneous vdso infrastructure, preparation

In reply to Nathan Lynch

Define the layout of the data structure shared between kernel and userspace.

Track the vdso address in the mm_context; needed for communicating AT_SYSINFO_EHDR to the ELF loader.

Add declarations for arm_install_vdso; implementation is in a following patch.

Define AT_SYSINFO_EHDR, and, if CONFIG_VDSO=y, report the vdso shared object address via the ELF auxiliary vector.

Note - this adds the AT_SYSINFO_EHDR in a new user-visible header asm/auxvec.h; this is consistent with other architectures.

---
 arch/arm/include/asm/Kbuild          |  1 -
 arch/arm/include/asm/auxvec.h        |  1 +
 arch/arm/include/asm/elf.h           |  9 ++++++
 arch/arm/include/asm/mmu.h           |  3 ++
 arch/arm/include/asm/vdso.h          | 34 ++++++++++++++++++++
 arch/arm/include/asm/vdso_datapage.h | 60 ++++++++++++++++++++++++++++++++++++
 arch/arm/include/uapi/asm/Kbuild     |  1 +
 arch/arm/include/uapi/asm/auxvec.h   |  7 +++++
 8 files changed, 115 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/auxvec.h
 create mode 100644 arch/arm/include/asm/vdso.h
 create mode 100644 arch/arm/include/asm/vdso_datapage.h
 create mode 100644 arch/arm/include/uapi/asm/auxvec.h
arch/arm/include/asm/Kbuild +0 -1
index 70cd84eb7fda..9fb902425606 100644
@@ -1,6 +1,5 @@
 
 
-generic-y += auxvec.h
 generic-y += bitsperlong.h
 generic-y += cputime.h
 generic-y += current.h
arch/arm/include/asm/auxvec.h new file +1 -0
new file mode 100644
index 000000000000..fbd388c46299
@@ -0,0 +1 @@
+#include <uapi/asm/auxvec.h>
arch/arm/include/asm/elf.h +9 -0
index f4b46d39b9cf..e9822ac77efe 100644
@@ -1,7 +1,9 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <asm/auxvec.h>
 #include <asm/hwcap.h>
+#include <asm/vdso_datapage.h>
 
 /*
  * ELF register definitions..
@@ -129,6 +131,13 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
 #ifdef CONFIG_MMU
+#ifdef CONFIG_VDSO
+#define ARCH_DLINFO						\
+do {								\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,				\
+		    (elf_addr_t)current->mm->context.vdso);	\
+} while (0)
+#endif
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
 int arch_setup_additional_pages(struct linux_binprm *, int);
arch/arm/include/asm/mmu.h +3 -0
index 64fd15159b7d..a5b47421059d 100644
@@ -11,6 +11,9 @@ typedef struct {
 #endif
 	unsigned int	vmalloc_seq;
 	unsigned long	sigpage;
+#ifdef CONFIG_VDSO
+	unsigned long	vdso;
+#endif
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
arch/arm/include/asm/vdso.h new file +34 -0
new file mode 100644
index 000000000000..08d06e73ccf2
@@ -0,0 +1,34 @@
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct mm_struct;
+
+#ifdef CONFIG_VDSO
+
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr);
+
+extern char vdso_start, vdso_end;
+
+extern unsigned int vdso_total_pages;
+
+#else /* CONFIG_VDSO */
+
+static inline void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+}
+
+static const unsigned int vdso_total_pages = 0;
+
+#endif /* CONFIG_VDSO */
+
+#endif /* __ASSEMBLY__ */
+
+#define VDSO_LBASE	0x0
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
arch/arm/include/asm/vdso_datapage.h new file +60 -0

60 lines not on this page · raw message

arch/arm/include/uapi/asm/Kbuild +1 -0
index 70a1c9da30ca..a1c05f93d920 100644
@@ -1,6 +1,7 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
 header-y += byteorder.h
 header-y += fcntl.h
 header-y += hwcap.h
arch/arm/include/uapi/asm/auxvec.h new file +7 -0
new file mode 100644
index 000000000000..f56936b97ec2
@@ -0,0 +1,7 @@
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* vDSO location */
+#define AT_SYSINFO_EHDR	33
+
+#endif
Signature · 1 line
1.9.3
#4 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

In reply to Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

If CONFIG_ARM_ARCH_TIMER is not enabled, the vdso cannot service high-resolution clocks and falls back to syscalls. Low-resolution clocks e.g. CLOCK_REALTIME_COARSE can be serviced regardless.

Of particular note is that a post-processing step ("vdsomunge") is necessary to produce a shared object which is architecturally allowed to be used by both soft- and hard-float EABI programs.

The 2012 edition of the ARM ABI defines Tag_ABI_VFP_args = 3 "Code is compatible with both the base and VFP variants; the user did not permit non-variadic functions to pass FP parameters/results." Unfortunately current toolchains do not support this tag, which is ideally what we would use.

The best available option is to ensure that both EF_ARM_ABI_FLOAT_SOFT and EF_ARM_ABI_FLOAT_HARD are unset in the ELF header's e_flags, indicating that the shared object is "old" and should be accepted for backward compatibility's sake. While binutils < 2.24 appear to produce a vdso.so with both flags clear, 2.24 always sets EF_ARM_ABI_FLOAT_SOFT, with no way to inhibit this behavior. So we have to fix things up with a custom post-processing step.

In fact, the VDSO code in glibc does much less validation (including checking these flags) than the code for handling conventional file-backed shared libraries, so this is a bit moot unless glibc's VDSO code becomes more strict.

---
 arch/arm/kernel/asm-offsets.c |   5 +
 arch/arm/vdso/.gitignore      |   1 +
 arch/arm/vdso/Makefile        |  74 ++++++++++
 arch/arm/vdso/datapage.S      |  15 ++
 arch/arm/vdso/vdso.S          |  35 +++++
 arch/arm/vdso/vdso.lds.S      |  88 ++++++++++++
 arch/arm/vdso/vdsomunge.c     | 208 +++++++++++++++++++++++++++
 arch/arm/vdso/vgettimeofday.c | 320 ++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 746 insertions(+)
 create mode 100644 arch/arm/vdso/.gitignore
 create mode 100644 arch/arm/vdso/Makefile
 create mode 100644 arch/arm/vdso/datapage.S
 create mode 100644 arch/arm/vdso/vdso.S
 create mode 100644 arch/arm/vdso/vdso.lds.S
 create mode 100644 arch/arm/vdso/vdsomunge.c
 create mode 100644 arch/arm/vdso/vgettimeofday.c
arch/arm/kernel/asm-offsets.c +5 -0
index 713e807621d2..72b4c3873dc8 100644
@@ -24,6 +24,7 @@
 #include <asm/memory.h>
 #include <asm/procinfo.h>
 #include <asm/suspend.h>
+#include <asm/vdso_datapage.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
 
@@ -200,5 +201,9 @@ int main(void)
 #endif
   DEFINE(KVM_VTTBR,		offsetof(struct kvm, arch.vttbr));
 #endif
+  BLANK();
+#ifdef CONFIG_VDSO
+  DEFINE(VDSO_DATA_SIZE,	sizeof(union vdso_data_store));
+#endif
   return 0; 
 }
arch/arm/vdso/.gitignore new file +1 -0
new file mode 100644
index 000000000000..f8b69d84238e
@@ -0,0 +1 @@
+vdso.lds
arch/arm/vdso/Makefile new file +74 -0

74 lines not on this page · raw message

arch/arm/vdso/datapage.S new file +15 -0
new file mode 100644
index 000000000000..a2e60367931b
@@ -0,0 +1,15 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+
+	.align 2
+.L_vdso_data_ptr:
+	.long	_start - . - VDSO_DATA_SIZE
+
+ENTRY(__get_datapage)
+	.fnstart
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.fnend
+ENDPROC(__get_datapage)
arch/arm/vdso/vdso.S new file +35 -0
new file mode 100644
index 000000000000..b2b97e3e7bab
@@ -0,0 +1,35 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_start, vdso_end
+	.balign PAGE_SIZE
+vdso_start:
+	.incbin "arch/arm/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
arch/arm/vdso/vdso.lds.S new file +88 -0

88 lines not on this page · raw message

arch/arm/vdso/vdsomunge.c new file +208 -0

208 lines not on this page · raw message

arch/arm/vdso/vgettimeofday.c new file +320 -0

320 lines not on this page · raw message

Signature · 1 line
1.9.3
#5 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

Hi Nathan,

Quoted 5 lines · Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

I'm still a bit puzzled as to how we can implement a compat version of this for a 32-bit userspace running under a 64-bit kernel. Maybe the answer is that we don't care enough (programs will still work fine without it), but if we did want to then we're going to need to build the kernel with two toolchains and it gets really horrible.

Do you have any ideas?

Will

#6 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

Quoted 9 lines · Will Deacon

Hi Nathan,

Quoted 5 lines · Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

Quoted 7 lines

I'm still a bit puzzled as to how we can implement a compat version of this for a 32-bit userspace running under a 64-bit kernel. Maybe the answer is that we don't care enough (programs will still work fine without it), but if we did want to then we're going to need to build the kernel with two toolchains and it gets really horrible.

Do you have any ideas?

Convince the gcc and binutils people to add a-m32 option to aarch64? That's how x86_64 pulls this off :) Or you could require a cross-compiler to be available to enable this particular feature.

I have no further bright ideas, unless aarch64 and arm assembly are miraculously nearly compatible, in which case you could do something like what x32 does (build 64-bit and then use objcopy to turn the result into an x32 object).

--Andy

#7 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Will Deacon
Quoted 5 lines · Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

I'm still a bit puzzled as to how we can implement a compat version of this for a 32-bit userspace running under a 64-bit kernel. Maybe the answer is that we don't care enough (programs will still work fine without it), but if we did want to then we're going to need to build the kernel with two toolchains and it gets really horrible.

Quoted 5 lines
Quoted 1 line

Do you have any ideas?

Convince the gcc and binutils people to add a-m32 option to aarch64? That's how x86_64 pulls this off :) Or you could require a cross-compiler to be available to enable this particular feature.

The compilers have two separate backends, so I think I'll know what they say. I guess it's either overhauling kbuild to support two cross compilers, or have some shell script to accept an option we make up.

Quoted 4 lines

I have no further bright ideas, unless aarch64 and arm assembly are miraculously nearly compatible, in which case you could do something like what x32 does (build 64-bit and then use objcopy to turn the result into an x32 object).

The assembler is pretty different, so I'd be pretty uneasy about trying to do that.

Will

#8 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

Quoted 17 lines · Will Deacon
Quoted 16 lines · Andy Lutomirski
Quoted 14 lines · Will Deacon
Quoted 5 lines · Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

I'm still a bit puzzled as to how we can implement a compat version of this for a 32-bit userspace running under a 64-bit kernel. Maybe the answer is that we don't care enough (programs will still work fine without it), but if we did want to then we're going to need to build the kernel with two toolchains and it gets really horrible.

Do you have any ideas?

Quoted 7 lines
Quoted 3 lines

Convince the gcc and binutils people to add a-m32 option to aarch64? That's how x86_64 pulls this off :) Or you could require a cross-compiler to be available to enable this particular feature.

The compilers have two separate backends, so I think I'll know what they say. I guess it's either overhauling kbuild to support two cross compilers, or have some shell script to accept an option we make up.

arch/powerpc has addressed this with a CROSS32_COMPILE= variable for producing 32-bit outputs (compat vdso, bootwrapper) during a 64-bit kernel build. I think that was used before powerpc toolchains commonly honored -m32.

#9 lore raw

PATCH v9 4/6 ARM: add vdso user-space code

In reply to Will Deacon
Quoted 9 lines · Will Deacon

Hi Nathan,

Quoted 5 lines · Nathan Lynch

Place vdso-related user-space code in arch/arm/kernel/vdso/.

It is almost completely written in C with some assembly helpers to load the data page address, sample the counter, and fall back to system calls when necessary.

Quoted 7 lines

I'm still a bit puzzled as to how we can implement a compat version of this for a 32-bit userspace running under a 64-bit kernel. Maybe the answer is that we don't care enough (programs will still work fine without it), but if we did want to then we're going to need to build the kernel with two toolchains and it gets really horrible.

Do you have any ideas?

Assuming a GCC+binutils toolchain, I don't have any workable ideas for generating ARMv7 shared object during an arm64 kernel build without relying on a second compiler. I think theoretically you could do something like what kuser32.S does, but that would be untenable for something as complex as a vdso.

I recognize that this might present an awkward situation where an ARMv7 program could incur more system call overhead on arm64 than it does on arm, but I don't see any way around it.

#10 lore raw

PATCH v9 5/6 ARM: vdso initialization, mapping, and synchronization

In reply to Nathan Lynch

Initialize the vdso page list at boot, install the vdso mapping at exec time, and update the data page during timer ticks. This code is not built if CONFIG_VDSO is not enabled.

Account for the vdso length when randomizing the offset from the stack. The vdso is placed immediately following the sigpage with a separate install_special_mapping call in arm_install_vdso.

---
 arch/arm/kernel/process.c |  17 +++-
 arch/arm/kernel/vdso.c    | 207 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 221 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/kernel/vdso.c
arch/arm/kernel/process.c +14 -3
index 9e0d931dd475..7aa1025aff1f 100644
@@ -41,6 +41,7 @@
 #include <asm/system_misc.h>
 #include <asm/mach/time.h>
 #include <asm/tls.h>
+#include <asm/vdso.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -476,7 +477,7 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 }
 
 /* If possible, provide a placement hint at a random offset from the
- * stack for the signal page.
+ * stack for the sigpage and vdso pages.
  */
 static unsigned long sigpage_addr(const struct mm_struct *mm, unsigned int npages)
 {
@@ -519,6 +520,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+	unsigned long npages;
 	unsigned long addr;
 	unsigned long hint;
 	int ret = 0;
@@ -528,9 +530,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (!signal_page)
 		return -ENOMEM;
 
+	npages = 1; /* for sigpage */
+	npages += vdso_total_pages;
+
 	down_write(&mm->mmap_sem);
-	hint = sigpage_addr(mm, 1);
-	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
+	hint = sigpage_addr(mm, npages);
+	addr = get_unmapped_area(NULL, hint, npages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
@@ -547,6 +552,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
 	mm->context.sigpage = addr;
 
+	/* Unlike the sigpage, failure to install the vdso is unlikely
+	 * to be fatal to the process, so no error check needed
+	 * here.
+	 */
+	arm_install_vdso(mm, addr + PAGE_SIZE);
+
  up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
arch/arm/kernel/vdso.c new file +207 -0

207 lines not on this page · raw message

Signature · 1 line
1.9.3
#11 lore raw

PATCH v9 6/6 ARM: add CONFIG_VDSO Kconfig and Makefile bits

In reply to Nathan Lynch

Allow users to enable the vdso in Kconfig; include the vdso in the build if CONFIG_VDSO is enabled. Add 'vdso_install' target.

---
 arch/arm/Makefile        |  8 ++++++++
 arch/arm/kernel/Makefile |  1 +
 arch/arm/mm/Kconfig      | 15 +++++++++++++++
 3 files changed, 24 insertions(+)
arch/arm/Makefile +8 -0
index 0ce9d0f71f2a..109c011ef4ed 100644
@@ -264,6 +264,7 @@ core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)		+= arch/arm/vfp/
 core-$(CONFIG_XEN)		+= arch/arm/xen/
 core-$(CONFIG_KVM_ARM_HOST) 	+= arch/arm/kvm/
+core-$(CONFIG_VDSO)		+= arch/arm/vdso/
 
 # If we have a machine-specific directory, then include it in the build.
 core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
@@ -316,6 +317,12 @@ PHONY += dtbs dtbs_install
 dtbs dtbs_install: prepare scripts
 	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@
 
+PHONY += vdso_install
+vdso_install:
+ifeq ($(CONFIG_VDSO),y)
+	$(Q)$(MAKE) $(build)=arch/arm/vdso $@
+endif
+
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
@@ -340,4 +347,5 @@ define archhelp
   echo  '                  Install using (your) ~/bin/$(INSTALLKERNEL) or'
   echo  '                  (distribution) /sbin/$(INSTALLKERNEL) or'
   echo  '                  install to $$(INSTALL_PATH) and run lilo'
+  echo  '  vdso_install  - Install unstripped vdso.so to $$(INSTALL_MOD_PATH)/vdso'
 endef
arch/arm/kernel/Makefile +1 -0
index 38ddd9f83d0e..3e2b80658344 100644
@@ -86,6 +86,7 @@ obj-$(CONFIG_PERF_EVENTS)	+= perf_regs.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o perf_event_cpu.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
+obj-$(CONFIG_VDSO)		+= vdso.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
arch/arm/mm/Kconfig +15 -0
index ae69809a9e47..c256323040d6 100644
@@ -824,6 +824,21 @@ config KUSER_HELPERS
 	  Say N here only if you are absolutely certain that you do not
 	  need these helpers; otherwise, the safe option is to say Y.
 
+config VDSO
+	bool "Enable vDSO for acceleration of some system calls"
+	depends on AEABI && MMU
+	default y if ARM_ARCH_TIMER
+	select GENERIC_TIME_VSYSCALL
+	help
+	  Place in the process address space an ELF shared object
+	  providing fast implementations of several system calls,
+	  including gettimeofday and clock_gettime.  Systems that
+	  implement the ARM architected timer will receive maximum
+	  benefit.
+
+	  You must have glibc 2.21 or later for programs to seamlessly
+	  take advantage of this.
+
 config DMA_CACHE_RWFO
 	bool "Enable read/write for ownership DMA cache maintenance"
 	depends on CPU_V6K && SMP
Signature · 1 line
1.9.3
#12 lore raw

v9 cover ARM: VDSO

In reply to Nathan Lynch
Quoted 199 lines · Nathan Lynch

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7. This follows the example of arm64 in conception but significantly differs in some aspects of the implementation (C vs assembly, mainly).

Clocks supported:
- CLOCK_REALTIME
- CLOCK_MONOTONIC
- CLOCK_REALTIME_COARSE
- CLOCK_MONOTONIC_COARSE

This also provides clock_getres (as arm64 does).

getcpu support is planned but not included at this time.

For applications to transparently benefit from this change, ARM-specific support code needs to be added to glibc. I have such a patch, and have verified that glibc's self tests do not detect any regressions. I hope to have that code added to glibc for the 2.21 release.

The VDSO symbols are available for lookup via dlsym even with an unpatched glibc.

Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for clock_getres and coarse clocks is independent of the timer implementation and is provided unconditionally. High-resolution clock support requires changes to the arch timer code, posted here:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/281280.html

The VDSO will function correctly without those changes, but gettimeofday and clock_gettime with CLOCK_REALTIME/CLOCK_MONOTONIC will not be accelerated.

Tested on OMAP5 and i.MX6, verifying that results obtained with the vdso are consistent with those obtained from the kernel. On OMAP5 I observe a 3- to 4-fold speedup for gettimeofday / CLOCK_REALTIME, with even better (if less interesting) speedups for the coarse clock ids and clock_getres.

I've been testing and benchmarking this with some custom test code which I have hosted here:

https://github.com/nlynch-mentor/vdsotest

Unpatched FSF GDB may complain "warning: Could not load shared library symbols for linux-vdso.so.1." This is not an ARM-specific issue. Current Fedora and Debian patch their GDB packages to prevent this warning.

Changes since v8:
- Update to 3.17-rc1.
- Split out arch timer changes into separate series.
- Ensure that VDSO will not attempt to read the counter if access is not enabled; this check can be removed after the arch timer changes are merged. See update_vsyscall and vdso_can_use_arch_timer in patch #5.

Changes since v7:
- Update to next-20140801.
- In arch_setup_additional_pages, fix call to get_unmapped_area - use bytes (not pages) for length argument.
- As x86 does, separate data and text into two VMAs, [vvar] and [vdso] respectively. These have different permissions; [vdso] will allow debuggers to set breakpoints, but [vvar] is read-only and cannot be modified even via ptrace.
- Use _install_special_mapping for signal page, vvar, and vdso mappings.
- Add -DDISABLE_BRANCH_PROFILING.
- Add --no-undefined -Bsymbolic to link options to cause linker to error out on unresolved references, making checkundef script unnecessary.
- Specify max-page-size, common-page-size in linker options so the true alignment is reflected in program header; otherwise gdb gets confused.
- Fix incremental build vs. generated auxvec.h.
- Use appropriate unwind directives in __get_datapage.
- Added vdso_install target and help text. Install build-id symlinks as x86 does.
- Adjust update_vsyscall for changes in struct timekeeper.

Changes since v6:
- Update to 3.16-rc1.
- Remove -lgcc from link step - need to support GCC installations without libgcc.
- Force -O2 compilation to prevent GCC from emitting calls to libgcc math routines.
- Use custom post-processing to clear the EF_ARM_ABI_FLOAT_SOFT flag if set in the ELF header to produce a shared object which is architecturally allowed to be used by both soft- and hard-float code.
- Consolidate common arch timer code instead of duplicating it.
- Prevent the VDSO from attempting CP15 access on memory-only architected timer implementations by renaming the clocksource.

Changes since v5:
- Update to 3.15-rc1.
- Place vdso at a randomized offset above the stack along with the sigpage.
- Properly export asm/auxvec.h.
- Split patch into series for ease of review.

Changes since v4:
- Map data page at the beginning of the VMA to prevent orphan sections at the end of output invalidating the calculated offset.
- Move checkundef into cmd_vdsold to avoid spurious rebuilds.
- Change vdso_init message to pr_debug.
- Add -fno-stack-protector to cflags.

Changes since v3:
- Update to 3.14-rc6.
- Record vdso base in mm context before installing mapping (for the sake of perf_mmap_event).
- Use a more seqcount-like API for critical sections. Using seqcount API directly, however, would leak kernel pointers to userspace when lockdep is enabled.
- Trap instead of looping forever in division-by-zero stubs.

Changes since v2:
- Update to 3.14-rc4.
- Make vDSO configurable, depending on AEABI and MMU.
- Defer shifting of nanosecond component of timespec: fixes observed 1ns inconsistencies for CLOCK_REALTIME, CLOCK_MONOTONIC (see 45a7905fc48f for arm64 equivalent).
- Force reload of seq_count when spinning: without a memory clobber after the load of vdata->seq_count, GCC can generate code like this:

    2f8:   e59c9020        ldr     r9, [ip, #32]
    2fc:   e3190001        tst     r9, #1
    300:   1a000033        bne     3d4 <do_realtime+0x104>
    304:   f57ff05b        dmb     ish
    308:   e59c3034        ldr     r3, [ip, #52]   ; 0x34
    ...
    3d4:   eafffffe        b       3d4 <do_realtime+0x104>

- Build vdso.so with -lgcc: calls to __lshrdi3, __divsi3 sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.
- Do not clear PG_reserved on vdso pages.
- Remove unnecessary get_page calls.
- Simplify ELF signature check during init.
- Use volatile for asm syscall fallbacks.
- Check whether vdso_pagelist is initialized in arm_install_vdso.
- Record clocksource mask in data page.
- Reduce code duplication in do_realtime, do_monotonic.
- Reduce calculations performed in critical sections.
- Simplify coarse clock handling.
- Move datapage load to its own assembly routine.
- Tune vdso_data layout and tweak field names.
- Check vdso shared object for undefined symbols during build.

Changes since v1:
- update to 3.14-rc1
- ensure cache coherency for data page
- Document the kernel-to-userspace protocol for vdso data page updates, and note that the timekeeping core prevents concurrent updates.
- update wall-to-monotonic fields unconditionally
- move vdso_start, vdso_end declarations to vdso.h
- correctly build and run when CONFIG_ARM_ARCH_TIMER=n
- rearrange linker script to avoid overlapping sections when CONFIG_DEBUGINFO=n
- remove use_syscall checks from coarse clock paths
- crib BUG_INSTR (0xe7f001f2) from asm/bug.h for text fill

Nathan Lynch (6):
ARM: use _install_special_mapping for sigpage
ARM: place sigpage at a random offset above stack
ARM: miscellaneous vdso infrastructure, preparation
ARM: add vdso user-space code
ARM: vdso initialization, mapping, and synchronization
ARM: add CONFIG_VDSO Kconfig and Makefile bits

 arch/arm/Makefile                    |   8 +
 arch/arm/include/asm/Kbuild          |   1 -
 arch/arm/include/asm/auxvec.h        |   1 +
 arch/arm/include/asm/elf.h           |   9 +
 arch/arm/include/asm/mmu.h           |   3 +
 arch/arm/include/asm/vdso.h          |  34 ++++
 arch/arm/include/asm/vdso_datapage.h |  60 +++++++
 arch/arm/include/uapi/asm/Kbuild     |   1 +
 arch/arm/include/uapi/asm/auxvec.h   |   7 +
 arch/arm/kernel/Makefile             |   1 +
 arch/arm/kernel/asm-offsets.c        |   5 +
 arch/arm/kernel/process.c            |  71 +++++++-
 arch/arm/kernel/vdso.c               | 207 ++++++++++++++++++++++
 arch/arm/mm/Kconfig                  |  15 ++
 arch/arm/vdso/.gitignore             |   1 +
 arch/arm/vdso/Makefile               |  74 ++++++++
 arch/arm/vdso/datapage.S             |  15 ++
 arch/arm/vdso/vdso.S                 |  35 ++++
 arch/arm/vdso/vdso.lds.S             |  88 ++++++++++
 arch/arm/vdso/vdsomunge.c            | 208 +++++++++++++++++++++++
 arch/arm/vdso/vgettimeofday.c        | 320 +++++++++++++++++++++++++++++++++++
 21 files changed, 1154 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/include/asm/auxvec.h
 create mode 100644 arch/arm/include/asm/vdso.h
 create mode 100644 arch/arm/include/asm/vdso_datapage.h
 create mode 100644 arch/arm/include/uapi/asm/auxvec.h
Quoted 8 lines
 create mode 100644 arch/arm/kernel/vdso.c
 create mode 100644 arch/arm/vdso/.gitignore
 create mode 100644 arch/arm/vdso/Makefile
 create mode 100644 arch/arm/vdso/datapage.S
 create mode 100644 arch/arm/vdso/vdso.S
 create mode 100644 arch/arm/vdso/vdso.lds.S
 create mode 100644 arch/arm/vdso/vdsomunge.c
 create mode 100644 arch/arm/vdso/vgettimeofday.c

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Thanks,
Christopher

Signature · 3 lines
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by the Linux Foundation.
#13 lore raw

v9 cover ARM: VDSO

Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

There's certainly code that could be consolidated, but it would be a decently large project.

Some day, I'd like to see everyone use vdso2c, but it needs to stop knowing that it's targetting x86 for that to happen.

--Andy

#14 lore raw

v9 cover ARM: VDSO

In reply to Christopher Covington
Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Sorry to not respond to this promptly, was distracted by some other work.

As Andy said, the possibility for consolidating some aspects of VDSO support is there, but it would be a fair bit of work.

For example, arch_setup_additional_pages tends to have the general form of:

lock mmap_sem
get_unmapped_area
install_special_mapping (or _install_special_mapping, preferably) stash vdso address in mmu context
release mmap_sem

But there are a lot of implementation details that differ:

         +----------------------------------------------------------------
         | Number of VMAs installed
         |   +------------------------------------------------------------
         |   | Considers uses_interp
         |   |     +------------------------------------------------------
         |   |     | Uses _install_special_mapping
         |   |     |     +------------------------------------------------
         |   |     |     | Performs additional work (e.g. remap_pfn_range)
         |   |     |     |     +------------------------------------------
         |   |     |     |     | Randomizes VDSO offset vs stack and libs
         |   |     |     |     |     +------------------------------------
         |   |     |     |     |     | Records VDSO address in mmu context
         |   |     |     |     |     |     +------------------------------
         |   |     |     |     |     |     | Supports compat VDSO
         |   |     |     |     |     |     |     +------------------------
         |   |     |     |     |     |     |     | Supports disabling VDSO
         |   |     |     |     |     |     |     | at boot (e.g. vdso=off)
         |   |     |     |     |     |     |     |     +------------------
         |   |     |     |     |     |     |     |     | Can disable VDSO
 arch    |   |     |     |     |     |     |     |     | via Kconfig
---------+---+-----+-----+-----+-----+-----+-----+-----+------------------
 arm*    | 3 | no  | yes | no  | yes | yes | no  | no  | yes
 arm64   | 2 | no  | yes | no  | no  | yes | no  | no  | no
 hexagon | 1 | no  | no  | no  | no  | yes | no  | no  | no
 mips    | 1 | no  | no  | no  | no  | yes | no  | no  | no
 powerpc | 1 | no  | no  | no  | no  | yes | yes | no  | no
 s390    | 1 | yes | no  | no  | no  | yes | yes | yes | no
 sh      | 1 | no  | no  | no  | no  | yes | no  | yes | yes
 tile    | 1 | no  | no  | yes | no  | yes | no  | yes | no
 x86     | 2 | no  | yes | yes | yes | yes | yes | yes | no

* With VDSO patches from this thread, of course.

I think pushing the mmap_sem lock/unlock up into the ELF loader might be of some benefit (slightly reduced complexity in the arch code). But any generic replacement for arch_setup_additional_pages will have to account for all the differences above, and probably a few more I've missed.

#15 lore raw

v9 cover ARM: VDSO

Hi Nathan,

Quoted 56 lines · Nathan Lynch
Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Sorry to not respond to this promptly, was distracted by some other work.

As Andy said, the possibility for consolidating some aspects of VDSO support is there, but it would be a fair bit of work.

For example, arch_setup_additional_pages tends to have the general form of:

lock mmap_sem
get_unmapped_area
install_special_mapping (or _install_special_mapping, preferably) stash vdso address in mmu context
release mmap_sem

But there are a lot of implementation details that differ:

         +----------------------------------------------------------------
         | Number of VMAs installed
         |   +------------------------------------------------------------
         |   | Considers uses_interp
         |   |     +------------------------------------------------------
         |   |     | Uses _install_special_mapping
         |   |     |     +------------------------------------------------
         |   |     |     | Performs additional work (e.g. remap_pfn_range)
         |   |     |     |     +------------------------------------------
         |   |     |     |     | Randomizes VDSO offset vs stack and libs
         |   |     |     |     |     +------------------------------------
         |   |     |     |     |     | Records VDSO address in mmu context
         |   |     |     |     |     |     +------------------------------
         |   |     |     |     |     |     | Supports compat VDSO
         |   |     |     |     |     |     |     +------------------------
         |   |     |     |     |     |     |     | Supports disabling VDSO
         |   |     |     |     |     |     |     | at boot (e.g. vdso=off)
         |   |     |     |     |     |     |     |     +------------------
         |   |     |     |     |     |     |     |     | Can disable VDSO
 arch    |   |     |     |     |     |     |     |     | via Kconfig
---------+---+-----+-----+-----+-----+-----+-----+-----+------------------
 arm*    | 3 | no  | yes | no  | yes | yes | no  | no  | yes
 arm64   | 2 | no  | yes | no  | no  | yes | no  | no  | no
 hexagon | 1 | no  | no  | no  | no  | yes | no  | no  | no
 mips    | 1 | no  | no  | no  | no  | yes | no  | no  | no
 powerpc | 1 | no  | no  | no  | no  | yes | yes | no  | no
 s390    | 1 | yes | no  | no  | no  | yes | yes | yes | no
 sh      | 1 | no  | no  | no  | no  | yes | no  | yes | yes
 tile    | 1 | no  | no  | yes | no  | yes | no  | yes | no
 x86     | 2 | no  | yes | yes | yes | yes | yes | yes | no
Quoted 7 lines

* With VDSO patches from this thread, of course.

I think pushing the mmap_sem lock/unlock up into the ELF loader might be of some benefit (slightly reduced complexity in the arch code). But any generic replacement for arch_setup_additional_pages will have to account for all the differences above, and probably a few more I've missed.

I really appreciate the detailed response. I'll try to find time to explore this further, hopefully using QEMU to run kernels for most of those architectures.

Christopher

Signature · 3 lines
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by the Linux Foundation.
#16 lore raw

v9 cover ARM: VDSO

In reply to Nathan Lynch
Quoted 57 lines · Nathan Lynch
Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Sorry to not respond to this promptly, was distracted by some other work.

As Andy said, the possibility for consolidating some aspects of VDSO support is there, but it would be a fair bit of work.

For example, arch_setup_additional_pages tends to have the general form of:

lock mmap_sem
get_unmapped_area
install_special_mapping (or _install_special_mapping, preferably) stash vdso address in mmu context
release mmap_sem

But there are a lot of implementation details that differ:

         +----------------------------------------------------------------
         | Number of VMAs installed
         |   +------------------------------------------------------------
         |   | Considers uses_interp
         |   |     +------------------------------------------------------
         |   |     | Uses _install_special_mapping
         |   |     |     +------------------------------------------------
         |   |     |     | Performs additional work (e.g. remap_pfn_range)
         |   |     |     |     +------------------------------------------
         |   |     |     |     | Randomizes VDSO offset vs stack and libs
         |   |     |     |     |     +------------------------------------
         |   |     |     |     |     | Records VDSO address in mmu context
         |   |     |     |     |     |     +------------------------------
         |   |     |     |     |     |     | Supports compat VDSO
         |   |     |     |     |     |     |     +------------------------
         |   |     |     |     |     |     |     | Supports disabling VDSO
         |   |     |     |     |     |     |     | at boot (e.g. vdso=off)
         |   |     |     |     |     |     |     |     +------------------
         |   |     |     |     |     |     |     |     | Can disable VDSO
 arch    |   |     |     |     |     |     |     |     | via Kconfig
---------+---+-----+-----+-----+-----+-----+-----+-----+------------------
 arm*    | 3 | no  | yes | no  | yes | yes | no  | no  | yes
 arm64   | 2 | no  | yes | no  | no  | yes | no  | no  | no
 hexagon | 1 | no  | no  | no  | no  | yes | no  | no  | no
 mips    | 1 | no  | no  | no  | no  | yes | no  | no  | no
 powerpc | 1 | no  | no  | no  | no  | yes | yes | no  | no
 s390    | 1 | yes | no  | no  | no  | yes | yes | yes | no
 sh      | 1 | no  | no  | no  | no  | yes | no  | yes | yes
 tile    | 1 | no  | no  | yes | no  | yes | no  | yes | no
 x86     | 2 | no  | yes | yes | yes | yes | yes | yes | no
Quoted 8 lines

* With VDSO patches from this thread, of course.

I think pushing the mmap_sem lock/unlock up into the ELF loader might be of some benefit (slightly reduced complexity in the arch code). But any generic replacement for arch_setup_additional_pages will have to account for all the differences above, and probably a few more I've missed.

Wow, nice table! I think that we should eventually get rid of most of these differences.

Christopher, since you seem to be interested in CRIU, one thing to note is that any architecture that shoves a pointer to the vdso into the mmu context is likely to fail if the vdso is mremapped. CRIU needs to mremap the vdso, so this is a problem.

x86_64 is an exception: it doesn't use that pointer for anything.

--Andy

#17 lore raw

v9 cover ARM: VDSO

Quoted 67 lines · Andy Lutomirski
Quoted 57 lines · Nathan Lynch
Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Sorry to not respond to this promptly, was distracted by some other work.

As Andy said, the possibility for consolidating some aspects of VDSO support is there, but it would be a fair bit of work.

For example, arch_setup_additional_pages tends to have the general form of:

lock mmap_sem
get_unmapped_area
install_special_mapping (or _install_special_mapping, preferably) stash vdso address in mmu context
release mmap_sem

But there are a lot of implementation details that differ:

         +----------------------------------------------------------------
         | Number of VMAs installed
         |   +------------------------------------------------------------
         |   | Considers uses_interp
         |   |     +------------------------------------------------------
         |   |     | Uses _install_special_mapping
         |   |     |     +------------------------------------------------
         |   |     |     | Performs additional work (e.g. remap_pfn_range)
         |   |     |     |     +------------------------------------------
         |   |     |     |     | Randomizes VDSO offset vs stack and libs
         |   |     |     |     |     +------------------------------------
         |   |     |     |     |     | Records VDSO address in mmu context
         |   |     |     |     |     |     +------------------------------
         |   |     |     |     |     |     | Supports compat VDSO
         |   |     |     |     |     |     |     +------------------------
         |   |     |     |     |     |     |     | Supports disabling VDSO
         |   |     |     |     |     |     |     | at boot (e.g. vdso=off)
         |   |     |     |     |     |     |     |     +------------------
         |   |     |     |     |     |     |     |     | Can disable VDSO
 arch    |   |     |     |     |     |     |     |     | via Kconfig
---------+---+-----+-----+-----+-----+-----+-----+-----+------------------
 arm*    | 3 | no  | yes | no  | yes | yes | no  | no  | yes
 arm64   | 2 | no  | yes | no  | no  | yes | no  | no  | no
 hexagon | 1 | no  | no  | no  | no  | yes | no  | no  | no
 mips    | 1 | no  | no  | no  | no  | yes | no  | no  | no
 powerpc | 1 | no  | no  | no  | no  | yes | yes | no  | no
 s390    | 1 | yes | no  | no  | no  | yes | yes | yes | no
 sh      | 1 | no  | no  | no  | no  | yes | no  | yes | yes
 tile    | 1 | no  | no  | yes | no  | yes | no  | yes | no
 x86     | 2 | no  | yes | yes | yes | yes | yes | yes | no
Quoted 8 lines

* With VDSO patches from this thread, of course.

I think pushing the mmap_sem lock/unlock up into the ELF loader might be of some benefit (slightly reduced complexity in the arch code). But any generic replacement for arch_setup_additional_pages will have to account for all the differences above, and probably a few more I've missed.

Quoted 2 lines

Wow, nice table! I think that we should eventually get rid of most of these differences.

Thanks, and agreed.

Quoted 6 lines

Christopher, since you seem to be interested in CRIU, one thing to note is that any architecture that shoves a pointer to the vdso into the mmu context is likely to fail if the vdso is mremapped. CRIU needs to mremap the vdso, so this is a problem.

x86_64 is an exception: it doesn't use that pointer for anything.

Hmm, I would expect architectures that implement arch_vma_name like so to experience problems with CRIU:

const char *arch_vma_name(struct vm_area_struct *vma)

{
	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
		return "[vdso]";
	return NULL;
}

Is this what you're referring to?

Looking at 3.17-rc3, every arch uses mm_context_t->vdso_base or similar to provide a value for AT_SYSINFO_EHDR at exec time. Is this also problematic?

#18 lore raw

v9 cover ARM: VDSO

Quoted 84 lines · Nathan Lynch
Quoted 67 lines · Andy Lutomirski
Quoted 57 lines · Nathan Lynch
Quoted 8 lines · Christopher Covington

It appears to me that there is code in several architecture subdirectories (I'm aware of x86, arm64, and with these patches arm[32] and I would be surprised if there weren't more) doing largely the same setup of special mappings at randomized offsets, checking ELF magic etc. Not that these patches should necessarily do it, but is there a reasonable amount of consolidation that could be done, or am I underestimating how much of this really does vary per architecture?

Sorry to not respond to this promptly, was distracted by some other work.

As Andy said, the possibility for consolidating some aspects of VDSO support is there, but it would be a fair bit of work.

For example, arch_setup_additional_pages tends to have the general form of:

lock mmap_sem
get_unmapped_area
install_special_mapping (or _install_special_mapping, preferably) stash vdso address in mmu context
release mmap_sem

But there are a lot of implementation details that differ:

         +----------------------------------------------------------------
         | Number of VMAs installed
         |   +------------------------------------------------------------
         |   | Considers uses_interp
         |   |     +------------------------------------------------------
         |   |     | Uses _install_special_mapping
         |   |     |     +------------------------------------------------
         |   |     |     | Performs additional work (e.g. remap_pfn_range)
         |   |     |     |     +------------------------------------------
         |   |     |     |     | Randomizes VDSO offset vs stack and libs
         |   |     |     |     |     +------------------------------------
         |   |     |     |     |     | Records VDSO address in mmu context
         |   |     |     |     |     |     +------------------------------
         |   |     |     |     |     |     | Supports compat VDSO
         |   |     |     |     |     |     |     +------------------------
         |   |     |     |     |     |     |     | Supports disabling VDSO
         |   |     |     |     |     |     |     | at boot (e.g. vdso=off)
         |   |     |     |     |     |     |     |     +------------------
         |   |     |     |     |     |     |     |     | Can disable VDSO
 arch    |   |     |     |     |     |     |     |     | via Kconfig
---------+---+-----+-----+-----+-----+-----+-----+-----+------------------
 arm*    | 3 | no  | yes | no  | yes | yes | no  | no  | yes
 arm64   | 2 | no  | yes | no  | no  | yes | no  | no  | no
 hexagon | 1 | no  | no  | no  | no  | yes | no  | no  | no
 mips    | 1 | no  | no  | no  | no  | yes | no  | no  | no
 powerpc | 1 | no  | no  | no  | no  | yes | yes | no  | no
 s390    | 1 | yes | no  | no  | no  | yes | yes | yes | no
 sh      | 1 | no  | no  | no  | no  | yes | no  | yes | yes
 tile    | 1 | no  | no  | yes | no  | yes | no  | yes | no
 x86     | 2 | no  | yes | yes | yes | yes | yes | yes | no
Quoted 8 lines

* With VDSO patches from this thread, of course.

I think pushing the mmap_sem lock/unlock up into the ELF loader might be of some benefit (slightly reduced complexity in the arch code). But any generic replacement for arch_setup_additional_pages will have to account for all the differences above, and probably a few more I've missed.

Quoted 2 lines

Wow, nice table! I think that we should eventually get rid of most of these differences.

Thanks, and agreed.

Quoted 6 lines

Christopher, since you seem to be interested in CRIU, one thing to note is that any architecture that shoves a pointer to the vdso into the mmu context is likely to fail if the vdso is mremapped. CRIU needs to mremap the vdso, so this is a problem.

x86_64 is an exception: it doesn't use that pointer for anything.

Hmm, I would expect architectures that implement arch_vma_name like so to experience problems with CRIU:

Quoted 8 lines

const char *arch_vma_name(struct vm_area_struct *vma)

{
        if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
                return "[vdso]";
        return NULL;
}

Is this what you're referring to?

I never entirely understood why this wasn't a bigger problem. I think it only really caused problems when checkpointing, restoring, checkpointing *again*, and getting unlucky.

Quoted 5 lines

Looking at 3.17-rc3, every arch uses mm_context_t->vdso_base or similar to provide a value for AT_SYSINFO_EHDR at exec time. Is this also problematic?

This one's fine, since it's very hard to mremap between mapping the vdso and having exec return.

The ones that are serious problems (on x86 32-bit userspace, at least) are the vdso sigreturn trampoline and, even worse, the vdso sysexit trampoline. The latter will cause every syscall on any native 32-bit system or on any 32-bit compat code running on an Intel CPU to segfault immediately upon mremapping the vdso.

--Andy

#19 lore raw

v9 cover ARM: VDSO

In reply to Nathan Lynch
Quoted 31 lines · Nathan Lynch

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7. This follows the example of arm64 in conception but significantly differs in some aspects of the implementation (C vs assembly, mainly).

Clocks supported:
- CLOCK_REALTIME
- CLOCK_MONOTONIC
- CLOCK_REALTIME_COARSE
- CLOCK_MONOTONIC_COARSE

This also provides clock_getres (as arm64 does).

getcpu support is planned but not included at this time.

For applications to transparently benefit from this change, ARM-specific support code needs to be added to glibc. I have such a patch, and have verified that glibc's self tests do not detect any regressions. I hope to have that code added to glibc for the 2.21 release.

The VDSO symbols are available for lookup via dlsym even with an unpatched glibc.

Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for clock_getres and coarse clocks is independent of the timer implementation and is provided unconditionally. High-resolution clock support requires changes to the arch timer code, posted here:

Quoted 5 lines

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/281280.html

The VDSO will function correctly without those changes, but gettimeofday and clock_gettime with CLOCK_REALTIME/CLOCK_MONOTONIC will not be accelerated.

Russell, what is your current thinking on taking the VDSO patches? I believe all feedback has been addressed and I was hoping to get it into 3.18...