Skip to contentSkip to conversation

ARM: VDSO

PATCH Superseded Nathan Lynch 8 participants 76 messages Jun 23, 2014 – Jul 22, 2014

Subsystems (5)

v7 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v7 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.

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.

Run-time 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

If this series is applied to an already-built tree and CONFIG_VDSO is enabled, an incremental build may fail with:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function)

This can be worked around by removing arch/arm/include/generated/asm/auxvec.h from the build tree. I lean toward attributing this to a Kbuild limitation/bug, but would appreciate extra scrutiny on the patch "ARM: miscellaneous vdso infrastructure, preparation" to see if there's anything to correct there.

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 (9):
clocksource: arm_arch_timer: change clocksource name if CP15
unavailable
clocksource: arm_arch_timer: enable counter access for 32-bit ARM
ARM: arch_timer: remove unused functions
arm64: arch_timer: remove unused functions
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/include/asm/Kbuild          |   1 -
 arch/arm/include/asm/arch_timer.h    |  25 ---
 arch/arm/include/asm/elf.h           |  11 ++
 arch/arm/include/asm/mmu.h           |   3 +
 arch/arm/include/asm/vdso.h          |  47 +++++
 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            |  56 +++++-
 arch/arm/kernel/vdso.c               | 168 ++++++++++++++++++
 arch/arm/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 arch/arm/mm/Kconfig                  |  15 ++
 arch/arm64/include/asm/arch_timer.h  |  31 ----
 drivers/clocksource/arm_arch_timer.c |  48 +++++-
 23 files changed, 1134 insertions(+), 65 deletions(-)
 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/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c
Signature · 1 line
1.9.3
#1 lore raw

PATCH v7 1/9 clocksource: arm_arch_timer: change clocksource name if CP15 unavailable

The arm and arm64 VDSOs need CP15 access to the architected counter. If this is unavailable (which is allowed by ARM v7), indicate this by changing the clocksource name to "arch_mem_counter" before registering the clocksource.

Suggested by Stephen Boyd.

---
 drivers/clocksource/arm_arch_timer.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/clocksource/arm_arch_timer.c +10 -2
index 5163ec13429d..c99afdf12e98 100644
@@ -429,11 +429,19 @@ static void __init arch_counter_register(unsigned type)
 	u64 start_count;
 
 	/* Register the CP15 based counter if we have one */
-	if (type & ARCH_CP15_TIMER)
+	if (type & ARCH_CP15_TIMER) {
 		arch_timer_read_counter = arch_counter_get_cntvct;
-	else
+	} else {
 		arch_timer_read_counter = arch_counter_get_cntvct_mem;
 
+		/* If the clocksource name is "arch_sys_counter" the
+		 * VDSO will attempt to read the CP15-based counter.
+		 * Ensure this does not happen when CP15-based
+		 * counter is not available.
+		 */
+		clocksource_counter.name = "arch_mem_counter";
+	}
+
 	start_count = arch_timer_read_counter();
 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
 	cyclecounter.mult = clocksource_counter.mult;
Signature · 1 line
1.9.3
#2 lore raw

PATCH v7 2/9 clocksource: arm_arch_timer: enable counter access for 32-bit ARM

In reply to Nathan Lynch

The only difference between arm and arm64's implementations of arch_counter_set_user_access is that 32-bit ARM does not enable user access to the virtual counter. We want to enable this access for the 32-bit ARM VDSO, so copy the arm64 version to the driver itself, giving it a slightly different name (arch_counter_set_access) to avoid redefinition.

The arch_timer_evtstrm_enable hooks are also substantially similar, the only difference being a CONFIG_COMPAT-conditional section which is relevant only for arm64. Copy the arm64 version to the driver, again slightly renaming (arch_timer_evtstrm_enable => arch_timer_enable_evtstrm).

With this change, the arch_counter_set_user_access and arch_timer_evtstrm_enable hooks in both arm and arm64 become unused, to be removed in followup patches.

---
 drivers/clocksource/arm_arch_timer.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)
drivers/clocksource/arm_arch_timer.c +34 -2
index c99afdf12e98..0188332ad24b 100644
@@ -23,6 +23,7 @@
 #include <linux/sched_clock.h>
 
 #include <asm/arch_timer.h>
+#include <asm/hwcap.h>
 #include <asm/virt.h>
 
 #include <clocksource/arm_arch_timer.h>
@@ -299,6 +300,20 @@ static void __arch_timer_setup(unsigned type,
 	clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
 }
 
+static void arch_timer_enable_evtstrm(int divider)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
+	/* Set the divider and enable virtual event stream */
+	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
+			| ARCH_TIMER_VIRT_EVT_EN;
+	arch_timer_set_cntkctl(cntkctl);
+	elf_hwcap |= HWCAP_EVTSTRM;
+#ifdef CONFIG_COMPAT
+	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
+#endif
+}
+
 static void arch_timer_configure_evtstream(void)
 {
 	int evt_stream_div, pos;
@@ -309,7 +324,24 @@ static void arch_timer_configure_evtstream(void)
 	if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
 		pos--;
 	/* enable event stream */
-	arch_timer_evtstrm_enable(min(pos, 15));
+	arch_timer_enable_evtstrm(min(pos, 15));
+}
+
+static void arch_counter_set_access(void)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+
+	/* Disable user access to the timers and the physical counter */
+	/* Also disable virtual event stream */
+	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
+			| ARCH_TIMER_USR_VT_ACCESS_EN
+			| ARCH_TIMER_VIRT_EVT_EN
+			| ARCH_TIMER_USR_PCT_ACCESS_EN);
+
+	/* Enable user access to the virtual counter */
+	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+
+	arch_timer_set_cntkctl(cntkctl);
 }
 
 static int arch_timer_setup(struct clock_event_device *clk)
@@ -324,7 +356,7 @@ static int arch_timer_setup(struct clock_event_device *clk)
 			enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
 	}
 
-	arch_counter_set_user_access();
+	arch_counter_set_access();
 	if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
 		arch_timer_configure_evtstream();
 
Signature · 1 line
1.9.3
#3 lore raw

PATCH v7 3/9 ARM: arch_timer: remove unused functions

In reply to Nathan Lynch

The counter access and evtstream configuration are now done in common code, so remove the now-unused arch_counter_set_user_access and arch_timer_evtstrm_enable.

---
 arch/arm/include/asm/arch_timer.h | 25 -------------------------
 1 file changed, 25 deletions(-)
arch/arm/include/asm/arch_timer.h +0 -25
index 0704e0cf5571..92793ba69c40 100644
@@ -99,31 +99,6 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
 	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
 }
 
-static inline void arch_counter_set_user_access(void)
-{
-	u32 cntkctl = arch_timer_get_cntkctl();
-
-	/* Disable user access to both physical/virtual counters/timers */
-	/* Also disable virtual event stream */
-	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
-			| ARCH_TIMER_USR_VT_ACCESS_EN
-			| ARCH_TIMER_VIRT_EVT_EN
-			| ARCH_TIMER_USR_VCT_ACCESS_EN
-			| ARCH_TIMER_USR_PCT_ACCESS_EN);
-	arch_timer_set_cntkctl(cntkctl);
-}
-
-static inline void arch_timer_evtstrm_enable(int divider)
-{
-	u32 cntkctl = arch_timer_get_cntkctl();
-	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
-	/* Set the divider and enable virtual event stream */
-	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
-			| ARCH_TIMER_VIRT_EVT_EN;
-	arch_timer_set_cntkctl(cntkctl);
-	elf_hwcap |= HWCAP_EVTSTRM;
-}
-
 #endif
 
 #endif
Signature · 1 line
1.9.3
#4 lore raw

PATCH v7 4/9 arm64: arch_timer: remove unused functions

In reply to Nathan Lynch

The counter access and evtstream configuration are now done in common code, so remove the now-unused arch_counter_set_user_access and arch_timer_evtstrm_enable.

---
 arch/arm64/include/asm/arch_timer.h | 31 -------------------------------
 1 file changed, 31 deletions(-)
arch/arm64/include/asm/arch_timer.h +0 -31
index 9400596a0f39..f19097134b02 100644
@@ -104,37 +104,6 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
 	asm volatile("msr	cntkctl_el1, %0" : : "r" (cntkctl));
 }
 
-static inline void arch_counter_set_user_access(void)
-{
-	u32 cntkctl = arch_timer_get_cntkctl();
-
-	/* Disable user access to the timers and the physical counter */
-	/* Also disable virtual event stream */
-	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
-			| ARCH_TIMER_USR_VT_ACCESS_EN
-			| ARCH_TIMER_VIRT_EVT_EN
-			| ARCH_TIMER_USR_PCT_ACCESS_EN);
-
-	/* Enable user access to the virtual counter */
-	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
-
-	arch_timer_set_cntkctl(cntkctl);
-}
-
-static inline void arch_timer_evtstrm_enable(int divider)
-{
-	u32 cntkctl = arch_timer_get_cntkctl();
-	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
-	/* Set the divider and enable virtual event stream */
-	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
-			| ARCH_TIMER_VIRT_EVT_EN;
-	arch_timer_set_cntkctl(cntkctl);
-	elf_hwcap |= HWCAP_EVTSTRM;
-#ifdef CONFIG_COMPAT
-	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
-#endif
-}
-
 static inline u64 arch_counter_get_cntvct(void)
 {
 	u64 cval;
Signature · 1 line
1.9.3
#5 lore raw

PATCH v7 5/9 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).

This code will be used for placing the vdso as well, hence the vdso_addr function name and npages argument.

---
 arch/arm/kernel/process.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)
arch/arm/kernel/process.c +32 -1
index 81ef686a91ca..219a0d1d10fc 100644
@@ -477,6 +477,35 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 		 "[sigpage]" : NULL;
 }
 
+static unsigned long vdso_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);
 
@@ -484,6 +513,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long addr;
+	unsigned long hint;
 	int ret;
 
 	if (!signal_page)
@@ -492,7 +522,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 = vdso_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
#6 lore raw

PATCH v7 6/9 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 reporting [vdso] via /proc/pid/maps and communicating AT_SYSINFO_EHDR to the ELF loader.

Add declarations for vma_is_vdso, arm_install_vdso, and !CONFIG_VDSO implementations of same. The CONFIG_VDSO=y implementations of these come later.

Make arch_vma_name recognize a vdso VMA, using vma_is_vdso to return "[vdso]" when appropriate.

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/elf.h           | 11 +++++++
 arch/arm/include/asm/mmu.h           |  3 ++
 arch/arm/include/asm/vdso.h          | 47 ++++++++++++++++++++++++++++
 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/process.c            | 14 +++++++--
 8 files changed, 140 insertions(+), 4 deletions(-)
 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 f5a357601983..0e70f40e04ef 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/elf.h +11 -0
index f4b46d39b9cf..45d2ddff662a 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,15 @@ 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 {										\
+	/* Account for the data page at the beginning of the [vdso] VMA. */	\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,						\
+		    (elf_addr_t)current->mm->context.vdso +			\
+		    sizeof(union vdso_data_store));				\
+} 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 +47 -0

47 lines not on this page · raw message

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
arch/arm/kernel/process.c +11 -3
index 219a0d1d10fc..40445fb71ac9 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>
@@ -472,9 +473,16 @@ 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;
+	if (is_gate_vma(vma))
+		return "[vectors]";
+
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage)
+		return "[sigpage]";
+
+	if (vma_is_vdso(vma))
+		return "[vdso]";
+
+	return NULL;
 }
 
 static unsigned long vdso_addr(const struct mm_struct *mm, unsigned int npages)
Signature · 1 line
1.9.3
#7 lore raw

PATCH v7 6/9 ARM: miscellaneous vdso infrastructure, preparation

arch/arm/include/asm/vdso_datapage.h line 36

Quoted 6 lines · Nathan Lynch
arch/arm/include/asm/vdso_datapage.h new file +6 -0
+struct vdso_data {
+       u32 seq_count;          /* sequence count - odd during updates */
+       u16 use_syscall;        /* whether to fall back to syscalls */
+       u16 cs_shift;           /* clocksource shift */
+       u32 xtime_coarse_sec;   /* coarse time */
+       u32 xtime_coarse_nsec;

Note that we will at some point have to introduce 64-bit time_t in user space in some form. We will have to add new system calls for anything dealing with time on the kernel boundary, but it would be good to be prepared here.

Is vdso_data an ABI-relevant data structure? If so, I think all you need here is to make xtime_coarse_sec a u64 type for now, so we can add the other functions later. The code can of course for now access only the lower half (keeping endianess in mind), so there should not be any performance impact.

If the structure is not part of the ABI, there probably isn't much we can do here.

Arnd

#8 lore raw

PATCH v7 6/9 ARM: miscellaneous vdso infrastructure, preparation

Quoted 12 lines · Arnd Bergmann

arch/arm/include/asm/vdso_datapage.h line 36

Quoted 6 lines · Nathan Lynch
arch/arm/include/asm/vdso_datapage.h new file +6 -0
+struct vdso_data {
+       u32 seq_count;          /* sequence count - odd during updates */
+       u16 use_syscall;        /* whether to fall back to syscalls */
+       u16 cs_shift;           /* clocksource shift */
+       u32 xtime_coarse_sec;   /* coarse time */
+       u32 xtime_coarse_nsec;

Note that we will at some point have to introduce 64-bit time_t in user space in some form. We will have to add new system calls for anything dealing with time on the kernel boundary, but it would be good to be prepared here.

Quoted 7 lines

Is vdso_data an ABI-relevant data structure? If so, I think all you need here is to make xtime_coarse_sec a u64 type for now, so we can add the other functions later. The code can of course for now access only the lower half (keeping endianess in mind), so there should not be any performance impact.

If the structure is not part of the ABI, there probably isn't much we can do here.

In short, no, vdso_data is not ABI-relevant.

The vdso_data structure may be accessed legitimately only through the entry points (gettimeofday, clock_gettime) that the VDSO provides, and it is my intent that we should be able to change the structure as needed, just like other architectures. vdso_data should not show up in any exported header and I'll double-check to make sure it does not.

So, when the time comes, we should be able to change it to accommodate 64-bit time_t by (I imagine) making any field that stores seconds 64 bits and adding new entry points (clock_gettime64 or whatever).

#9 lore raw

PATCH v7 6/9 ARM: miscellaneous vdso infrastructure, preparation

Quoted 29 lines · On Monday 30 June 2014 07:27:59 Nathan Lynch wrote:
Quoted 12 lines · Arnd Bergmann

arch/arm/include/asm/vdso_datapage.h line 36

Quoted 6 lines · Nathan Lynch
arch/arm/include/asm/vdso_datapage.h new file +6 -0
+struct vdso_data {
+       u32 seq_count;          /* sequence count - odd during updates */
+       u16 use_syscall;        /* whether to fall back to syscalls */
+       u16 cs_shift;           /* clocksource shift */
+       u32 xtime_coarse_sec;   /* coarse time */
+       u32 xtime_coarse_nsec;

Note that we will at some point have to introduce 64-bit time_t in user space in some form. We will have to add new system calls for anything dealing with time on the kernel boundary, but it would be good to be prepared here.

Quoted 7 lines

Is vdso_data an ABI-relevant data structure? If so, I think all you need here is to make xtime_coarse_sec a u64 type for now, so we can add the other functions later. The code can of course for now access only the lower half (keeping endianess in mind), so there should not be any performance impact.

If the structure is not part of the ABI, there probably isn't much we can do here.

In short, no, vdso_data is not ABI-relevant.

The vdso_data structure may be accessed legitimately only through the entry points (gettimeofday, clock_gettime) that the VDSO provides, and it is my intent that we should be able to change the structure as needed, just like other architectures. vdso_data should not show up in any exported header and I'll double-check to make sure it does not.

Quoted 3 lines

So, when the time comes, we should be able to change it to accommodate 64-bit time_t by (I imagine) making any field that stores seconds 64 bits and adding new entry points (clock_gettime64 or whatever).

Ok, very good.

Arnd

#10 lore raw

PATCH v7 7/9 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/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 9 files changed, 725 insertions(+)
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c
arch/arm/kernel/asm-offsets.c +5 -0
index 85598b5d1efd..a582bb42dc87 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/kernel/vdso/.gitignore new file +1 -0
new file mode 100644
index 000000000000..f8b69d84238e
@@ -0,0 +1 @@
+vdso.lds
arch/arm/kernel/vdso/Makefile new file +59 -0

59 lines not on this page · raw message

arch/arm/kernel/vdso/checkundef.sh new file +9 -0
new file mode 100755
index 000000000000..185c30da202b
@@ -0,0 +1,9 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+"$nm" -u "$file" | ( ret=0; while read discard symbol
+do
+    echo "$file: undefined symbol $symbol"
+    ret=1
+done ; exit $ret )
+exit $?
arch/arm/kernel/vdso/datapage.S new file +15 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+	.cfi_startproc
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.cfi_endproc
+ENDPROC(__get_datapage)
arch/arm/kernel/vdso/vdso.S new file +35 -0
new file mode 100644
index 000000000000..aed16ff84c5f
@@ -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/kernel/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
arch/arm/kernel/vdso/vdso.lds.S new file +88 -0

88 lines not on this page · raw message

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

193 lines not on this page · raw message

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

320 lines not on this page · raw message

Signature · 1 line
1.9.3
#11 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 45 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.

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/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 9 files changed, 725 insertions(+)
Quoted 8 lines
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c

One change I would like to see (to stop the directory tree getting soo deep) is to move this to arch/arm/vdso - just like x86 is arch/x86/vdso. Was there a pressing reason to have it in arch/arm/kernel ?

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#12 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 55 lines · Russell King - ARM Linux
Quoted 45 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.

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/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 9 files changed, 725 insertions(+)
Quoted 8 lines
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c
Quoted 3 lines

One change I would like to see (to stop the directory tree getting soo deep) is to move this to arch/arm/vdso - just like x86 is arch/x86/vdso. Was there a pressing reason to have it in arch/arm/kernel ?

It also looks like there's something missing for vdso_install to work. arch/x86 has this:

PHONY += vdso_install
vdso_install:

        $(Q)$(MAKE) $(build)=arch/x86/vdso $@

but doesn't list it in the arch help. I'm sure we can do better on ARM. :)

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#13 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 60 lines · Russell King - ARM Linux
Quoted 55 lines · Russell King - ARM Linux
Quoted 45 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.

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/kernel/vdso/.gitignore      |   1 +
  arch/arm/kernel/vdso/Makefile        |  59 +++++++
  arch/arm/kernel/vdso/checkundef.sh   |   9 +
  arch/arm/kernel/vdso/datapage.S      |  15 ++
  arch/arm/kernel/vdso/vdso.S          |  35 ++++
  arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
  arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
  arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
  9 files changed, 725 insertions(+)
Quoted 8 lines

create mode 100644 arch/arm/kernel/vdso/.gitignore create mode 100644 arch/arm/kernel/vdso/Makefile create mode 100755 arch/arm/kernel/vdso/checkundef.sh create mode 100644 arch/arm/kernel/vdso/datapage.S create mode 100644 arch/arm/kernel/vdso/vdso.S create mode 100644 arch/arm/kernel/vdso/vdso.lds.S create mode 100644 arch/arm/kernel/vdso/vdsomunge.c create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c

Quoted 3 lines

One change I would like to see (to stop the directory tree getting soo deep) is to move this to arch/arm/vdso - just like x86 is arch/x86/vdso. Was there a pressing reason to have it in arch/arm/kernel ?

Quoted 8 lines

It also looks like there's something missing for vdso_install to work. arch/x86 has this:

PHONY += vdso_install
vdso_install:

         $(Q)$(MAKE) $(build)=arch/x86/vdso $@

but doesn't list it in the arch help. I'm sure we can do better on ARM. :)

In 3.16-rc3 this is rather improved, albeit still undocumented. It's probably worth matching x86's behavior for gdb's benefit.

--Andy

#14 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Russell King - ARM Linux
Quoted 55 lines · Russell King - ARM Linux
Quoted 45 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.

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/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 9 files changed, 725 insertions(+)
Quoted 8 lines
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c
Quoted 3 lines

One change I would like to see (to stop the directory tree getting soo deep) is to move this to arch/arm/vdso - just like x86 is arch/x86/vdso. Was there a pressing reason to have it in arch/arm/kernel ?

No pressing reason. I think I was just following the example of non-x86 architectures. I can move it to arch/arm/vdso.

#15 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Nathan Lynch
Quoted 9 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.

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.

Okay, how is this used by userspace?

It seems that on ARM, we generate a dso with these symbols:

DYNAMIC SYMBOL TABLE:

000001e4 l    d  .eh_frame_hdr	00000000              .eh_frame_hdr
00000000 g    DO *ABS*	00000000  LINUX_3.17  LINUX_3.17
000003c4 g    DF .text	00000080  LINUX_3.17  __kernel_clock_getres
00000444 g    DF .text	0000002c  LINUX_3.17  __kernel_gettimeofday
00000298 g    DF .text	0000012c  LINUX_3.17  __kernel_clock_gettime

whereas, x86-64 generates this:

DYNAMIC SYMBOL TABLE:

ffffffffff700330 l    d  .eh_frame_hdr	0000000000000000              .eh_frame_hdr
ffffffffff700600  w   DF .text	00000000000002b9  LINUX_2.6   clock_gettime
0000000000000000 g    DO *ABS*	0000000000000000  LINUX_2.6   LINUX_2.6
ffffffffff7008c0 g    DF .text	000000000000015a  LINUX_2.6   __vdso_gettimeofday
ffffffffff700a40 g    DF .text	000000000000003d  LINUX_2.6   __vdso_getcpu
ffffffffff7008c0  w   DF .text	000000000000015a  LINUX_2.6   gettimeofday
ffffffffff700a20  w   DF .text	0000000000000016  LINUX_2.6   time
ffffffffff700a40  w   DF .text	000000000000003d  LINUX_2.6   getcpu
ffffffffff700600 g    DF .text	00000000000002b9  LINUX_2.6   __vdso_clock_gettime
ffffffffff700a20 g    DF .text	0000000000000016  LINUX_2.6   __vdso_time

hence references to gettimeofday automatically get resolved to the vdso version without needing C library updates.

Or... do we need a glibc update to make use of this?

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#16 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 7 lines · Russell King - ARM Linux
Quoted 6 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 5 lines
Quoted 3 lines

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.

Okay, how is this used by userspace?

Primarily it's intended to be transparent to userspace applications; glibc -- with a patch -- detects the VDSO at startup and binds the appropriate routines to the VDSO's.

However, even an unpatched glibc makes the VDSO symbols available for lookup via dlsym, which has been convenient for testing.

Quoted 23 lines

It seems that on ARM, we generate a dso with these symbols:

DYNAMIC SYMBOL TABLE:

000001e4 l    d  .eh_frame_hdr	00000000              .eh_frame_hdr
00000000 g    DO *ABS*	00000000  LINUX_3.17  LINUX_3.17
000003c4 g    DF .text	00000080  LINUX_3.17  __kernel_clock_getres
00000444 g    DF .text	0000002c  LINUX_3.17  __kernel_gettimeofday
00000298 g    DF .text	0000012c  LINUX_3.17  __kernel_clock_gettime

whereas, x86-64 generates this:

DYNAMIC SYMBOL TABLE:

ffffffffff700330 l    d  .eh_frame_hdr	0000000000000000              .eh_frame_hdr
ffffffffff700600  w   DF .text	00000000000002b9  LINUX_2.6   clock_gettime
0000000000000000 g    DO *ABS*	0000000000000000  LINUX_2.6   LINUX_2.6
ffffffffff7008c0 g    DF .text	000000000000015a  LINUX_2.6   __vdso_gettimeofday
ffffffffff700a40 g    DF .text	000000000000003d  LINUX_2.6   __vdso_getcpu
ffffffffff7008c0  w   DF .text	000000000000015a  LINUX_2.6   gettimeofday
ffffffffff700a20  w   DF .text	0000000000000016  LINUX_2.6   time
ffffffffff700a40  w   DF .text	000000000000003d  LINUX_2.6   getcpu
ffffffffff700600 g    DF .text	00000000000002b9  LINUX_2.6   __vdso_clock_gettime
ffffffffff700a20 g    DF .text	0000000000000016  LINUX_2.6   __vdso_time
Quoted 2 lines

hence references to gettimeofday automatically get resolved to the vdso version without needing C library updates.

Hmm, I'm not sure. I had wondered why x86-64's vdso has the aliases (clock_gettime --> __vdso_clock_gettime). Most other architectures' VDSOs don't.

Quoted 1 line

Or... do we need a glibc update to make use of this?

That is the idea, yes. You don't have to rebuild applications but glibc needs to be updated to dispatch its gettimeofday and clock_gettime to the VDSO.

I'm in the process of refreshing and re-testing that patch. I posted an RFC to libc-alpha a few months back:

https://www.sourceware.org/ml/libc-alpha/2014-02/msg00680.html

I should have a new one posted within a couple days.

#17 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 12 lines · Nathan Lynch
Quoted 11 lines · Russell King - ARM Linux
Quoted 9 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.

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.

Quoted 8 lines
Quoted 1 line

Okay, how is this used by userspace?

Primarily it's intended to be transparent to userspace applications; glibc -- with a patch -- detects the VDSO at startup and binds the appropriate routines to the VDSO's.

However, even an unpatched glibc makes the VDSO symbols available for lookup via dlsym, which has been convenient for testing.

It's a shame that the vDSO provided symbols aren't automatically picked up in place of the glibc versions, because it means probably many years before the vDSO seriously gets used.

I know that I'm probably many years away from it, even if Ubuntu adopt it for something recent - I'm rather stuck with 12.04 due to the move towards requiring 3D GPU acceleration in later versions. It seems that the choices on ARM now are to either have a crippled distro through lack of open GPU support, or stick with an old distro that doesn't require GPUs.

Quoted 6 lines
Quoted 2 lines

hence references to gettimeofday automatically get resolved to the vdso version without needing C library updates.

Hmm, I'm not sure. I had wondered why x86-64's vdso has the aliases (clock_gettime --> __vdso_clock_gettime). Most other architectures' VDSOs don't.

Yes, and providing them seems to have no useful benefit either, because they aren't picked up automatically by the linker.

Quoted 5 lines
Quoted 1 line

Or... do we need a glibc update to make use of this?

That is the idea, yes. You don't have to rebuild applications but glibc needs to be updated to dispatch its gettimeofday and clock_gettime to the VDSO.

Yea, many people aren't going to rebuild glibc just because of this, me included. If only there was a way for automatic vdso support.

So, I'm going to have to rely on you to say "yes it works" and to keep an eye on it in the future in case something breaks.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#18 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 26 lines · Russell King - ARM Linux
Quoted 12 lines · Nathan Lynch
Quoted 11 lines · Russell King - ARM Linux
Quoted 9 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.

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.

Quoted 8 lines
Quoted 1 line

Okay, how is this used by userspace?

Primarily it's intended to be transparent to userspace applications; glibc -- with a patch -- detects the VDSO at startup and binds the appropriate routines to the VDSO's.

However, even an unpatched glibc makes the VDSO symbols available for lookup via dlsym, which has been convenient for testing.

It's a shame that the vDSO provided symbols aren't automatically picked up in place of the glibc versions, because it means probably many years before the vDSO seriously gets used.

Quoted 6 lines

I know that I'm probably many years away from it, even if Ubuntu adopt it for something recent - I'm rather stuck with 12.04 due to the move towards requiring 3D GPU acceleration in later versions. It seems that the choices on ARM now are to either have a crippled distro through lack of open GPU support, or stick with an old distro that doesn't require GPUs.

Based on other messages from you on the ML I'm assuming you have an i.MX6 system in mind? (Forgive me if I'm wrong.) On any Cortex-A9 or -A8 the VDSO isn't going to be any great benefit anyway. Those CPUs don't implement the generic timers extension, so only clock_gettime() with low-resolution clock ids will see a speedup. And few programs use those, to my knowledge.

A15, A7, and I'm pretty sure A12 and A17 all implement the timer extension and will see full benefit. Some Qualcomm CPUs too, I think.

Quoted 16 lines
Quoted 6 lines
Quoted 2 lines

hence references to gettimeofday automatically get resolved to the vdso version without needing C library updates.

Hmm, I'm not sure. I had wondered why x86-64's vdso has the aliases (clock_gettime --> __vdso_clock_gettime). Most other architectures' VDSOs don't.

Yes, and providing them seems to have no useful benefit either, because they aren't picked up automatically by the linker.

Quoted 5 lines
Quoted 1 line

Or... do we need a glibc update to make use of this?

That is the idea, yes. You don't have to rebuild applications but glibc needs to be updated to dispatch its gettimeofday and clock_gettime to the VDSO.

Quoted 5 lines

Yea, many people aren't going to rebuild glibc just because of this, me included. If only there was a way for automatic vdso support.

So, I'm going to have to rely on you to say "yes it works" and to keep an eye on it in the future in case something breaks.

Understood. FWIW I would expect the uptake to be a little more rapid in OE and Buildroot-type distributions. The workload I'm interested in accelerating -- high-volume tracing -- should show up any problems pretty quickly and obviously. Not to mention I've got my own set of IMO unforgiving testcases which I'll be running regularly.

I'll wait a couple days to see what Arnd has to say about the generated header issue and plan on posting v8 early-to-mid next week. Thanks.

#19 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 15 lines · Nathan Lynch
Quoted 6 lines · Russell King - ARM Linux

I know that I'm probably many years away from it, even if Ubuntu adopt it for something recent - I'm rather stuck with 12.04 due to the move towards requiring 3D GPU acceleration in later versions. It seems that the choices on ARM now are to either have a crippled distro through lack of open GPU support, or stick with an old distro that doesn't require GPUs.

Based on other messages from you on the ML I'm assuming you have an i.MX6 system in mind? (Forgive me if I'm wrong.) On any Cortex-A9 or -A8 the VDSO isn't going to be any great benefit anyway. Those CPUs don't implement the generic timers extension, so only clock_gettime() with low-resolution clock ids will see a speedup. And few programs use those, to my knowledge.

Quoted 2 lines

A15, A7, and I'm pretty sure A12 and A17 all implement the timer extension and will see full benefit. Some Qualcomm CPUs too, I think.

Here's the results from vdsotest... yes on iMX6 as that's the most advanced bootable system I have:

clock-gettime-monotonic system calls per second: 1601780
clock-gettime-monotonic vdso calls per second: 1600862 (1.00x speedup)
clock-getres-monotonic system calls per second: 3001396
clock-getres-monotonic vdso calls per second: 52163259 (17.38x speedup)
clock-gettime-monotonic-coarse system calls per second: 2824631
clock-gettime-monotonic-coarse vdso calls per second: 13760820 (4.87x speedup)
clock-getres-monotonic-coarse system calls per second: 3166932
clock-getres-monotonic-coarse vdso calls per second: 52111805 (16.45x speedup)
clock-gettime-realtime system calls per second: 1596863
clock-gettime-realtime vdso calls per second: 1590424 (1.00x speedup)
clock-getres-realtime system calls per second: 2993748
clock-getres-realtime vdso calls per second: 52123753 (17.41x speedup)
clock-gettime-realtime-coarse system calls per second: 3007894
clock-gettime-realtime-coarse vdso calls per second: 17081617 (5.68x speedup)
clock-getres-realtime-coarse system calls per second: 3072073
clock-getres-realtime-coarse vdso calls per second: 49401452 (16.08x speedup)
Note: vDSO version of getcpu not found
getcpu system calls per second: 4902323
getcpu vdso calls per second: 4972290 (1.01x speedup)
Note: vDSO version of getcpu not found
Note: vDSO version of getcpu not found
gettimeofday system calls per second: 1637099
gettimeofday vdso calls per second: 1637573 (1.00x speedup)

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#20 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 37 lines · Russell King - ARM Linux
Quoted 15 lines · Nathan Lynch
Quoted 6 lines · Russell King - ARM Linux

I know that I'm probably many years away from it, even if Ubuntu adopt it for something recent - I'm rather stuck with 12.04 due to the move towards requiring 3D GPU acceleration in later versions. It seems that the choices on ARM now are to either have a crippled distro through lack of open GPU support, or stick with an old distro that doesn't require GPUs.

Based on other messages from you on the ML I'm assuming you have an i.MX6 system in mind? (Forgive me if I'm wrong.) On any Cortex-A9 or -A8 the VDSO isn't going to be any great benefit anyway. Those CPUs don't implement the generic timers extension, so only clock_gettime() with low-resolution clock ids will see a speedup. And few programs use those, to my knowledge.

Quoted 2 lines

A15, A7, and I'm pretty sure A12 and A17 all implement the timer extension and will see full benefit. Some Qualcomm CPUs too, I think.

Here's the results from vdsotest... yes on iMX6 as that's the most advanced bootable system I have:

clock-gettime-monotonic system calls per second: 1601780
clock-gettime-monotonic vdso calls per second: 1600862 (1.00x speedup)
clock-getres-monotonic system calls per second: 3001396
clock-getres-monotonic vdso calls per second: 52163259 (17.38x speedup)
clock-gettime-monotonic-coarse system calls per second: 2824631
clock-gettime-monotonic-coarse vdso calls per second: 13760820 (4.87x speedup)
clock-getres-monotonic-coarse system calls per second: 3166932
clock-getres-monotonic-coarse vdso calls per second: 52111805 (16.45x speedup)
clock-gettime-realtime system calls per second: 1596863
clock-gettime-realtime vdso calls per second: 1590424 (1.00x speedup)
clock-getres-realtime system calls per second: 2993748
clock-getres-realtime vdso calls per second: 52123753 (17.41x speedup)
clock-gettime-realtime-coarse system calls per second: 3007894
clock-gettime-realtime-coarse vdso calls per second: 17081617 (5.68x speedup)
clock-getres-realtime-coarse system calls per second: 3072073

Quoted 8 lines

clock-getres-realtime-coarse vdso calls per second: 49401452 (16.08x speedup)
Note: vDSO version of getcpu not found getcpu system calls per second: 4902323
getcpu vdso calls per second: 4972290 (1.01x speedup)
Note: vDSO version of getcpu not found
Note: vDSO version of getcpu not found gettimeofday system calls per second: 1637099
gettimeofday vdso calls per second: 1637573 (1.00x speedup)

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

#21 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 5 lines · Nathan Lynch

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

Here's another issue which cropped up when I ran this patch set through the autobuilder last night - allnoconfig's now fail with:

mm/memory.c: In function 'gate_vma_init':
mm/memory.c:3410:22: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3411:20: error: 'FIXADDR_USER_END' undeclared (first use in this function) mm/memory.c: In function 'in_gate_area_no_mm':
mm/memory.c:3432:15: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3432:46: error: 'FIXADDR_USER_END' undeclared (first use in this function) make[2]: *** [mm/memory.o] Error 1

Any ideas?

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#22 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 10 lines · Russell King - ARM Linux
Quoted 5 lines · Nathan Lynch

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

Here's another issue which cropped up when I ran this patch set through the autobuilder last night - allnoconfig's now fail with:

Quoted 7 lines

mm/memory.c: In function 'gate_vma_init':
mm/memory.c:3410:22: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3411:20: error: 'FIXADDR_USER_END' undeclared (first use in this function) mm/memory.c: In function 'in_gate_area_no_mm':
mm/memory.c:3432:15: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3432:46: error: 'FIXADDR_USER_END' undeclared (first use in this function) make[2]: *** [mm/memory.o] Error 1

arch/arm/include/page.h:
#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
#endif

mm/memory.c:
#if !defined(__HAVE_ARCH_GATE_AREA)

#if defined(AT_SYSINFO_EHDR)
static struct vm_area_struct gate_vma;

static int __init gate_vma_init(void)

{
	gate_vma.vm_mm = NULL;
	gate_vma.vm_start = FIXADDR_USER_START;
	gate_vma.vm_end = FIXADDR_USER_END;

...

The vdso patches add an ARM definition for AT_SYSINFO_EHDR. So when CONFIG_KUSER_HELPERS=n, this code is pulled in now...

Not sure what the fix would be right now. I don't understand why there is this relationship between AT_SYSINFO_EHDR and gate vma code.

#23 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 35 lines · Nathan Lynch
Quoted 10 lines · Russell King - ARM Linux
Quoted 5 lines · Nathan Lynch

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

Here's another issue which cropped up when I ran this patch set through the autobuilder last night - allnoconfig's now fail with:

Quoted 7 lines

mm/memory.c: In function 'gate_vma_init':
mm/memory.c:3410:22: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3411:20: error: 'FIXADDR_USER_END' undeclared (first use in this function) mm/memory.c: In function 'in_gate_area_no_mm':
mm/memory.c:3432:15: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3432:46: error: 'FIXADDR_USER_END' undeclared (first use in this function) make[2]: *** [mm/memory.o] Error 1

arch/arm/include/page.h:
#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
#endif

mm/memory.c:
#if !defined(__HAVE_ARCH_GATE_AREA)

#if defined(AT_SYSINFO_EHDR)
static struct vm_area_struct gate_vma;

static int __init gate_vma_init(void)

{
	gate_vma.vm_mm = NULL;
	gate_vma.vm_start = FIXADDR_USER_START;
	gate_vma.vm_end = FIXADDR_USER_END;
Quoted 7 lines

...

The vdso patches add an ARM definition for AT_SYSINFO_EHDR. So when CONFIG_KUSER_HELPERS=n, this code is pulled in now...

Not sure what the fix would be right now. I don't understand why there is this relationship between AT_SYSINFO_EHDR and gate vma code.

Me neither. It looks like changing those tests for AT_SYSINFO_EHDR to something like __HAVE_GATE_VMA or CONFIG_HAVE_GATE_VMA would be a good step, so we can keep this disabled on ARM. I don't see a need for the gate VMA stuff just because we have a vDSO.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#24 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 41 lines · Russell King - ARM Linux
Quoted 40 lines · Nathan Lynch
Quoted 10 lines · Russell King - ARM Linux
Quoted 5 lines · Nathan Lynch

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

Here's another issue which cropped up when I ran this patch set through the autobuilder last night - allnoconfig's now fail with:

Quoted 7 lines

mm/memory.c: In function 'gate_vma_init':
mm/memory.c:3410:22: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3411:20: error: 'FIXADDR_USER_END' undeclared (first use in this function) mm/memory.c: In function 'in_gate_area_no_mm':
mm/memory.c:3432:15: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3432:46: error: 'FIXADDR_USER_END' undeclared (first use in this function) make[2]: *** [mm/memory.o] Error 1

arch/arm/include/page.h:
#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
#endif

mm/memory.c:
#if !defined(__HAVE_ARCH_GATE_AREA)

#if defined(AT_SYSINFO_EHDR)
static struct vm_area_struct gate_vma;

static int __init gate_vma_init(void)

{
	gate_vma.vm_mm = NULL;
	gate_vma.vm_start = FIXADDR_USER_START;
	gate_vma.vm_end = FIXADDR_USER_END;

...

The vdso patches add an ARM definition for AT_SYSINFO_EHDR. So when CONFIG_KUSER_HELPERS=n, this code is pulled in now...

Quoted 7 lines
Quoted 2 lines

Not sure what the fix would be right now. I don't understand why there is this relationship between AT_SYSINFO_EHDR and gate vma code.

Me neither. It looks like changing those tests for AT_SYSINFO_EHDR to something like __HAVE_GATE_VMA or CONFIG_HAVE_GATE_VMA would be a good step, so we can keep this disabled on ARM. I don't see a need for the gate VMA stuff just because we have a vDSO.

How about the following as an additonal preparatory patch? It's not as good as cleaning up interaction between the core mm and architecture code with respect to the gate vma APIs, but it has the advantage of not blocking the ARM VDSO code.

(sorry if it's mangled, I swear I'm going to stop using this mail client soon)

============

Quoted 1 line

From 4ad05345625d6f6a045ebe5ed355e3a2c2272fd4 Mon Sep 17 00:00:00 2001

From: Nathan Lynch <[email protected]>
Date: Sun, 29 Jun 2014 17:20:46 -0500
Subject: [PATCH] ARM: provide gate vma API stubs when CONFIG_KUSER_HELPERS
disabled

If an architecture defines AT_SYSINFO_EHDR and does not define __HAVE_ARCH_GATE_AREA, code in mm/memory.c (gate_vma_init, get_gate_vma, etc) is enabled which is unbuildable unless the architecure provides FIXADDR_USER_START and FIXADDR_USER_END.

This situation can arise with arch/arm with the introduction of VDSO support, which adds a definition for AT_SYSINFO_EHDR. __HAVE_ARCH_GATE_AREA is conditional on CONFIG_KUSER_HELPERS, so if that config option is disabled, the ARM build fails. We don't want to enable this code on ARM.

Other architectures (arm64, powerpc, s390, tile) define __HAVE_ARCH_GATE_AREA unconditionally, and provide stub implementations of the gate vma APIs. This avoids building the default gate vma code in the core mm, which appears to be useful only for ia64 and user-mode x86.

Make ARM work similarly, except we provide real implementations of the gate APIs when the kuser helper page is enabled. When it's disabled, use stubs like the other architectures. Define __HAVE_ARCH_GATE_AREA unconditionally.

---
 arch/arm/include/asm/page.h |  2 --
 arch/arm/kernel/process.c   | 20 ++++++++++++++++++--
 2 files changed, 18 insertions(+), 4 deletions(-)
arch/arm/include/asm/page.h +0 -2
index 4355f0ec44d6..6363f3d1d505 100644
@@ -142,9 +142,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
-#ifdef CONFIG_KUSER_HELPERS
 #define __HAVE_ARCH_GATE_AREA 1
-#endif
 
 #ifdef CONFIG_ARM_LPAE
 #include <asm/pgtable-3level-types.h>
arch/arm/kernel/process.c +18 -2
index 39b0d68aa068..35f4cb54bb14 100644
@@ -467,9 +467,25 @@ int in_gate_area_no_mm(unsigned long addr)
 	return in_gate_area(NULL, addr);
 }
 #define is_gate_vma(vma)	((vma) == &gate_vma)
-#else
+
+#else /* !CONFIG_KUSER_HELPERS */
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
 #define is_gate_vma(vma)	0
-#endif
+#endif /* CONFIG_KUSER_HELPERS */
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
Signature · 1 line
1.9.3
#25 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Russell King - ARM Linux
Quoted 41 lines · Russell King - ARM Linux
Quoted 40 lines · Nathan Lynch
Quoted 10 lines · Russell King - ARM Linux
Quoted 5 lines · Nathan Lynch

That's consistent with my results on iMX6. The reported 1.00x "speedup" for clock-gettime-monotonic etc indicates the VDSO is falling back to syscall.

Thanks for testing.

Here's another issue which cropped up when I ran this patch set through the autobuilder last night - allnoconfig's now fail with:

Quoted 7 lines

mm/memory.c: In function 'gate_vma_init':
mm/memory.c:3410:22: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3411:20: error: 'FIXADDR_USER_END' undeclared (first use in this function) mm/memory.c: In function 'in_gate_area_no_mm':
mm/memory.c:3432:15: error: 'FIXADDR_USER_START' undeclared (first use in this function) mm/memory.c:3432:46: error: 'FIXADDR_USER_END' undeclared (first use in this function) make[2]: *** [mm/memory.o] Error 1

arch/arm/include/page.h:
#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
#endif

mm/memory.c:
#if !defined(__HAVE_ARCH_GATE_AREA)

#if defined(AT_SYSINFO_EHDR)
static struct vm_area_struct gate_vma;

static int __init gate_vma_init(void)

{
	gate_vma.vm_mm = NULL;
	gate_vma.vm_start = FIXADDR_USER_START;
	gate_vma.vm_end = FIXADDR_USER_END;

...

The vdso patches add an ARM definition for AT_SYSINFO_EHDR. So when CONFIG_KUSER_HELPERS=n, this code is pulled in now...

Quoted 8 lines
Quoted 2 lines

Not sure what the fix would be right now. I don't understand why there is this relationship between AT_SYSINFO_EHDR and gate vma code.

Me neither. It looks like changing those tests for AT_SYSINFO_EHDR to something like __HAVE_GATE_VMA or CONFIG_HAVE_GATE_VMA would be a good step, so we can keep this disabled on ARM. I don't see a need for the gate VMA stuff just because we have a vDSO.

The code you're running into is mostly bogus. I'm planning on resending a real fix in about five minutes. I'll see if I can get hpa to pick it up in a couple days (or to tell me whos tree it should live in).

I'd actually prefer if you rebase on top of it, because otherwise I'll have to undo whatever hack you add.

--Andy

#26 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Russell King - ARM Linux
Quoted 13 lines · Russell King - ARM Linux
Quoted 9 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.

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.

Okay, how is this used by userspace?

Quoted 8 lines

It seems that on ARM, we generate a dso with these symbols:

DYNAMIC SYMBOL TABLE:

000001e4 l    d  .eh_frame_hdr	00000000              .eh_frame_hdr
00000000 g    DO *ABS*	00000000  LINUX_3.17  LINUX_3.17
000003c4 g    DF .text	00000080  LINUX_3.17  __kernel_clock_getres
00000444 g    DF .text	0000002c  LINUX_3.17  __kernel_gettimeofday
00000298 g    DF .text	0000012c  LINUX_3.17  __kernel_clock_gettime

Sorry, late to the thread.

I think that, if your function signatures match, you should give them the same names and versions as for x86 (i.e. LINUX_2.6, __vdso_clock_gettime). Userspace will thank you.

Don't do the weak clock_gettime, etc aliases, though. That was never a good idea to begin with.

--Andy

#27 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 23 lines · Andy Lutomirski
Quoted 13 lines · Russell King - ARM Linux
Quoted 9 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.

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.

Okay, how is this used by userspace?

Quoted 8 lines

It seems that on ARM, we generate a dso with these symbols:

DYNAMIC SYMBOL TABLE:

000001e4 l    d  .eh_frame_hdr    00000000              .eh_frame_hdr
00000000 g    DO *ABS*    00000000  LINUX_3.17  LINUX_3.17
000003c4 g    DF .text    00000080  LINUX_3.17  __kernel_clock_getres
00000444 g    DF .text    0000002c  LINUX_3.17  __kernel_gettimeofday
00000298 g    DF .text    0000012c  LINUX_3.17  __kernel_clock_gettime
Quoted 5 lines

Sorry, late to the thread.

I think that, if your function signatures match, you should give them the same names and versions as for x86 (i.e. LINUX_2.6, __vdso_clock_gettime). Userspace will thank you.

I don't care strongly about it, but I was following arm64's example with the naming, and I thought the version should match the Linux version in which the VDSO symbols were introduced. I can see that about half the vdso-providing architectures (e.g. arm64, powerpc, s390) follow that version convention instead of using LINUX_2.6. However, looking through git history I see that when people add new symbols to their VDSOs they don't mark them with the current Linux version -- for example, when powerpc added getcpu -- so I'm left thinking the version is not that meaningful.

In other words, I'm inclined to make the changes you suggest, unless someone knows why I shouldn't.

Quoted 2 lines

Don't do the weak clock_gettime, etc aliases, though. That was never a good idea to begin with.

OK, that was my suspicion, thanks for confirming.

#28 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Nathan Lynch
Quoted 42 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.

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/vdso/Makefile new file +1 -0
new file mode 100644
index 000000000000..ceb712a7626c
@@ -0,0 +1,59 @@
+hostprogs-y := vdsomunge

arch/arm/kernel/vdso/Makefile line 11

Quoted 10 lines
arch/arm/kernel/vdso/Makefile new file +10 -0
+
+obj-vdso := vgettimeofday.o datapage.o
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fPIC -fno-common -fno-builtin -fno-stack-protector
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)

Does this need -DDISABLE_BRANCH_PROFILING?

Quoted 6 lines
arch/arm/kernel/vdso/checkundef.sh new file +0 -0
new file mode 100755
index 000000000000..185c30da202b

arch/arm/kernel/vdso/checkundef.sh line 9

Quoted 9 lines
arch/arm/kernel/vdso/checkundef.sh new file +9 -0
@@ -0,0 +1,9 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+"$nm" -u "$file" | ( ret=0; while read discard symbol
+do
+    echo "$file: undefined symbol $symbol"
+    ret=1
+done ; exit $ret )
+exit $?

This is just as buggy as the x86 version. make;make malfunctions.

Can you rely on a new enough toolchain to use -Wl,--no-undefined?

Quoted 11 lines
arch/arm/kernel/vdso/datapage.S new file +5 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -0,0 +1,15 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+
+	.align 2
+.L_vdso_data_ptr:

arch/arm/kernel/vdso/datapage.S line 15

Quoted 10 lines
arch/arm/kernel/vdso/datapage.S new file +10 -0
+	.long	_start - . - VDSO_DATA_SIZE
+
+ENTRY(__get_datapage)
+	.cfi_startproc
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

Quoted 19 lines
arch/arm/kernel/vdso/datapage.S new file +19 -0
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define HOST_ORDER ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define HOST_ORDER ELFDATA2MSB
+#endif
+
+static const char *outfile;
+
+static void cleanup(void)
+{
+	if (error_message_count > 0 && outfile != NULL)
+		unlink(outfile);
+}
+
+static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
+{
+	return swap ? bswap_32(word) : word;
+}

arch/arm/kernel/vdso/datapage.S

Quoted 10 lines
arch/arm/kernel/vdso/datapage.S new file +10 -0
+
+static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
+{
+	return swap ? bswap_16(half) : half;
+}
+
+static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
+{
+	*dst = swap ? bswap_32(val) : val;
+}

The macros in arch/x86/vdso/vdso2c.c are IMO much nicer.

--Andy

#29 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 16 lines · Andy Lutomirski
Quoted 15 lines · Nathan Lynch
arch/arm/kernel/vdso/datapage.S new file +9 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+	.cfi_startproc
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S line 15

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

Also, I'm not sure .cfi directives are the right things to use for AArch32. ARM has special .fnstart, .fnend, .movsp diretives for its own unwind format.

Maybe GDB works with both -- have you tried unwinding out of this with anything?

Will

#30 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 26 lines · Will Deacon
Quoted 16 lines · Andy Lutomirski
Quoted 15 lines · Nathan Lynch
arch/arm/kernel/vdso/datapage.S new file +9 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+	.cfi_startproc
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S line 15

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

Quoted 6 lines

Also, I'm not sure .cfi directives are the right things to use for AArch32. ARM has special .fnstart, .fnend, .movsp diretives for its own unwind format.

Maybe GDB works with both -- have you tried unwinding out of this with anything?

Not since it stopped crashing, which was months ago :-)

I think it worked with GDB 7.5 at least.

I'll revisit this.

#31 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 31 lines · Nathan Lynch
Quoted 30 lines · Will Deacon
Quoted 16 lines · Andy Lutomirski
Quoted 15 lines · Nathan Lynch
arch/arm/kernel/vdso/datapage.S new file +9 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+   .cfi_startproc
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S line 15

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+   adr     r0, .L_vdso_data_ptr
+   ldr     r1, [r0]
+   add     r0, r0, r1
+   bx      lr
+   .cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

Also, I'm not sure .cfi directives are the right things to use for AArch32. ARM has special .fnstart, .fnend, .movsp diretives for its own unwind format.

Quoted 6 lines
Quoted 2 lines

Maybe GDB works with both -- have you tried unwinding out of this with anything?

Not since it stopped crashing, which was months ago :-)

I think it worked with GDB 7.5 at least.

Keep in mind that gdb might not be noticing your unwind information at all, and it might be unwinding correctly by dumb luck.

FWIW, on all x86 targets, -fPIC and a symbol in the linker script do exactly the right thing. Well, almost: x86_32 doesn't have real PC-relative addressing, so gcc ends up storing the GOT address in a register instead of the actual target in a register, but that doesn't seem to make a big difference. Maybe ARM can get away with the same thing.

--Andy

#32 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

In reply to Andy Lutomirski
Quoted 11 lines · Andy Lutomirski

arch/arm/kernel/vdso/Makefile line 11

Quoted 8 lines · Nathan Lynch
arch/arm/kernel/vdso/Makefile new file +8 -0
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fPIC -fno-common -fno-builtin -fno-stack-protector
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)

Does this need -DDISABLE_BRANCH_PROFILING?

Yes, thanks.

Quoted 18 lines
Quoted 6 lines
arch/arm/kernel/vdso/checkundef.sh new file +0 -0
new file mode 100755
index 000000000000..185c30da202b

arch/arm/kernel/vdso/checkundef.sh line 9

Quoted 9 lines
arch/arm/kernel/vdso/checkundef.sh new file +9 -0
@@ -0,0 +1,9 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+"$nm" -u "$file" | ( ret=0; while read discard symbol
+do
+    echo "$file: undefined symbol $symbol"
+    ret=1
+done ; exit $ret )
+exit $?

This is just as buggy as the x86 version. make;make malfunctions.

Quoted 1 line

Can you rely on a new enough toolchain to use -Wl,--no-undefined?

Looks like relying on --no-undefined should be okay.

Quoted 15 lines
Quoted 15 lines
arch/arm/kernel/vdso/datapage.S new file +9 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+	.cfi_startproc
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S line 15

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+	adr	r0, .L_vdso_data_ptr
+	ldr	r1, [r0]
+	add	r0, r0, r1
+	bx	lr
+	.cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

It's a PC-relative load of the data page. If someone knows how to make this happen in the C portion of the vdso, it would might get us a little speedup.

Quoted 22 lines
Quoted 22 lines
arch/arm/kernel/vdso/datapage.S new file +22 -0
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define HOST_ORDER ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define HOST_ORDER ELFDATA2MSB
+#endif
+
+static const char *outfile;
+
+static void cleanup(void)
+{
+	if (error_message_count > 0 && outfile != NULL)
+		unlink(outfile);
+}
+
+static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
+{
+	return swap ? bswap_32(word) : word;
+}
+
+static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
+{
+	return swap ? bswap_16(half) : half;
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+}
+
+static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
+{
+	*dst = swap ? bswap_32(val) : val;
+}

The macros in arch/x86/vdso/vdso2c.c are IMO much nicer.

Respectfully, I think I'd disagree, but more importantly, vdso2c.c seems to assume a little-endian target.

#33 lore raw

PATCH v7 7/9 ARM: add vdso user-space code

Quoted 99 lines · Nathan Lynch
Quoted 11 lines · Andy Lutomirski

arch/arm/kernel/vdso/Makefile line 11

Quoted 8 lines · Nathan Lynch
arch/arm/kernel/vdso/Makefile new file +8 -0
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fPIC -fno-common -fno-builtin -fno-stack-protector
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+            $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)

Does this need -DDISABLE_BRANCH_PROFILING?

Yes, thanks.

Quoted 18 lines
Quoted 6 lines
arch/arm/kernel/vdso/checkundef.sh new file +0 -0
new file mode 100755
index 000000000000..185c30da202b

arch/arm/kernel/vdso/checkundef.sh line 9

Quoted 9 lines
arch/arm/kernel/vdso/checkundef.sh new file +9 -0
@@ -0,0 +1,9 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+"$nm" -u "$file" | ( ret=0; while read discard symbol
+do
+    echo "$file: undefined symbol $symbol"
+    ret=1
+done ; exit $ret )
+exit $?

This is just as buggy as the x86 version. make;make malfunctions.

Quoted 1 line

Can you rely on a new enough toolchain to use -Wl,--no-undefined?

Looks like relying on --no-undefined should be okay.

Quoted 15 lines
Quoted 15 lines
arch/arm/kernel/vdso/datapage.S new file +9 -0
new file mode 100644
index 000000000000..fbf36d75da06
@@ -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)
+    .cfi_startproc
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S line 15

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+    adr     r0, .L_vdso_data_ptr
+    ldr     r1, [r0]
+    add     r0, r0, r1
+    bx      lr
+    .cfi_endproc
+ENDPROC(__get_datapage)

Can you translate this into English for the non-ARM-speakers here?

It's a PC-relative load of the data page. If someone knows how to make this happen in the C portion of the vdso, it would might get us a little speedup.

Quoted 22 lines
Quoted 22 lines
arch/arm/kernel/vdso/datapage.S new file +22 -0
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define HOST_ORDER ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define HOST_ORDER ELFDATA2MSB
+#endif
+
+static const char *outfile;
+
+static void cleanup(void)
+{
+    if (error_message_count > 0 && outfile != NULL)
+            unlink(outfile);
+}
+
+static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
+{
+    return swap ? bswap_32(word) : word;
+}
+
+static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
+{
+    return swap ? bswap_16(half) : half;
Quoted 8 lines

arch/arm/kernel/vdso/datapage.S

Quoted 6 lines
arch/arm/kernel/vdso/datapage.S new file +6 -0
+}
+
+static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
+{
+    *dst = swap ? bswap_32(val) : val;
+}

The macros in arch/x86/vdso/vdso2c.c are IMO much nicer.

Quoted 3 lines

Respectfully, I think I'd disagree, but more importantly, vdso2c.c seems to assume a little-endian target.

That would be easy enough to fix.

The real reason that I went with the macroized approach is that x86 needs to support 32-bit and 64-bit targets with the same host code. ELF has lots of odd types, and using the macros means that I can't screw up the width of the integer that I'm converting.

--Andy

#34 lore raw

PATCH v7 8/9 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 |  13 +++-
 arch/arm/kernel/vdso.c    | 168 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/kernel/vdso.c
arch/arm/kernel/process.c +11 -2
index 40445fb71ac9..39b0d68aa068 100644
@@ -520,6 +520,7 @@ extern struct page *get_signal_page(void);
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
+	unsigned long npages;
 	unsigned long addr;
 	unsigned long hint;
 	int ret;
@@ -529,9 +530,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (!signal_page)
 		return -ENOMEM;
 
+	npages = (vdso_mapping_len >> PAGE_SHIFT) + 1;
+
 	down_write(&mm->mmap_sem);
-	hint = vdso_addr(mm, 1);
-	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
+	hint = vdso_addr(mm, npages);
+	addr = get_unmapped_area(NULL, hint, npages, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
@@ -544,6 +547,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (ret == 0)
 		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 +168 -0

168 lines not on this page · raw message

Signature · 1 line
1.9.3
#35 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 145 lines · 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 |  13 +++-
 arch/arm/kernel/vdso.c    | 168 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/kernel/vdso.c
arch/arm/kernel/process.c +11 -2
index 40445fb71ac9..39b0d68aa068 100644
@@ -520,6 +520,7 @@ extern struct page *get_signal_page(void);
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
+	unsigned long npages;
 	unsigned long addr;
 	unsigned long hint;
 	int ret;
@@ -529,9 +530,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (!signal_page)
 		return -ENOMEM;
 
+	npages = (vdso_mapping_len >> PAGE_SHIFT) + 1;
+
 	down_write(&mm->mmap_sem);
-	hint = vdso_addr(mm, 1);
-	addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
+	hint = vdso_addr(mm, npages);
+	addr = get_unmapped_area(NULL, hint, npages, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
@@ -544,6 +547,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (ret == 0)
 		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 +85 -0
new file mode 100644
index 000000000000..0cfd25f09adf
@@ -0,0 +1,168 @@
+/*
+ * 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/>.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
+#include <linux/vmalloc.h>
+
+#include <asm/barrier.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+#include <asm/vdso_datapage.h>
+
+static struct page **vdso_pagelist;
+
+unsigned long vdso_mapping_len __read_mostly;
+
+/*
+ * The vDSO data page.
+ */
+static union vdso_data_store vdso_data_store __page_aligned_data;
+static struct vdso_data *vdso_data = &vdso_data_store.data;
+
+static int __init vdso_init(void)
+{
+	unsigned long vdso_pages;
+	int i;
+
+	if (memcmp(&vdso_start, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		return -ENOEXEC;
+	}
+
+	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	pr_debug("vdso: %ld code pages at base %p\n", vdso_pages, &vdso_start);
+
+	/* Allocate the vDSO pagelist, plus a page for the data. */
+	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
+				GFP_KERNEL);
+	if (vdso_pagelist == NULL)
+		return -ENOMEM;
+
+	/* Grab the vDSO data page. */
+	vdso_pagelist[0] = virt_to_page(vdso_data);
+
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++)
+		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+
+	/* Precompute the mapping size */
+	vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+
+	return 0;
+}
+arch_initcall(vdso_init);
+
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+	int ret;
+
+	mm->context.vdso = ~0UL;
+
+	if (vdso_pagelist == NULL)
+		return;
+
+	/*

arch/arm/kernel/vdso.c line 95

Quoted 10 lines
arch/arm/kernel/vdso.c new file +10 -0
+	 * Put vDSO base into mm struct before calling
+	 * install_special_mapping so the perf counter mmap tracking
+	 * code will recognise it as a vDSO.
+	 */
+	mm->context.vdso = addr;
+
+	ret = install_special_mapping(mm, addr, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it. You also seem to be sticking it *before* the vdso in the same vma. This will severely piss off all the tools that assume that "[vdso]" points to an ELF object.

x86 calls this thing "[vvar]" and sticks it after the vdso. You might not want to have the complexity of sticking it after the vdso (it's distinctly nontrivial), but I see nothing wrong with giving it its own vma just before the vdso. The new _install_special_mapping function makes it considerably easier to do.

(Don't use any version of x86's code before 3.16-rc3 as a reference.)

--Andy

#36 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 8 lines · Andy Lutomirski
Quoted 7 lines · 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.

[...]

Quoted 16 lines
Quoted 16 lines
arch/arm/kernel/vdso.c new file +16 -0
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+	int ret;
+
+	mm->context.vdso = ~0UL;
+
+	if (vdso_pagelist == NULL)
+		return;
+
+	/*
+	 * Put vDSO base into mm struct before calling
+	 * install_special_mapping so the perf counter mmap tracking
+	 * code will recognise it as a vDSO.
+	 */
+	mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+	ret = install_special_mapping(mm, addr, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

Hmm, but how else can we support software breakpoints on the vdso?

Will

#37 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 37 lines · Will Deacon
Quoted 8 lines · Andy Lutomirski
Quoted 7 lines · 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.

[...]

Quoted 16 lines
Quoted 16 lines
arch/arm/kernel/vdso.c new file +16 -0
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+	int ret;
+
+	mm->context.vdso = ~0UL;
+
+	if (vdso_pagelist == NULL)
+		return;
+
+	/*
+	 * Put vDSO base into mm struct before calling
+	 * install_special_mapping so the perf counter mmap tracking
+	 * code will recognise it as a vDSO.
+	 */
+	mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+	ret = install_special_mapping(mm, addr, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

Quoted 1 line

Hmm, but how else can we support software breakpoints on the vdso?

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

#38 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 38 lines · Nathan Lynch
Quoted 37 lines · Will Deacon
Quoted 8 lines · Andy Lutomirski
Quoted 7 lines · 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.

[...]

Quoted 24 lines
Quoted 11 lines
arch/arm/kernel/vdso.c new file +11 -0
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+	int ret;
+
+	mm->context.vdso = ~0UL;
+
+	if (vdso_pagelist == NULL)
+		return;
+
+	/*

arch/arm/kernel/vdso.c line 95

Quoted 10 lines
arch/arm/kernel/vdso.c new file +10 -0
+	 * Put vDSO base into mm struct before calling
+	 * install_special_mapping so the perf counter mmap tracking
+	 * code will recognise it as a vDSO.
+	 */
+	mm->context.vdso = addr;
+
+	ret = install_special_mapping(mm, addr, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

Quoted 6 lines
Quoted 1 line

Hmm, but how else can we support software breakpoints on the vdso?

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

Ah, yes. That makes a lot of sense for the data page -- we should do something similar on arm64 too, since the CoW will break everything for the task being debugged. We could also drop the EXEC flags too.

Thanks for the explanation,

Will

#39 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 41 lines · Will Deacon
Quoted 40 lines · Nathan Lynch
Quoted 38 lines · Will Deacon
Quoted 8 lines · Andy Lutomirski
Quoted 7 lines · 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.

[...]

Quoted 16 lines
Quoted 16 lines
arch/arm/kernel/vdso.c new file +16 -0
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+ int ret;
+
+ mm->context.vdso = ~0UL;
+
+ if (vdso_pagelist == NULL)
+         return;
+
+ /*
+  * Put vDSO base into mm struct before calling
+  * install_special_mapping so the perf counter mmap tracking
+  * code will recognise it as a vDSO.
+  */
+ mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+ ret = install_special_mapping(mm, addr, vdso_mapping_len,
+                               VM_READ|VM_EXEC|
+                               VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+                               vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

Hmm, but how else can we support software breakpoints on the vdso?

Quoted 8 lines
Quoted 4 lines

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

Ah, yes. That makes a lot of sense for the data page -- we should do something similar on arm64 too, since the CoW will break everything for the task being debugged. We could also drop the EXEC flags too.

If you do this, I have a slight preference for the new vma being called "[vvar]" to match x86. It'll make the CRIU people happy if and when they port it to ARM.

--Andy

#40 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 47 lines · Andy Lutomirski
Quoted 46 lines · Will Deacon
Quoted 44 lines · Nathan Lynch
Quoted 37 lines · Will Deacon
Quoted 8 lines · Andy Lutomirski
Quoted 7 lines · 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.

[...]

Quoted 16 lines
Quoted 16 lines
arch/arm/kernel/vdso.c new file +16 -0
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+ int ret;
+
+ mm->context.vdso = ~0UL;
+
+ if (vdso_pagelist == NULL)
+         return;
+
+ /*
+  * Put vDSO base into mm struct before calling
+  * install_special_mapping so the perf counter mmap tracking
+  * code will recognise it as a vDSO.
+  */
+ mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+ ret = install_special_mapping(mm, addr, vdso_mapping_len,
+                               VM_READ|VM_EXEC|
+                               VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+                               vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

Quoted 1 line

Hmm, but how else can we support software breakpoints on the vdso?

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

Quoted 7 lines
Quoted 3 lines

Ah, yes. That makes a lot of sense for the data page -- we should do something similar on arm64 too, since the CoW will break everything for the task being debugged. We could also drop the EXEC flags too.

If you do this, I have a slight preference for the new vma being called "[vvar]" to match x86. It'll make the CRIU people happy if and when they port it to ARM.

CRIU is functional on AArch32 and AArch64. I use norandmaps and identical kernels so I've not needed explicit VDSO support (on A64), but it'd certainly be nice for whoever does need it for things to be as much the same as possible. Here is some description of it:

http://git.criu.org/?p=criu.git;a=commit;h=fe7b8aeb8c65e11e190282aae8db2d2bebd4f6e9

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.
#41 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

In reply to Andy Lutomirski

Hi Andy,

Quoted 7 lines · Andy Lutomirski
Quoted 6 lines · Will Deacon
Quoted 4 lines · Nathan Lynch

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

Quoted 7 lines
Quoted 3 lines

Ah, yes. That makes a lot of sense for the data page -- we should do something similar on arm64 too, since the CoW will break everything for the task being debugged. We could also drop the EXEC flags too.

If you do this, I have a slight preference for the new vma being called "[vvar]" to match x86. It'll make the CRIU people happy if and when they port it to ARM.

I quickly hacked something (see below) and now I see the following in /proc/$$/maps:

7fa1574000-7fa1575000 r-xp 00000000 00:00 0 [vdso]
7fa1575000-7fa1576000 r--p 00000000 00:00 0 [vvar]

Is that what you're after?

Will

--->8

arch/arm64/kernel/vdso.c +26 -8
index 50384fec56c4..84cafbc3eb54 100644
@@ -138,11 +138,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 				int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long vdso_base, vdso_mapping_len;
+	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
 	int ret;
 
+	vdso_text_len = vdso_pages << PAGE_SHIFT;
 	/* Be sure to map the data page */
-	vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
 
 	down_write(&mm->mmap_sem);
 	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
@@ -152,35 +153,52 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	}
 	mm->context.vdso = (void *)vdso_base;
 
-	ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
+	ret = install_special_mapping(mm, vdso_base, vdso_text_len,
 				      VM_READ|VM_EXEC|
 				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
 				      vdso_pagelist);
-	if (ret) {
-		mm->context.vdso = NULL;
+	if (ret)
+		goto up_fail;
+
+	vdso_base += vdso_text_len;
+	ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+				      VM_READ|VM_MAYREAD,
+				      vdso_pagelist + vdso_pages);
+	if (ret)
 		goto up_fail;
-	}
 
-up_fail:
 	up_write(&mm->mmap_sem);
+	return 0;
 
+up_fail:
+	mm->context.vdso = NULL;
+	up_write(&mm->mmap_sem);
 	return ret;
 }
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
+	unsigned long vdso_text;
+
+	if (!vma->vm_mm)
+		return NULL;
+
+	vdso_text = (unsigned long)vma->vm_mm->context.vdso;
+
 	/*
 	 * We can re-use the vdso pointer in mm_context_t for identifying
 	 * the vectors page for compat applications. The vDSO will always
 	 * sit above TASK_UNMAPPED_BASE and so we don't need to worry about
 	 * it conflicting with the vectors base.
 	 */
-	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) {
+	if (vma->vm_start == vdso_text) {
 #ifdef CONFIG_COMPAT
 		if (vma->vm_start == AARCH32_VECTORS_BASE)
 			return "[vectors]";
 #endif
 		return "[vdso]";
+	} else if (vma->vm_start == (vdso_text + (vdso_pages << PAGE_SHIFT))) {
+		return "[vvar]";
 	}
 
 	return NULL;
#42 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 18 lines · Will Deacon

Hi Andy,

Quoted 7 lines · Andy Lutomirski
Quoted 6 lines · Will Deacon
Quoted 4 lines · Nathan Lynch

I believe Andy is suggesting separate VMAs (with different VM flags) for the VDSO's data and code. So, breakpoints in code would work, but attempts to modify the data page via ptrace() would fail outright instead of silently COWing.

Quoted 7 lines
Quoted 3 lines

Ah, yes. That makes a lot of sense for the data page -- we should do something similar on arm64 too, since the CoW will break everything for the task being debugged. We could also drop the EXEC flags too.

If you do this, I have a slight preference for the new vma being called "[vvar]" to match x86. It'll make the CRIU people happy if and when they port it to ARM.

Quoted 7 lines

I quickly hacked something (see below) and now I see the following in /proc/$$/maps:

7fa1574000-7fa1575000 r-xp 00000000 00:00 0 [vdso]
7fa1575000-7fa1576000 r--p 00000000 00:00 0 [vvar]

Is that what you're after?

Yes, with caveats.

Caveat 1: (minor) if you use _install_special_mapping, then you'll fix an mremap bug and most of arch_vma_name can go away.

Caveat 2: (major) I'm kind of surprised that this, or the current code, works reliably. You're doing something that I tried briefly for x86_64:

        _end = .;
        PROVIDE(end = .);

        . = ALIGN(PAGE_SIZE);
        PROVIDE(_vdso_data = .);

This sounds great, except that you're assuming that vdso_end - vdso_start == ALIGN(_end, PAGE_SIZE) - (vdso base address).

If you *fully* strip the vdso (eu-strip --strip-sections), then this is true: eu-strip --strip-sections outputs just the PT_LOAD piece of the vdso. But any binutils-generated incompletely stripped ELF image contains a section table and possible non-allocatable sections at the end. If these exceed the amount of unused space in the last PT_LOAD page, then they'll spill into the next page, and _vdso_data in the vdso will no longer match the address at which vdso.c loads it. Boom!

I bet you're getting away with this because the whole arm64 vdso seems to be written in assembly, so it seems extremely unlikely to exceed one page minus a few hundred bytes. But if you start adding complexity, you might get unlucky.

The x86_32 solution in v3.15 was to simply reverse the order: stick the data page before the vdso instead of after it. This seems to work fine.

The x86 (all variants) solution in v3.16-rc1 was to fully strip the vdso. This broke gdb (and Go, but you won't have that particular problem on ARM). In v3.16-rc3, we're using a hack that moves the section table into an actual allocated section -- this works, and if the kernel builds then it's guaranteed to work, but I'm now fighting with weird output from various binutils versions, and at least one version of binutils can't build 3.16-rc3 for x86_64.

Anyway, all solutions are messy, but the arm64 one has the particular disadvantage of failing silently. I think I just got lucky on x86_64 in that I happened to trigger the failure myself before I ever sent out the patches.

--Andy

#43 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 21 lines · Andy Lutomirski

Caveat 2: (major) I'm kind of surprised that this, or the current code, works reliably. You're doing something that I tried briefly for x86_64:

        _end = .;
        PROVIDE(end = .);

        . = ALIGN(PAGE_SIZE);
        PROVIDE(_vdso_data = .);

This sounds great, except that you're assuming that vdso_end - vdso_start == ALIGN(_end, PAGE_SIZE) - (vdso base address).

If you *fully* strip the vdso (eu-strip --strip-sections), then this is true: eu-strip --strip-sections outputs just the PT_LOAD piece of the vdso. But any binutils-generated incompletely stripped ELF image contains a section table and possible non-allocatable sections at the end. If these exceed the amount of unused space in the last PT_LOAD page, then they'll spill into the next page, and _vdso_data in the vdso will no longer match the address at which vdso.c loads it. Boom!

Quoted 4 lines

I bet you're getting away with this because the whole arm64 vdso seems to be written in assembly, so it seems extremely unlikely to exceed one page minus a few hundred bytes. But if you start adding complexity, you might get unlucky.

This is why I switched (in v5) the proposed 32-bit ARM VDSO to place the data page before the code -- adding -frecord-gcc-switches to the compiler flags was enough to break it.

I meant to call Will's attention to it at the time for arm64's sake, but I guess it slipped my mind... sorry.

#44 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 27 lines · Nathan Lynch
Quoted 21 lines · Andy Lutomirski

Caveat 2: (major) I'm kind of surprised that this, or the current code, works reliably. You're doing something that I tried briefly for x86_64:

        _end = .;
        PROVIDE(end = .);

        . = ALIGN(PAGE_SIZE);
        PROVIDE(_vdso_data = .);

This sounds great, except that you're assuming that vdso_end - vdso_start == ALIGN(_end, PAGE_SIZE) - (vdso base address).

If you *fully* strip the vdso (eu-strip --strip-sections), then this is true: eu-strip --strip-sections outputs just the PT_LOAD piece of the vdso. But any binutils-generated incompletely stripped ELF image contains a section table and possible non-allocatable sections at the end. If these exceed the amount of unused space in the last PT_LOAD page, then they'll spill into the next page, and _vdso_data in the vdso will no longer match the address at which vdso.c loads it. Boom!

Quoted 4 lines

I bet you're getting away with this because the whole arm64 vdso seems to be written in assembly, so it seems extremely unlikely to exceed one page minus a few hundred bytes. But if you start adding complexity, you might get unlucky.

Quoted 6 lines

This is why I switched (in v5) the proposed 32-bit ARM VDSO to place the data page before the code -- adding -frecord-gcc-switches to the compiler flags was enough to break it.

I meant to call Will's attention to it at the time for arm64's sake, but I guess it slipped my mind... sorry.

Hmm, so I could definitely look at doing the same thing, but I don't know if we actually need to for arm64. As Andy points out, we're written entirely in assembly and we objcopy -S to create the vdso.so. I've dumped the headers below and everything appears to be PT_LOAD.

Will

--->8

arch/arm64/kernel/vdso/vdso.so: file format elf64-littleaarch64
arch/arm64/kernel/vdso/vdso.so
architecture: aarch64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00000000000002d0

Program Header:

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
         filesz 0x00000000000006e8 memsz 0x00000000000006e8 flags r-x
 DYNAMIC off    0x00000000000005d8 vaddr 0x00000000000005d8 paddr 0x00000000000005d8 align 2**3
         filesz 0x00000000000000f0 memsz 0x00000000000000f0 flags r--
    NOTE off    0x00000000000002b8 vaddr 0x00000000000002b8 paddr 0x00000000000002b8 align 2**2
         filesz 0x0000000000000018 memsz 0x0000000000000018 flags r--
EH_FRAME off    0x00000000000004f0 vaddr 0x00000000000004f0 paddr 0x00000000000004f0 align 2**2
         filesz 0x0000000000000034 memsz 0x0000000000000034 flags r--

Dynamic Section:

  SONAME               linux-vdso.so.1
  HASH                 0x0000000000000120
  STRTAB               0x00000000000001f8
  SYMTAB               0x0000000000000150
  STRSZ                0x0000000000000077
  SYMENT               0x0000000000000018
  VERDEF               0x0000000000000280
  VERDEFNUM            0x0000000000000002
  VERSYM               0x0000000000000270

Version definitions:
1 0x01 0x0deebfa1 linux-vdso.so.1
2 0x00 0x075fcb89 LINUX_2.6.39
private flags = 0:

Sections:

Idx Name          Size      VMA               LMA               File off  Algn
  0 .hash         00000030  0000000000000120  0000000000000120  00000120  2**3

CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .dynsym 000000a8 0000000000000150 0000000000000150 00000150 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynstr 00000077 00000000000001f8 00000000000001f8 000001f8 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.version 0000000e 0000000000000270 0000000000000270 00000270 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.version_d 00000038 0000000000000280 0000000000000280 00000280 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .note 00000018 00000000000002b8 00000000000002b8 000002b8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_CONTENTS
6 .text 00000220 00000000000002d0 00000000000002d0 000002d0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
7 .eh_frame_hdr 00000034 00000000000004f0 00000000000004f0 000004f0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .eh_frame 000000b0 0000000000000528 0000000000000528 00000528 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .dynamic 000000f0 00000000000005d8 00000000000005d8 000005d8 2**3
CONTENTS, ALLOC, LOAD, DATA
10 .got 00000008 00000000000006c8 00000000000006c8 000006c8 2**3
CONTENTS, ALLOC, LOAD, DATA
11 .got.plt 00000018 00000000000006d0 00000000000006d0 000006d0 2**3
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
no symbols

#45 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 32 lines · Will Deacon
Quoted 31 lines · Nathan Lynch
Quoted 21 lines · Andy Lutomirski

Caveat 2: (major) I'm kind of surprised that this, or the current code, works reliably. You're doing something that I tried briefly for x86_64:

        _end = .;
        PROVIDE(end = .);

        . = ALIGN(PAGE_SIZE);
        PROVIDE(_vdso_data = .);

This sounds great, except that you're assuming that vdso_end - vdso_start == ALIGN(_end, PAGE_SIZE) - (vdso base address).

If you *fully* strip the vdso (eu-strip --strip-sections), then this is true: eu-strip --strip-sections outputs just the PT_LOAD piece of the vdso. But any binutils-generated incompletely stripped ELF image contains a section table and possible non-allocatable sections at the end. If these exceed the amount of unused space in the last PT_LOAD page, then they'll spill into the next page, and _vdso_data in the vdso will no longer match the address at which vdso.c loads it. Boom!

Quoted 4 lines

I bet you're getting away with this because the whole arm64 vdso seems to be written in assembly, so it seems extremely unlikely to exceed one page minus a few hundred bytes. But if you start adding complexity, you might get unlucky.

This is why I switched (in v5) the proposed 32-bit ARM VDSO to place the data page before the code -- adding -frecord-gcc-switches to the compiler flags was enough to break it.

Quoted 7 lines
Quoted 2 lines

I meant to call Will's attention to it at the time for arm64's sake, but I guess it slipped my mind... sorry.

Hmm, so I could definitely look at doing the same thing, but I don't know if we actually need to for arm64. As Andy points out, we're written entirely in assembly and we objcopy -S to create the vdso.so. I've dumped the headers below and everything appears to be PT_LOAD.

Your dump doesn't show the location of the section and section string tables themselves. Try:

eu-readelf -l -h -S whatever.so

--Andy

#46 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 41 lines · Andy Lutomirski
Quoted 32 lines · Will Deacon
Quoted 31 lines · Nathan Lynch
Quoted 21 lines · Andy Lutomirski

Caveat 2: (major) I'm kind of surprised that this, or the current code, works reliably. You're doing something that I tried briefly for x86_64:

        _end = .;
        PROVIDE(end = .);

        . = ALIGN(PAGE_SIZE);
        PROVIDE(_vdso_data = .);

This sounds great, except that you're assuming that vdso_end - vdso_start == ALIGN(_end, PAGE_SIZE) - (vdso base address).

If you *fully* strip the vdso (eu-strip --strip-sections), then this is true: eu-strip --strip-sections outputs just the PT_LOAD piece of the vdso. But any binutils-generated incompletely stripped ELF image contains a section table and possible non-allocatable sections at the end. If these exceed the amount of unused space in the last PT_LOAD page, then they'll spill into the next page, and _vdso_data in the vdso will no longer match the address at which vdso.c loads it. Boom!

Quoted 4 lines

I bet you're getting away with this because the whole arm64 vdso seems to be written in assembly, so it seems extremely unlikely to exceed one page minus a few hundred bytes. But if you start adding complexity, you might get unlucky.

This is why I switched (in v5) the proposed 32-bit ARM VDSO to place the data page before the code -- adding -frecord-gcc-switches to the compiler flags was enough to break it.

Quoted 7 lines
Quoted 2 lines

I meant to call Will's attention to it at the time for arm64's sake, but I guess it slipped my mind... sorry.

Hmm, so I could definitely look at doing the same thing, but I don't know if we actually need to for arm64. As Andy points out, we're written entirely in assembly and we objcopy -S to create the vdso.so. I've dumped the headers below and everything appears to be PT_LOAD.

Quoted 4 lines

Your dump doesn't show the location of the section and section string tables themselves. Try:

eu-readelf -l -h -S whatever.so

Thanks. See below.

Will

--->8

ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x2d0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          1888 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         4
  Size of section headers:           64 (bytes)
  Number of section headers:         14

Section header string table index: 13

Section Headers:

  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .hash             HASH             0000000000000120  00000120
       0000000000000030  0000000000000004   A       2     0     8
  [ 2] .dynsym           DYNSYM           0000000000000150  00000150
       00000000000000a8  0000000000000018   A       3     2     8
  [ 3] .dynstr           STRTAB           00000000000001f8  000001f8
       0000000000000077  0000000000000000   A       0     0     1
  [ 4] .gnu.version      VERSYM           0000000000000270  00000270
       000000000000000e  0000000000000002   A       2     0     2
  [ 5] .gnu.version_d    VERDEF           0000000000000280  00000280
       0000000000000038  0000000000000000   A       3     2     8
  [ 6] .note             NOTE             00000000000002b8  000002b8
       0000000000000018  0000000000000000   A       0     0     4
  [ 7] .text             PROGBITS         00000000000002d0  000002d0
       0000000000000220  0000000000000000  AX       0     0     16
  [ 8] .eh_frame_hdr     PROGBITS         00000000000004f0  000004f0
       0000000000000034  0000000000000000   A       0     0     4
  [ 9] .eh_frame         PROGBITS         0000000000000528  00000528
       00000000000000b0  0000000000000000   A       0     0     8
  [10] .dynamic          DYNAMIC          00000000000005d8  000005d8
       00000000000000f0  0000000000000010  WA       3     0     8
  [11] .got              PROGBITS         00000000000006c8  000006c8
       0000000000000008  0000000000000008  WA       0     0     8
  [12] .got.plt          PROGBITS         00000000000006d0  000006d0
       0000000000000018  0000000000000008  WA       0     0     8
  [13] .shstrtab         STRTAB           0000000000000000  000006e8
       0000000000000078  0000000000000000           0     0     1

Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000

                 0x00000000000006e8 0x00000000000006e8  R E    10
  DYNAMIC        0x00000000000005d8 0x00000000000005d8 0x00000000000005d8
                 0x00000000000000f0 0x00000000000000f0  R      8
  NOTE           0x00000000000002b8 0x00000000000002b8 0x00000000000002b8
                 0x0000000000000018 0x0000000000000018  R      4
  GNU_EH_FRAME   0x00000000000004f0 0x00000000000004f0 0x00000000000004f0
                 0x0000000000000034 0x0000000000000034  R      4

Section to Segment mapping:
Segment Sections...

   00     .hash .dynsym .dynstr .gnu.version .gnu.version_d .note .text .eh_frame_hdr .eh_frame .dynamic .got .got.plt 
   01     .dynamic 
   02     .note 
   03     .eh_frame_hdr 
#47 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 17 lines · Will Deacon
Quoted 9 lines · Andy Lutomirski
Quoted 7 lines · Will Deacon
Quoted 1 line · Nathan Lynch

On 07/02/2014 10:54 AM, Andy Lutomirski wrote:

Hmm, so I could definitely look at doing the same thing, but I don't know if we actually need to for arm64. As Andy points out, we're written entirely in assembly and we objcopy -S to create the vdso.so. I've dumped the headers below and everything appears to be PT_LOAD.

Quoted 4 lines

Your dump doesn't show the location of the section and section string tables themselves. Try:

eu-readelf -l -h -S whatever.so

Thanks. See below.

Quoted 8 lines

Will

--->8

ELF Header:

  Start of section headers:          1888 (bytes into file)
  Size of section headers:           64 (bytes)
  Number of section headers:         14

That's 896 bytes for the section table, starting at offset 1888.

Quoted 7 lines

Section header string table index: 13

Section Headers:
[13] .shstrtab STRTAB 0000000000000000 000006e8

       0000000000000078  0000000000000000           0     0     1

120 bytes of section headers strings, starting at offset 1768 (and not allocatable -- no 'A' here).

Quoted 6 lines

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000

                 0x00000000000006e8 0x00000000000006e8  R E    10

The loadable segment is 1768 bytes long, starting at the beginning of the file (and therefore the beginning of the mapping).

So you have a total of 1016 bytes of non-allocatable stuff at the end that I've accounted for. I assume that the whole file is 2784 bytes.

If you added text or data to bring PT_LOAD to between 3081 and 4095 bytes, then the section headers and/or section string table would cross a page boundary.

--Andy

#48 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Cheers for this, Andy.

Quoted 26 lines · Andy Lutomirski
Quoted 4 lines · Will Deacon

ELF Header:

  Start of section headers:          1888 (bytes into file)
  Size of section headers:           64 (bytes)
  Number of section headers:         14

That's 896 bytes for the section table, starting at offset 1888.

Quoted 7 lines

Section header string table index: 13

Section Headers:
[13] .shstrtab STRTAB 0000000000000000 000006e8

       0000000000000078  0000000000000000           0     0     1

120 bytes of section headers strings, starting at offset 1768 (and not allocatable -- no 'A' here).

Quoted 6 lines

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000

                 0x00000000000006e8 0x00000000000006e8  R E    10
Quoted 5 lines

The loadable segment is 1768 bytes long, starting at the beginning of the file (and therefore the beginning of the mapping).

So you have a total of 1016 bytes of non-allocatable stuff at the end that I've accounted for. I assume that the whole file is 2784 bytes.

Correct.

Quoted 3 lines

If you added text or data to bring PT_LOAD to between 3081 and 4095 bytes, then the section headers and/or section string table would cross a page boundary.

Ok, so that explains why things are working at the moment and it sounds like we have some wiggle room too. I'll look at moving the datapage anyway, since having these artificial limits is error-prone and fragile, but I don't think it's something we need to panic about immediately.

Also, if you get to the bottom of your binutils issues with the section allocation, that might work for us since we don't really have any legacy binutils supporting arm64.

Will

#49 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 41 lines · Will Deacon

Cheers for this, Andy.

Quoted 26 lines · Andy Lutomirski
Quoted 4 lines · Will Deacon

ELF Header:

  Start of section headers:          1888 (bytes into file)
  Size of section headers:           64 (bytes)
  Number of section headers:         14

That's 896 bytes for the section table, starting at offset 1888.

Quoted 7 lines

Section header string table index: 13

Section Headers:
[13] .shstrtab STRTAB 0000000000000000 000006e8

       0000000000000078  0000000000000000           0     0     1

120 bytes of section headers strings, starting at offset 1768 (and not allocatable -- no 'A' here).

Quoted 6 lines

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000

                 0x00000000000006e8 0x00000000000006e8  R E    10
Quoted 5 lines

The loadable segment is 1768 bytes long, starting at the beginning of the file (and therefore the beginning of the mapping).

So you have a total of 1016 bytes of non-allocatable stuff at the end that I've accounted for. I assume that the whole file is 2784 bytes.

Correct.

Quoted 3 lines

If you added text or data to bring PT_LOAD to between 3081 and 4095 bytes, then the section headers and/or section string table would cross a page boundary.

Quoted 8 lines

Ok, so that explains why things are working at the moment and it sounds like we have some wiggle room too. I'll look at moving the datapage anyway, since having these artificial limits is error-prone and fragile, but I don't think it's something we need to panic about immediately.

Also, if you get to the bottom of your binutils issues with the section allocation, that might work for us since we don't really have any legacy binutils supporting arm64.

Just in case anyone still cares about this thread, moving the vvar area back before the vdso text is queued up for 3.17. I gave up on reliably keeping binutils happy with my ugly hack.

--Andy

#50 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 6 lines · Andy Lutomirski
Quoted 5 lines · Will Deacon

Ok, so that explains why things are working at the moment and it sounds like we have some wiggle room too. I'll look at moving the datapage anyway, since having these artificial limits is error-prone and fragile, but I don't think it's something we need to panic about immediately.

Quoted 7 lines
Quoted 3 lines

Also, if you get to the bottom of your binutils issues with the section allocation, that might work for us since we don't really have any legacy binutils supporting arm64.

Just in case anyone still cares about this thread, moving the vvar area back before the vdso text is queued up for 3.17. I gave up on reliably keeping binutils happy with my ugly hack.

The same change is also queued for arm64.

Thanks Andy,

Will

#51 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

In reply to Andy Lutomirski
Quoted 16 lines · Andy Lutomirski
Quoted 15 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +15 -0
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+	int ret;
+
+	mm->context.vdso = ~0UL;
+
+	if (vdso_pagelist == NULL)
+		return;
+
+	/*
+	 * Put vDSO base into mm struct before calling
+	 * install_special_mapping so the perf counter mmap tracking
+	 * code will recognise it as a vDSO.
+	 */
+	mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+	ret = install_special_mapping(mm, addr, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

I'm aware of that. One could argue (as does the author of the equivalent code in powerpc) that this is a "well, don't do that" situation. But I tend to agree that it would be nicer to prevent this failure mode.

Quoted 3 lines

You also seem to
be sticking it *before* the vdso in the same vma. This will severely piss off all the tools that assume that "[vdso]" points to an ELF object.

Hmm, which tools? Shouldn't they be consulting AT_SYSINFO_EHDR in the auxiliary vector instead?

Quoted 5 lines

x86 calls this thing "[vvar]" and sticks it after the vdso. You might not want to have the complexity of sticking it after the vdso (it's distinctly nontrivial), but I see nothing wrong with giving it its own vma just before the vdso. The new _install_special_mapping function makes it considerably easier to do.

I'll give this a shot, thanks.

#52 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 32 lines · Nathan Lynch
Quoted 16 lines · Andy Lutomirski
Quoted 15 lines · Nathan Lynch
arch/arm/kernel/vdso.c new file +15 -0
+void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
+{
+    int ret;
+
+    mm->context.vdso = ~0UL;
+
+    if (vdso_pagelist == NULL)
+            return;
+
+    /*
+     * Put vDSO base into mm struct before calling
+     * install_special_mapping so the perf counter mmap tracking
+     * code will recognise it as a vDSO.
+     */
+    mm->context.vdso = addr;
Quoted 8 lines

arch/arm/kernel/vdso.c line 95

Quoted 5 lines
arch/arm/kernel/vdso.c new file +5 -0
+
+    ret = install_special_mapping(mm, addr, vdso_mapping_len,
+                                  VM_READ|VM_EXEC|
+                                  VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+                                  vdso_pagelist);

Eek. You're mapping the shared data VM_MAYWRITE. This will cause bizarre and confusing failures if ptrace pokes at it.

I'm aware of that. One could argue (as does the author of the equivalent code in powerpc) that this is a "well, don't do that" situation. But I tend to agree that it would be nicer to prevent this failure mode.

Quoted 7 lines
Quoted 3 lines

You also seem to
be sticking it *before* the vdso in the same vma. This will severely piss off all the tools that assume that "[vdso]" points to an ELF object.

Hmm, which tools? Shouldn't they be consulting AT_SYSINFO_EHDR in the auxiliary vector instead?

There were a bunch of random things written before getauxvec(3) was introduced that look for "[vdso]"

gdb is also a bit weird. I think it's changed a couple times, but IIRC it looks for a vma that has a start address that matches AT_SYSINFO_EDHR, and then it parses the ELF header and *section* headers (sigh) in that vma. So if I'm remembering correctly, it just won't notice the vdso at all of AT_SYSINFO_EHDR and the vma start aren't the same.

Quoted 9 lines
Quoted 6 lines

x86 calls this thing "[vvar]" and sticks it after the vdso. You might not want to have the complexity of sticking it after the vdso (it's distinctly nontrivial), but I see nothing wrong with giving it its own vma just before the vdso. The new _install_special_mapping function makes it considerably easier to do.

I'll give this a shot, thanks.

--Andy

#53 lore raw

PATCH v7 8/9 ARM: vdso initialization, mapping, and synchronization

Quoted 8 lines · Andy Lutomirski
Quoted 3 lines · Nathan Lynch

Hmm, which tools? Shouldn't they be consulting AT_SYSINFO_EHDR in the auxiliary vector instead?

There were a bunch of random things written before getauxvec(3) was introduced that look for "[vdso]"

Quoted 6 lines

gdb is also a bit weird. I think it's changed a couple times, but IIRC it looks for a vma that has a start address that matches AT_SYSINFO_EDHR, and then it parses the ELF header and *section* headers (sigh) in that vma. So if I'm remembering correctly, it just won't notice the vdso at all of AT_SYSINFO_EHDR and the vma start aren't the same.

Hmm, that would explain the weird error I got when trying gdb with the vdso in place.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#54 lore raw

PATCH v7 9/9 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.

---
 arch/arm/kernel/Makefile |  1 +
 arch/arm/mm/Kconfig      | 15 +++++++++++++++
 2 files changed, 16 insertions(+)
arch/arm/kernel/Makefile +1 -0
index 38ddd9f83d0e..87d4cdc3f3f9 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 vdso/
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
arch/arm/mm/Kconfig +15 -0
index eda0dd0ab97b..616f46794502 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.20 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
#55 lore raw

v7 cover ARM: VDSO

In reply to Nathan Lynch
Quoted 5 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).

Hi Nathan,

applying your patches I get the following compile error under Ubuntu 12.04:

  CC      arch/arm/kernel/vdso.o
  LDS     arch/arm/kernel/vdso/vdso.lds
  CC      arch/arm/kernel/vdso/vgettimeofday.o
  AS      arch/arm/kernel/vdso/datapage.o
  VDSOL   arch/arm/kernel/vdso/vdso.so.raw
  HOSTCC  arch/arm/kernel/vdso/vdsomunge

arch/arm/kernel/vdso/vdsomunge.c: In function ?main?:
arch/arm/kernel/vdso/vdsomunge.c:152:16: error: ?EF_ARM_ABI_FLOAT_HARD? undeclared (first use in this function) arch/arm/kernel/vdso/vdsomunge.c:152:16: note: each undeclared identifier is reported only once for each function it appears in arch/arm/kernel/vdso/vdsomunge.c:156:34: error: ?EF_ARM_ABI_FLOAT_SOFT? undeclared (first use in this function) make[2]: *** [arch/arm/kernel/vdso/vdsomunge] Error 1
make[1]: *** [arch/arm/kernel/vdso] Error 2
make: *** [arch/arm/kernel] Error 2

Looks like the libc dev is too old (EF_ARM_ABI_FLOAT_* not in /usr/include/elf.h). On a more recent Ubuntu it compiles fine. Not sure how to solve this, maybe disable vdso if the libc is too old?

Regards, Jan

#56 lore raw

v7 cover ARM: VDSO

Quoted 25 lines · Jan Glauber
Quoted 5 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).

Hi Nathan,

applying your patches I get the following compile error under Ubuntu 12.04:

  CC      arch/arm/kernel/vdso.o
  LDS     arch/arm/kernel/vdso/vdso.lds
  CC      arch/arm/kernel/vdso/vgettimeofday.o
  AS      arch/arm/kernel/vdso/datapage.o
  VDSOL   arch/arm/kernel/vdso/vdso.so.raw
  HOSTCC  arch/arm/kernel/vdso/vdsomunge

arch/arm/kernel/vdso/vdsomunge.c: In function ?main?:
arch/arm/kernel/vdso/vdsomunge.c:152:16: error: ?EF_ARM_ABI_FLOAT_HARD? undeclared (first use in this function) arch/arm/kernel/vdso/vdsomunge.c:152:16: note: each undeclared identifier is reported only once for each function it appears in arch/arm/kernel/vdso/vdsomunge.c:156:34: error: ?EF_ARM_ABI_FLOAT_SOFT? undeclared (first use in this function) make[2]: *** [arch/arm/kernel/vdso/vdsomunge] Error 1
make[1]: *** [arch/arm/kernel/vdso] Error 2
make: *** [arch/arm/kernel] Error 2

Quoted 3 lines

Looks like the libc dev is too old (EF_ARM_ABI_FLOAT_* not in /usr/include/elf.h). On a more recent Ubuntu it compiles fine. Not sure how to solve this, maybe disable vdso if the libc is too old?

This is what really concerns me about the VDSO. It adds an additional dependence on the C library in order to build the kernel. What if you don't have a C library in your cross-build setup (I don't.)

Until that is solved, the VDSO support is not going in, as it will effectively render the kernel unbuildable for me.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#57 lore raw

v7 cover ARM: VDSO

Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Jan Glauber
Quoted 5 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).

Hi Nathan,

applying your patches I get the following compile error under Ubuntu 12.04:

  CC      arch/arm/kernel/vdso.o
  LDS     arch/arm/kernel/vdso/vdso.lds
  CC      arch/arm/kernel/vdso/vgettimeofday.o
  AS      arch/arm/kernel/vdso/datapage.o
  VDSOL   arch/arm/kernel/vdso/vdso.so.raw
  HOSTCC  arch/arm/kernel/vdso/vdsomunge

arch/arm/kernel/vdso/vdsomunge.c: In function ?main?:
arch/arm/kernel/vdso/vdsomunge.c:152:16: error: ?EF_ARM_ABI_FLOAT_HARD? undeclared (first use in this function) arch/arm/kernel/vdso/vdsomunge.c:152:16: note: each undeclared identifier is reported only once for each function it appears in arch/arm/kernel/vdso/vdsomunge.c:156:34: error: ?EF_ARM_ABI_FLOAT_SOFT? undeclared (first use in this function) make[2]: *** [arch/arm/kernel/vdso/vdsomunge] Error 1
make[1]: *** [arch/arm/kernel/vdso] Error 2
make: *** [arch/arm/kernel] Error 2

Quoted 4 lines
Quoted 3 lines

Looks like the libc dev is too old (EF_ARM_ABI_FLOAT_* not in /usr/include/elf.h). On a more recent Ubuntu it compiles fine. Not sure how to solve this, maybe disable vdso if the libc is too old?

It appears that the EF_ARM_ABI_FLOAT_[SOFT|HARD] defines are just renames of

#define EF_ARM_SOFT_FLOAT 0x200
#define EF_ARM_VFP_FLOAT 0x400

so perhaps use those instead?

Quoted 4 lines

This is what really concerns me about the VDSO. It adds an additional dependence on the C library in order to build the kernel. What if you don't have a C library in your cross-build setup (I don't.)

This is a host tool, so this is about the host libc not the target libc.

Signature · 1 line
Ard.
Quoted 6 lines

Until that is solved, the VDSO support is not going in, as it will effectively render the kernel unbuildable for me.

--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.

#58 lore raw

v7 cover ARM: VDSO

Quoted 6 lines · Ard Biesheuvel

It appears that the EF_ARM_ABI_FLOAT_[SOFT|HARD] defines are just renames of

#define EF_ARM_SOFT_FLOAT 0x200
#define EF_ARM_VFP_FLOAT 0x400

so perhaps use those instead?

Or maybe provide our own definitions so we're not reliant on the host environment providing the correct definitions for these.

Quoted 6 lines
Quoted 4 lines

This is what really concerns me about the VDSO. It adds an additional dependence on the C library in order to build the kernel. What if you don't have a C library in your cross-build setup (I don't.)

This is a host tool, so this is about the host libc not the target libc.

It still sounds pretty fragile.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#59 lore raw

v7 cover ARM: VDSO

Quoted 10 lines · Russell King - ARM Linux
Quoted 6 lines · Ard Biesheuvel

It appears that the EF_ARM_ABI_FLOAT_[SOFT|HARD] defines are just renames of

#define EF_ARM_SOFT_FLOAT 0x200
#define EF_ARM_VFP_FLOAT 0x400

so perhaps use those instead?

Or maybe provide our own definitions so we're not reliant on the host environment providing the correct definitions for these.

Right.

Quoted 9 lines
Quoted 7 lines
Quoted 5 lines

This is what really concerns me about the VDSO. It adds an additional dependence on the C library in order to build the kernel. What if you don't have a C library in your cross-build setup (I don't.)

This is a host tool, so this is about the host libc not the target libc.

It still sounds pretty fragile.

Since removing -lgcc from the link (one of the changes from v6 to v7), I believe the VDSO is not asking more of the toolchain or build environment than the rest of the kernel does. I have definitely built it without a target libc. Apart from the host program's use of too-recent ELF constants (now fixed), I would appreciate help identifying any remaining sources of fragility.

#60 lore raw

v7 cover ARM: VDSO

Quoted 6 lines · Nathan Lynch

Since removing -lgcc from the link (one of the changes from v6 to v7), I believe the VDSO is not asking more of the toolchain or build environment than the rest of the kernel does. I have definitely built it without a target libc. Apart from the host program's use of too-recent ELF constants (now fixed), I would appreciate help identifying any remaining sources of fragility.

There's still something wrong:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function) fs/binfmt_elf.c:231:35: note: each undeclared identifier is reported only once for each function it appears in

The problem is the fscking generated includes. This is going to be a right pain - Arnd, is there anything which can be done about this?

What's happening is if you try and rebuild a kernel with these patches applied, you already have an arch/arm/include/generated/asm/auxvec.h which points at the empty asm-generic version. This remains after these patches are applied, so the new include of asm/auxvec.h in asm/elf.h picks up on the empty version, not the newly introduced version.

So, the way to get this to build with the minimum of disruption is to first manually remove arch/arm/include/generated/asm/auxvec.h in the build tree before running make.

This isn't a vdso problem - it's a kbuild problem, one obviously caused by not thinking through properly the implications of generating include files and how to deal with changes in the future like this very scenario. I think I'd rather get rid of this generated include crap and instead have explicit include files instead in the kernel tree - that way we /know/ what the situation is at all times, and make has the proper idea about the dependencies at all times.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#61 lore raw

v7 cover ARM: VDSO

Quoted 8 lines · Russell King - ARM Linux
Quoted 6 lines · Nathan Lynch

Since removing -lgcc from the link (one of the changes from v6 to v7), I believe the VDSO is not asking more of the toolchain or build environment than the rest of the kernel does. I have definitely built it without a target libc. Apart from the host program's use of too-recent ELF constants (now fixed), I would appreciate help identifying any remaining sources of fragility.

Quoted 8 lines

There's still something wrong:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function) fs/binfmt_elf.c:231:35: note: each undeclared identifier is reported only once for each function it appears in

The problem is the fscking generated includes. This is going to be a right pain - Arnd, is there anything which can be done about this?

And yes, I see that you've mentioned this in the cover - but I think we /really/ need this solved before we can merge this series, otherwise we're likely to get lots of people asking about it.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#62 lore raw

v7 cover ARM: VDSO

Quoted 15 lines · Russell King - ARM Linux
Quoted 14 lines · Russell King - ARM Linux
Quoted 6 lines · Nathan Lynch

Since removing -lgcc from the link (one of the changes from v6 to v7), I believe the VDSO is not asking more of the toolchain or build environment than the rest of the kernel does. I have definitely built it without a target libc. Apart from the host program's use of too-recent ELF constants (now fixed), I would appreciate help identifying any remaining sources of fragility.

There's still something wrong:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function) fs/binfmt_elf.c:231:35: note: each undeclared identifier is reported only once for each function it appears in

Quoted 6 lines
Quoted 2 lines

The problem is the fscking generated includes. This is going to be a right pain - Arnd, is there anything which can be done about this?

And yes, I see that you've mentioned this in the cover - but I think we /really/ need this solved before we can merge this series, otherwise we're likely to get lots of people asking about it.

Thinking about this some more - if this can't be resolved by kbuild, then I think we should add to arch/arm/Kconfig to detect the generated include file, print a helpful message telling the user how to fix their build tree, and error out.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#63 lore raw

v7 cover ARM: VDSO

Quoted 19 lines · On Saturday 28 June 2014 15:49:04 Russell King - ARM Linux wrote:
Quoted 18 lines · Russell King - ARM Linux
Quoted 16 lines · Russell King - ARM Linux
Quoted 6 lines · Nathan Lynch

Since removing -lgcc from the link (one of the changes from v6 to v7), I believe the VDSO is not asking more of the toolchain or build environment than the rest of the kernel does. I have definitely built it without a target libc. Apart from the host program's use of too-recent ELF constants (now fixed), I would appreciate help identifying any remaining sources of fragility.

There's still something wrong:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function) fs/binfmt_elf.c:231:35: note: each undeclared identifier is reported only once for each function it appears in

The problem is the fscking generated includes. This is going to be a right pain - Arnd, is there anything which can be done about this?

Quoted 8 lines
Quoted 3 lines

And yes, I see that you've mentioned this in the cover - but I think we /really/ need this solved before we can merge this series, otherwise we're likely to get lots of people asking about it.

Thinking about this some more - if this can't be resolved by kbuild, then I think we should add to arch/arm/Kconfig to detect the generated include file, print a helpful message telling the user how to fix their build tree, and error out.

I think there is a way to flag files to be deleted on every build in the Makefile, I'd have to read up on that. I've run into similar problems before, also with generated files sometimes not getting removed during 'make clean'.

Arnd

#64 lore raw

v7 cover ARM: VDSO

In reply to Russell King - ARM Linux
Quoted 6 lines · On Saturday 28 June 2014 10:42:19 Russell King - ARM Linux wrote:

What's happening is if you try and rebuild a kernel with these patches applied, you already have an arch/arm/include/generated/asm/auxvec.h which points at the empty asm-generic version. This remains after these patches are applied, so the new include of asm/auxvec.h in asm/elf.h picks up on the empty version, not the newly introduced version.

One more piece of the puzzle: the top-level Makefile always includes the headers from the source tree before generated headers, so in theory this should not be happening. However, for some reason this ends up as arch/arm/include/generated/asm/auxvec.h rather than arch/arm/include/generated/uapi/asm/auxvec.h, and the kernel-only headers get included before any of the uapi headers.

An easy workaround would probably be to add an arch/arm/include/asm/auxvec.h file that contains only

#include <uapi/asm/auxvec.h>

Arnd

#65 lore raw

v7 cover ARM: VDSO

Quoted 15 lines · Arnd Bergmann
Quoted 6 lines · On Saturday 28 June 2014 10:42:19 Russell King - ARM Linux wrote:

What's happening is if you try and rebuild a kernel with these patches applied, you already have an arch/arm/include/generated/asm/auxvec.h which points at the empty asm-generic version. This remains after these patches are applied, so the new include of asm/auxvec.h in asm/elf.h picks up on the empty version, not the newly introduced version.

One more piece of the puzzle: the top-level Makefile always includes the headers from the source tree before generated headers, so in theory this should not be happening. However, for some reason this ends up as arch/arm/include/generated/asm/auxvec.h rather than arch/arm/include/generated/uapi/asm/auxvec.h, and the kernel-only headers get included before any of the uapi headers.

Quoted 4 lines

An easy workaround would probably be to add an arch/arm/include/asm/auxvec.h file that contains only

#include <uapi/asm/auxvec.h>

Thanks Arnd, that seems to do the trick.

#66 lore raw

v7 cover ARM: VDSO

In reply to Jan Glauber
Quoted 25 lines · Jan Glauber
Quoted 5 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).

Hi Nathan,

applying your patches I get the following compile error under Ubuntu 12.04:

  CC      arch/arm/kernel/vdso.o
  LDS     arch/arm/kernel/vdso/vdso.lds
  CC      arch/arm/kernel/vdso/vgettimeofday.o
  AS      arch/arm/kernel/vdso/datapage.o
  VDSOL   arch/arm/kernel/vdso/vdso.so.raw
  HOSTCC  arch/arm/kernel/vdso/vdsomunge

arch/arm/kernel/vdso/vdsomunge.c: In function ?main?:
arch/arm/kernel/vdso/vdsomunge.c:152:16: error: ?EF_ARM_ABI_FLOAT_HARD? undeclared (first use in this function) arch/arm/kernel/vdso/vdsomunge.c:152:16: note: each undeclared identifier is reported only once for each function it appears in arch/arm/kernel/vdso/vdsomunge.c:156:34: error: ?EF_ARM_ABI_FLOAT_SOFT? undeclared (first use in this function) make[2]: *** [arch/arm/kernel/vdso/vdsomunge] Error 1
make[1]: *** [arch/arm/kernel/vdso] Error 2
make: *** [arch/arm/kernel] Error 2

Quoted 3 lines

Looks like the libc dev is too old (EF_ARM_ABI_FLOAT_* not in /usr/include/elf.h). On a more recent Ubuntu it compiles fine. Not sure how to solve this, maybe disable vdso if the libc is too old?

We should just define some of the needed ELF constants in the tool if the host <elf.h> lacks them. EF_ARM_ABI_FLOAT_HARD/SOFT were added in 2012, EF_ARM_EABI_VER5 in 2009... everything else the tool uses has been there for twelve years or more.

Thanks for the report -- please try the below?

(quoted diff) +0 -0

b/arch/arm/kernel/vdso/vdsomunge.c
index 823b84d142bc..b586ef699fb8 100644

arch/arm/kernel/vdso/vdsomunge.c +15 -0
@@ -67,6 +67,21 @@
 #define HOST_ORDER ELFDATA2MSB
 #endif
 
+/* Some of the ELF constants we'd like to use were added to <elf.h>
+ * relatively recently.
+ */
+#ifndef EF_ARM_EABI_VER5
+#define EF_ARM_EABI_VER5 0x05000000
+#endif
+
+#ifndef EF_ARM_ABI_FLOAT_SOFT
+#define EF_ARM_ABI_FLOAT_SOFT 0x200
+#endif
+
+#ifndef EF_ARM_ABI_FLOAT_HARD
+#define EF_ARM_ABI_FLOAT_HARD 0x400
+#endif
+
 static const char *outfile;
 
 static void cleanup(void)
#67 lore raw

v7 cover ARM: VDSO

In reply to Jan Glauber
Quoted 6 lines · Jan Glauber
Quoted 5 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).

Sorry for replying to the wrong email in the thread -- my gmane feed missed the original.

One thing that might be nice to add is AT_VDSO_FINDSYM [1]. A lot of userspace implementations (especially for static, embedded things) might significantly prefer that style of entry point.

If you want to use vdso2c for vdso image post-processing, I'd be happy to try to make it available outside arch/x86 and to make it more configurable as needed.

Please use _install_special_mapping instead of install_special_mapping.
AFAICS it's basically impossible to use install_special_mapping correctly.

[1]
https://git.kernel.org/cgit/linux/kernel/git/luto/linux.git/log/?h=x86/vdso_findsym

--Andy

#68 lore raw

v7 cover ARM: VDSO

In reply to Nathan Lynch
Quoted 39 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.

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.

Run-time 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

If this series is applied to an already-built tree and CONFIG_VDSO is enabled, an incremental build may fail with:

fs/binfmt_elf.c: In function 'create_elf_tables':
fs/binfmt_elf.c:231:35: error: 'AT_SYSINFO_EHDR' undeclared (first use in this function)

Quoted 7 lines

This can be worked around by removing arch/arm/include/generated/asm/auxvec.h from the build tree. I lean toward attributing this to a Kbuild limitation/bug, but would appreciate extra scrutiny on the patch "ARM: miscellaneous vdso infrastructure, preparation" to see if there's anything to correct there.

On Exynos-5250 (Cortex-A15):

clock-gettime-monotonic system calls per second: 1759517
clock-gettime-monotonic vdso calls per second: 6027915 (3.43x speedup)
clock-getres-monotonic system calls per second: 2144055
clock-getres-monotonic vdso calls per second: 82783103 (38.61x speedup)
clock-gettime-monotonic-coarse system calls per second: 1971433
clock-gettime-monotonic-coarse vdso calls per second: 10710734 (5.43x speedup)
clock-getres-monotonic-coarse system calls per second: 2182380
clock-getres-monotonic-coarse vdso calls per second: 76710594 (35.15x speedup)
clock-gettime-realtime system calls per second: 1722524
clock-gettime-realtime vdso calls per second: 6309212 (3.66x speedup)
clock-getres-realtime system calls per second: 2182357
clock-getres-realtime vdso calls per second: 83120713 (38.09x speedup)
clock-gettime-realtime-coarse system calls per second: 2085498
clock-gettime-realtime-coarse vdso calls per second: 11326069 (5.43x speedup)
clock-getres-realtime-coarse system calls per second: 2178266
clock-getres-realtime-coarse vdso calls per second: 76731175 (35.23x speedup)
Note: vDSO version of getcpu not found
getcpu system calls per second: 2645300
getcpu vdso calls per second: 2612154 (0.99x speedup)
Note: vDSO version of getcpu not found
Note: vDSO version of getcpu not found
gettimeofday system calls per second: 1707745
gettimeofday vdso calls per second: 6474501 (3.79x speedup)

Regards,
Ard.

Quoted 132 lines

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 (9):
clocksource: arm_arch_timer: change clocksource name if CP15
unavailable
clocksource: arm_arch_timer: enable counter access for 32-bit ARM
ARM: arch_timer: remove unused functions
arm64: arch_timer: remove unused functions
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/include/asm/Kbuild          |   1 -
 arch/arm/include/asm/arch_timer.h    |  25 ---
 arch/arm/include/asm/elf.h           |  11 ++
 arch/arm/include/asm/mmu.h           |   3 +
 arch/arm/include/asm/vdso.h          |  47 +++++
 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            |  56 +++++-
 arch/arm/kernel/vdso.c               | 168 ++++++++++++++++++
 arch/arm/kernel/vdso/.gitignore      |   1 +
 arch/arm/kernel/vdso/Makefile        |  59 +++++++
 arch/arm/kernel/vdso/checkundef.sh   |   9 +
 arch/arm/kernel/vdso/datapage.S      |  15 ++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  88 ++++++++++
 arch/arm/kernel/vdso/vdsomunge.c     | 193 +++++++++++++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 320 +++++++++++++++++++++++++++++++++++
 arch/arm/mm/Kconfig                  |  15 ++
 arch/arm64/include/asm/arch_timer.h  |  31 ----
 drivers/clocksource/arm_arch_timer.c |  48 +++++-
 23 files changed, 1134 insertions(+), 65 deletions(-)
 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/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100755 arch/arm/kernel/vdso/checkundef.sh
 create mode 100644 arch/arm/kernel/vdso/datapage.S
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vdsomunge.c
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c

--
1.9.3

#69 lore raw

v7 cover ARM: VDSO

Quoted 4 lines · Ard Biesheuvel
Quoted 3 lines · Nathan Lynch

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7.

...

Quoted 19 lines

On Exynos-5250 (Cortex-A15):

clock-gettime-monotonic system calls per second: 1759517
clock-gettime-monotonic vdso calls per second: 6027915 (3.43x speedup)
clock-getres-monotonic system calls per second: 2144055
clock-getres-monotonic vdso calls per second: 82783103 (38.61x speedup)
clock-gettime-monotonic-coarse system calls per second: 1971433
clock-gettime-monotonic-coarse vdso calls per second: 10710734 (5.43x speedup)
clock-getres-monotonic-coarse system calls per second: 2182380
clock-getres-monotonic-coarse vdso calls per second: 76710594 (35.15x speedup)
clock-gettime-realtime system calls per second: 1722524
clock-gettime-realtime vdso calls per second: 6309212 (3.66x speedup)
clock-getres-realtime system calls per second: 2182357
clock-getres-realtime vdso calls per second: 83120713 (38.09x speedup)
clock-gettime-realtime-coarse system calls per second: 2085498
clock-gettime-realtime-coarse vdso calls per second: 11326069 (5.43x speedup)
clock-getres-realtime-coarse system calls per second: 2178266

Quoted 8 lines

clock-getres-realtime-coarse vdso calls per second: 76731175 (35.23x speedup)
Note: vDSO version of getcpu not found getcpu system calls per second: 2645300
getcpu vdso calls per second: 2612154 (0.99x speedup)
Note: vDSO version of getcpu not found
Note: vDSO version of getcpu not found gettimeofday system calls per second: 1707745
gettimeofday vdso calls per second: 6474501 (3.79x speedup)

Thank you very much for testing (especially on a platform I don't have).

These results match up with what I get on OMAP5 (also Cortex-A15).

Since it looks like I will need to make some significant changes for the next version, I think I can't in good conscience carry your Tested-by on to v8 (although I'm open to different opinions). But I still very much appreciate it.

#70 lore raw

v7 cover ARM: VDSO

Quoted 36 lines · Nathan Lynch
Quoted 4 lines · Ard Biesheuvel
Quoted 3 lines · Nathan Lynch

Provide fast userspace implementations of gettimeofday and clock_gettime on systems that implement the generic timers extension defined in ARMv7.

...

Quoted 19 lines

On Exynos-5250 (Cortex-A15):

clock-gettime-monotonic system calls per second: 1759517
clock-gettime-monotonic vdso calls per second: 6027915 (3.43x speedup)
clock-getres-monotonic system calls per second: 2144055
clock-getres-monotonic vdso calls per second: 82783103 (38.61x speedup)
clock-gettime-monotonic-coarse system calls per second: 1971433
clock-gettime-monotonic-coarse vdso calls per second: 10710734 (5.43x speedup)
clock-getres-monotonic-coarse system calls per second: 2182380
clock-getres-monotonic-coarse vdso calls per second: 76710594 (35.15x speedup)
clock-gettime-realtime system calls per second: 1722524
clock-gettime-realtime vdso calls per second: 6309212 (3.66x speedup)
clock-getres-realtime system calls per second: 2182357
clock-getres-realtime vdso calls per second: 83120713 (38.09x speedup)
clock-gettime-realtime-coarse system calls per second: 2085498
clock-gettime-realtime-coarse vdso calls per second: 11326069 (5.43x speedup)
clock-getres-realtime-coarse system calls per second: 2178266

Quoted 8 lines

clock-getres-realtime-coarse vdso calls per second: 76731175 (35.23x speedup)
Note: vDSO version of getcpu not found getcpu system calls per second: 2645300
getcpu vdso calls per second: 2612154 (0.99x speedup)
Note: vDSO version of getcpu not found
Note: vDSO version of getcpu not found gettimeofday system calls per second: 1707745
gettimeofday vdso calls per second: 6474501 (3.79x speedup)

Quoted 4 lines

Thank you very much for testing (especially on a platform I don't have).

These results match up with what I get on OMAP5 (also Cortex-A15).

Good.

Quoted 5 lines

Since it looks like I will need to make some significant changes for the next version, I think I can't in good conscience carry your Tested-by on to v8 (although I'm open to different opinions). But I still very much appreciate it.

We (at Linaro) had independently identified VDSO for ARM as a topic of interest after seeing gettimeofday() turn up in a couple of benchmarks (which btw seem to be the primary users of gettimeofday() at such a high rate), so of course, when someone else steps up and does the work, i am happy to at least spend some time testing it. Therefore, I would be happy to test your new version either before or after you (re)post it, whichever you prefer.

Regards,
Ard.

#71 lore raw

v7 cover ARM: VDSO

Quoted 7 lines · Ard Biesheuvel

We (at Linaro) had independently identified VDSO for ARM as a topic of interest after seeing gettimeofday() turn up in a couple of benchmarks (which btw seem to be the primary users of gettimeofday() at such a high rate), so of course, when someone else steps up and does the work, i am happy to at least spend some time testing it. Therefore, I would be happy to test your new version either before or after you (re)post it, whichever you prefer.

As has been covered by Nathan in a previous reply - the VDSO is only of real benefit on CPUs with the architected timer. Those without this do not have access from userspace to an appropriate timer to allow the VDSO to compute the current time.

Hence, the VDSO will just call into the kernel via the standard (and very same) syscalls that glibc would otherwise have used.

This is illustrated nicely by the results posted for iMX6, which reflects how the VDSO is going to affect platforms without the architected timer.

Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#72 lore raw

v7 cover ARM: VDSO

In reply to Nathan Lynch

Hi Nathan,

Quoted 5 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).

[...]

This series is starting to gain traction now, so it's probably time to start thinking about implementing this for CONFIG_COMPAT on arm64. We currently map a fake vectors page there, but this would be much more flexible, particularly as its written in C (and so we would magically get any new functions added to the 32-bit version).

So, there are a couple of questions that spring to mind:

- How difficult is it to share the vdso code with arm64 to build a compat vdso? (getting the Makefile to work will be hard, as we'll need an arm toolchain...).

- If we use your code to build an arm64 vdso, how much slower is it than the handcrafted asm we currently have?

Will

#73 lore raw

v7 cover ARM: VDSO

Quoted 17 lines · Will Deacon

Hi Nathan,

Quoted 5 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).

[...]

This series is starting to gain traction now, so it's probably time to start thinking about implementing this for CONFIG_COMPAT on arm64. We currently map a fake vectors page there, but this would be much more flexible, particularly as its written in C (and so we would magically get any new functions added to the 32-bit version).

Quoted 5 lines

So, there are a couple of questions that spring to mind:

- How difficult is it to share the vdso code with arm64 to build a compat vdso? (getting the Makefile to work will be hard, as we'll need an arm toolchain...).

Not sure. x86 might be the best example to work from here, although it has the advantage of everything living under arch/x86. 64-bit powerpc kernels provide a 32-bit VDSO for compat tasks but I think it doesn't really share code with the 64-bit VDSO.

Quoted 3 lines

- If we use your code to build an arm64 vdso, how much slower is it than the handcrafted asm we currently have?

Someone with access to 64-bit hardware (i.e. not me) would have to find this out, but I would not be surprised if the C code could be tightened up -- I have not spent much time on optimizing it.

#74 lore raw

v7 cover ARM: VDSO

Quoted 20 lines · Nathan Lynch
Quoted 19 lines · Will Deacon

Hi Nathan,

Quoted 5 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).

[...]

This series is starting to gain traction now, so it's probably time to start thinking about implementing this for CONFIG_COMPAT on arm64. We currently map a fake vectors page there, but this would be much more flexible, particularly as its written in C (and so we would magically get any new functions added to the 32-bit version).

So, there are a couple of questions that spring to mind:

Quoted 8 lines
Quoted 3 lines

- How difficult is it to share the vdso code with arm64 to build a compat vdso? (getting the Makefile to work will be hard, as we'll need an arm toolchain...).

Not sure. x86 might be the best example to work from here, although it has the advantage of everything living under arch/x86. 64-bit powerpc kernels provide a 32-bit VDSO for compat tasks but I think it doesn't really share code with the 64-bit VDSO.

Heh. x86 was not a shining example of how to share code. It's a little bit better now (3.16-rc3 and up).

Quoted 9 lines
Quoted 4 lines

- If we use your code to build an arm64 vdso, how much slower is it than the handcrafted asm we currently have?

Someone with access to 64-bit hardware (i.e. not me) would have to find this out, but I would not be surprised if the C code could be tightened up -- I have not spent much time on optimizing it.

I can't comment on ARM specifically, but the only assembly in the x86 vclock_gettime is an asm volatile (""), which causes gcc to emit more optimal code. I doubt I could shave off more than a cycle or two by rewriting it in assembly.

--Andy

#75 lore raw

v7 cover ARM: VDSO

Quoted 10 lines · Andy Lutomirski
Quoted 8 lines · Nathan Lynch
Quoted 2 lines · Will Deacon

- If we use your code to build an arm64 vdso, how much slower is it than the handcrafted asm we currently have?

Someone with access to 64-bit hardware (i.e. not me) would have to find this out, but I would not be surprised if the C code could be tightened up -- I have not spent much time on optimizing it.

Quoted 4 lines

I can't comment on ARM specifically, but the only assembly in the x86 vclock_gettime is an asm volatile (""), which causes gcc to emit more optimal code. I doubt I could shave off more than a cycle or two by rewriting it in assembly.

The arm64 version avoids the stack completely (we have lots of registers), so I'd expect a significant win over a C version. However, I'd be interested to see a comparison as the C version is clearly more maintainable.

Will