ARM: vdso gettimeofday using generic timer architecture
Subsystems (4)
v6 cover ARM: vdso gettimeofday using generic timer architecture
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).
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.
As a preliminary step, the placement of the sigpage is changed to be at a randomized offset above the stack. The vdso is placed immediately above the sigpage.
Changes since v5:
- Update to 3.15-rc1.
- Place vdso at a randomized offset above the stack along with the sigpage.
- Properly export asm/auxvec.h.
- Split patch into series for ease of review.
Changes since v4:
- Map data page at the beginning of the VMA to prevent orphan sections at the end of output invalidating the calculated offset.
- Move checkundef into cmd_vdsold to avoid spurious rebuilds.
- Change vdso_init message to pr_debug.
- Add -fno-stack-protector to cflags.
Changes since v3:
- Update to 3.14-rc6.
- Record vdso base in mm context before installing mapping (for the sake of perf_mmap_event).
- Use a more seqcount-like API for critical sections. Using seqcount API directly, however, would leak kernel pointers to userspace when lockdep is enabled.
- Trap instead of looping forever in division-by-zero stubs.
Changes since v2:
- Update to 3.14-rc4.
- Make vDSO configurable, depending on AEABI and MMU.
- Defer shifting of nanosecond component of timespec: fixes observed 1ns inconsistencies for CLOCK_REALTIME, CLOCK_MONOTONIC (see 45a7905fc48f for arm64 equivalent).
- Force reload of seq_count when spinning: without a memory clobber after the load of vdata->seq_count, GCC can generate code like this:
2f8: e59c9020 ldr r9, [ip, #32]
2fc: e3190001 tst r9, #1
300: 1a000033 bne 3d4 <do_realtime+0x104>
304: f57ff05b dmb ish
308: e59c3034 ldr r3, [ip, #52] ; 0x34
...
3d4: eafffffe b 3d4 <do_realtime+0x104>- Build vdso.so with -lgcc: calls to __lshrdi3, __divsi3 sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.
- Do not clear PG_reserved on vdso pages.
- Remove unnecessary get_page calls.
- Simplify ELF signature check during init.
- Use volatile for asm syscall fallbacks.
- Check whether vdso_pagelist is initialized in arm_install_vdso.
- Record clocksource mask in data page.
- Reduce code duplication in do_realtime, do_monotonic.
- Reduce calculations performed in critical sections.
- Simplify coarse clock handling.
- Move datapage load to its own assembly routine.
- Tune vdso_data layout and tweak field names.
- Check vdso shared object for undefined symbols during build.
Changes since v1:
- update to 3.14-rc1
- ensure cache coherency for data page
- Document the kernel-to-userspace protocol for vdso data page updates, and note that the timekeeping core prevents concurrent updates.
- update wall-to-monotonic fields unconditionally
- move vdso_start, vdso_end declarations to vdso.h
- correctly build and run when CONFIG_ARM_ARCH_TIMER=n
- rearrange linker script to avoid overlapping sections when CONFIG_DEBUGINFO=n
- remove use_syscall checks from coarse clock paths
- crib BUG_INSTR (0xe7f001f2) from asm/bug.h for text fill
Nathan Lynch (6):
ARM: place sigpage at a random offset above stack
ARM: allow user access to arch timer virtual counter
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 | 7 +- 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 | 50 ++++++ 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/vgettimeofday.c | 338 +++++++++++++++++++++++++++++++++++ arch/arm/mm/Kconfig | 15 ++ 20 files changed, 911 insertions(+), 7 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/vgettimeofday.c
Signature · 1 line
1.8.3.1
PATCH v6 1/6 ARM: place sigpage at a random offset above stack
The sigpage is currently placed alongside shared libraries etc in the address space. Similar to what x86_64 does, 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
@@ -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.8.3.1
PATCH v6 2/6 ARM: allow user access to arch timer virtual counter
In reply to Nathan LynchAs ARM64 does. This is a necessary prerequisite for implementing gettimeofday and clock_gettime in a vdso.
--- arch/arm/include/asm/arch_timer.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
arch/arm/include/asm/arch_timer.h +5 -2
@@ -103,13 +103,16 @@ static inline void arch_counter_set_user_access(void) {u32 cntkctl =arch_timer_get_cntkctl (); -/* Disable user access to both physical/virtual counters/timers */ +/* 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_VCT_ACCESS_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); }
Signature · 1 line
1.8.3.1
PATCH v6 2/6 ARM: allow user access to arch timer virtual counter
Quoted 2 lines · Nathan Lynch
As ARM64 does. This is a necessary prerequisite for implementing gettimeofday and
clock_gettimein a vdso.
Doesn't this change make arch_counter_set_user_access identical for arm and arm64? In which case, we could move it into the driver itself.
Will
PATCH v6 2/6 ARM: allow user access to arch timer virtual counter
Quoted 6 lines · Will Deacon
Quoted 2 lines · Nathan Lynch
As ARM64 does. This is a necessary prerequisite for implementing gettimeofday and
clock_gettimein a vdso.Doesn't this change make
arch_counter_set_user_accessidentical for arm and arm64? In which case, we could move it into the driver itself.
True; I had considered this but wasn't sure how it could be staged.
Would a single patch updating arch/arm64, arch/arm, and drivers/clocksource/arm_arch_timer.c be okay?
PATCH v6 2/6 ARM: allow user access to arch timer virtual counter
Quoted 5 lines · Nathan Lynch
Quoted 4 lines · Will Deacon
Quoted 2 lines · Nathan Lynch
As ARM64 does. This is a necessary prerequisite for implementing gettimeofday and
clock_gettimein a vdso.
Quoted 7 lines
Quoted 2 lines
Doesn't this change make
arch_counter_set_user_accessidentical for arm and arm64? In which case, we could move it into the driver itself.True; I had considered this but wasn't sure how it could be staged.
Would a single patch updating
arch/arm64,arch/arm, anddrivers/clocksource/arm_arch_timer.cbe okay?
I'd probably modify arm_arch_timer.c to have it's own implementation, then have follow-up patches removing the arch-private definitions. You could probably deal with arch_timer_evtstrm_enable at the same time.
Will
PATCH v6 3/6 ARM: miscellaneous vdso infrastructure, preparation
In reply to Nathan LynchDefine 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
@@ -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
@@ -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 1struct linux_binprm ;int arch_setup_additional_pages (struct linux_binprm *,int );
arch/arm/include/asm/mmu.h +3 -0
@@ -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
@@ -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
@@ -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
@@ -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.8.3.1
PATCH v6 4/6 ARM: add vdso user-space code
In reply to Nathan LynchPlace 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.
--- arch/arm/kernel/asm-offsets.c | 5 + arch/arm/kernel/vdso/.gitignore | 1 + arch/arm/kernel/vdso/Makefile | 50 ++++++ 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/vgettimeofday.c | 338 +++++++++++++++++++++++++++++++++++ 8 files changed, 541 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/vgettimeofday.c
arch/arm/kernel/asm-offsets.c +5 -0
@@ -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
@@ -0,0 +1 @@ +vdso.lds
arch/arm/kernel/vdso/Makefile new file +50 -0
50 lines not on this page · raw message
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 $?
arch/arm/kernel/vdso/datapage.S new file +15 -0
@@ -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
@@ -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/vgettimeofday.c new file +338 -0
338 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH v6 5/6 ARM: vdso initialization, mapping, and synchronization
In reply to Nathan LynchInitialize 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
@@ -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.8.3.1
PATCH v6 6/6 ARM: add CONFIG_VDSO Kconfig and Makefile bits
In reply to Nathan LynchAllow 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
@@ -84,6 +84,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
@@ -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.8.3.1
v6 cover ARM: vdso gettimeofday using generic timer architecture
In reply to Nathan LynchQuoted 12 lines · Nathan Lynch
Provide fast userspace implementations of gettimeofday and
clock_gettimeon 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
Quoted 6 lines
This also provides
clock_getres(as arm64 does).Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for
clock_getresand coarse clocks is independent of the timer implementation and is provided unconditionally.
I think we'll need to rename the clocksource in arch_timer.c if we only have an mmio architected timer to something like arch_mem_counter. Or we would need to map the register space for the view into userspace? I'm guessing that is hard, but if that was done then I assume it would lay the foundation for any mmio clocksource being used for the vdso.
----8<-----
drivers/clocksource/arm_arch_timer.c +4 -2
@@ -449,10 +449,12 @@ 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_cp15; -else + }else { arch_timer_read_counter = arch_counter_get_cntvct_mem; + clocksource_counter.name ="arch_mem_counter" ; + } start_count =arch_timer_read_counter ();clocksource_register_hz (&clocksource_counter, arch_timer_rate);
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 15 lines · Stephen Boyd
Quoted 14 lines · Nathan Lynch
Provide fast userspace implementations of gettimeofday and
clock_gettimeon 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_COARSEThis also provides
clock_getres(as arm64 does).
Quoted 7 lines
Quoted 4 lines
Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for
clock_getresand coarse clocks is independent of the timer implementation and is provided unconditionally.I think we'll need to rename the clocksource in
arch_timer.cif we only have an mmio architected timer to something likearch_mem_counter.
I guess ARMv7 would allow you to have mmio without cp15 (AFAIK ARMv8 does not). I don't see any dts in arch/arm that contains an arm,armv7-timer-mem node without an arm,armv7-timer node, though.
If this is a practical concern, I think using CONFIG_ARCH_CLOCKSOURCE_DATA is perhaps a better way to communicate whether cp15 access is available. That's how the x86 vdso, for example, decides between using HPET vs TSC etc.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 20 lines · Nathan Lynch
Quoted 19 lines · Stephen Boyd
Quoted 18 lines · Nathan Lynch
Provide fast userspace implementations of gettimeofday and
clock_gettimeon 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_COARSEThis also provides
clock_getres(as arm64 does).Note that while the high-precision realtime and monotonic clock support depends on the generic timers extension, support for
clock_getresand coarse clocks is independent of the timer implementation and is provided unconditionally.
Quoted 5 lines
Quoted 2 lines
I think we'll need to rename the clocksource in
arch_timer.cif we only have an mmio architected timer to something likearch_mem_counter.I guess ARMv7 would allow you to have mmio without cp15 (AFAIK ARMv8 does not). I don't see any dts in
arch/armthat contains an arm,armv7-timer-mem node without an arm,armv7-timer node, though.
I only know of an ARMv7 device that is like this but the support for it isn't in linus' tree.
Quoted 5 lines
If this is a practical concern, I think using
CONFIG_ARCH_CLOCKSOURCE_DATAis perhaps a better way to communicate whether cp15 access is available. That's how the x86 vdso, for example, decides between using HPET vs TSC etc.
I don't quite follow why it's any better than changing the string because we only really care about using cp15. If we cared about using cp15 vs mmio it might make sense.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
v6 cover ARM: vdso gettimeofday using generic timer architecture
In reply to Nathan LynchQuoted 3 lines · Nathan Lynch
- Build vdso.so with -lgcc: calls to
__lshrdi3,__divsi3sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.
This rather worries me.
For a start, the toolchain I use for cross-building kernels (which I build myself from gnu.org source) never has a libgcc with it - that's because in order to build libgcc, I need a libc, and I don't want to have a full cross environment on my machine just to build the soddin compiler.
So, I want to be able to build kernels without having a libgcc sitting around.
Second point here is that we have multiple different versions of userspace crap with multiple different ABIs. Think about armel vs armhf for starters. There's at least *three* different ELF formats - OABI, EABI armel, EABI armhf. Okay, we can forget about OABI, but what about the other two? What about single zImage where you may want a single kernel image which can run on either flavour?
It is not possible to build a single .so which is compatible with both - an armhf dynamic linker rejects armel outright, and vice versa.
This, to me, sounds like one big fail... and as far as I'm aware, the kernel has no idea itself which flavour of userspace is running, so it has no idea which flavour of VDSO to offer (if it even had both.)
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.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 4 lines · Russell King - ARM Linux
Quoted 3 lines · Nathan Lynch
- Build vdso.so with -lgcc: calls to
__lshrdi3,__divsi3sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.
After reading Russell's concerns below, I had a quick play with these patches, and I noticed that the libgcc dependencies are actually only present when compiling -Os. However, with normal optimization enabled (which most people are using anyway), you don't need libgcc at all. So why not override -O2 optimization for vdso.so, and be done with it?
WIth -Os:
Archive member included because of file (symbol)
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_divsi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_idiv) /usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_lshrdi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_llsr)
Without CONFIG_OPTIMIZE_FOR_SIZE, no archive members are included at all.
Signature · 1 line
Ard.
Quoted 34 lines
This rather worries me.
For a start, the toolchain I use for cross-building kernels (which I build myself from gnu.org source) never has a libgcc with it - that's because in order to build libgcc, I need a libc, and I don't want to have a full cross environment on my machine just to build the soddin compiler.
So, I want to be able to build kernels without having a libgcc sitting around.
Second point here is that we have multiple different versions of userspace crap with multiple different ABIs. Think about armel vs armhf for starters. There's at least *three* different ELF formats - OABI, EABI armel, EABI armhf. Okay, we can forget about OABI, but what about the other two? What about single zImage where you may want a single kernel image which can run on either flavour?
It is not possible to build a single .so which is compatible with both - an armhf dynamic linker rejects armel outright, and vice versa.
This, to me, sounds like one big fail... and as far as I'm aware, the kernel has no idea itself which flavour of userspace is running, so it has no idea which flavour of VDSO to offer (if it even had both.)
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it._______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 16 lines · Ard Biesheuvel
Quoted 4 lines · Russell King - ARM Linux
Quoted 3 lines · Nathan Lynch
- Build vdso.so with -lgcc: calls to
__lshrdi3,__divsi3sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.After reading Russell's concerns below, I had a quick play with these patches, and I noticed that the libgcc dependencies are actually only present when compiling -Os. However, with normal optimization enabled (which most people are using anyway), you don't need libgcc at all. So why not override -O2 optimization for vdso.so, and be done with it?
WIth -Os:
Archive member included because of file (symbol)
Quoted 8 lines
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_divsi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_idiv) /usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_lshrdi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_llsr)Without
CONFIG_OPTIMIZE_FOR_SIZE, no archive members are included at all.
Thanks. I had thought about forcing -O2 in the past but just wasn't confident that it would prevent calls to __divsi3 etc in all situations.
I mean, that's not really a documented or guaranteed behavior of -O2,
is it?
I've now built vdso.so with your suggested change with GCC 4.[4-8] without getting any unresolved symbols, so here's hoping this is a viable option.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 24 lines · Nathan Lynch
Quoted 23 lines · Ard Biesheuvel
Quoted 4 lines · Russell King - ARM Linux
Quoted 3 lines · Nathan Lynch
- Build vdso.so with -lgcc: calls to
__lshrdi3,__divsi3sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.After reading Russell's concerns below, I had a quick play with these patches, and I noticed that the libgcc dependencies are actually only present when compiling -Os. However, with normal optimization enabled (which most people are using anyway), you don't need libgcc at all. So why not override -O2 optimization for vdso.so, and be done with it?
WIth -Os:
Archive member included because of file (symbol)
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_divsi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_idiv) /usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/sf/libgcc.a(_lshrdi3.o)
arch/arm/kernel/vdso/vgettimeofday.o
(__aeabi_llsr)
Quoted 7 lines
Quoted 1 line
Without
CONFIG_OPTIMIZE_FOR_SIZE, no archive members are included at all.Thanks. I had thought about forcing -O2 in the past but just wasn't confident that it would prevent calls to
__divsi3etc in all situations.
I mean, that's not really a documented or guaranteed behavior of -O2,
is it?
No it is not, unfortunately. But I agree with Russell that pulling in bits of libgcc.a into your vdso is a bad idea.
It would be interesting to find out why exactly these dependencies are there, so you can work around them.
And if that is not an option, it would be preferable IMO to duplicate __aeabi_idiv under vdso/ somewhere if you really depend on it.
Quoted 4 lines
I've now built vdso.so with your suggested change with GCC 4.[4-8] without getting any unresolved symbols, so here's hoping this is a viable option.
Signature · 1 line
Ard.
v6 cover ARM: vdso gettimeofday using generic timer architecture
In reply to Russell King - ARM LinuxQuoted 7 lines · Russell King - ARM Linux
Quoted 3 lines · Nathan Lynch
- Build vdso.so with -lgcc: calls to
__lshrdi3,__divsi3sometimes emitted (especially with -Os). Override certain libgcc functions to prevent undefined symbols.This rather worries me.
Quoted 8 lines
For a start, the toolchain I use for cross-building kernels (which I build myself from gnu.org source) never has a libgcc with it - that's because in order to build libgcc, I need a libc, and I don't want to have a full cross environment on my machine just to build the soddin compiler.
So, I want to be able to build kernels without having a libgcc sitting around.
I should be able to accommodate that (see Ard's suggestion for a possible approach).
Quoted 6 lines
Second point here is that we have multiple different versions of userspace crap with multiple different ABIs. Think about armel vs armhf for starters. There's at least *three* different ELF formats - OABI, EABI armel, EABI armhf. Okay, we can forget about OABI, but what about the other two? What about single zImage where you may want a single kernel image which can run on either flavour?
I confess I had not contemplated that use case.
Quoted 6 lines
It is not possible to build a single .so which is compatible with both - an armhf dynamic linker rejects armel outright, and vice versa.
This, to me, sounds like one big fail... and as far as I'm aware, the kernel has no idea itself which flavour of userspace is running, so it has no idea which flavour of VDSO to offer (if it even had both.)
Maybe I'm confused about something, but I'm able to use the vdso fine with an armhf userspace:
# readelf -A vdso.txt # dumped from /proc/pid/mem
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "6K"
Tag_CPU_arch: v6K
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_FP_arch: VFPv2
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int
Tag_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
# readelf -A /usr/bin/vdsotest
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7-A"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3-D16
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_rounding: Needed
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_HardFP_use: SP and DP
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
Tag_MPextension_use: Allowed
Tag_Virtualization_use: TrustZone
# LD_TRACE_LOADED_OBJECTS=1 /usr/bin/vdsotest
linux-vdso.so.1 (0xbec96000)
librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6fca000)
libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xb6fbf000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6ed8000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0
(0xb6ebd000)
/lib/ld-linux-armhf.so.3 (0xb6fd8000)
# vdsotest -v clock-gettime-realtime bench
clock-gettime-realtime: syscalls = 324192, vdso calls = 3282333
clock-gettime-realtime system calls per second: 648309
clock-gettime-realtime vdso calls per second: 6563926 (10.12x speedup)(That's with a kernel with lots of debugging enabled, don't get excited about the speedup reported.)
The test program (vdsotest) is using dlsym to get at the vdso and the glibc is straight from a Linaro toolchain, no vdso patches.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 2 lines · Nathan Lynch
Maybe I'm confused about something, but I'm able to use the vdso fine with an armhf userspace:
On my Dove CuBox, I have both armel and armhf binaries. All armel stuff lives in /armel (the machine used to run ubuntu 12.04 armel but now runs ubuntu 12.04 armhf.)
root at cubox:~# LD_TRACE_LOADED_OBJECTS=1 /armel/lib/arm-linux-gnueabi/ld-linux.so.3 --library-path /lib/arm-linux-gnueabihf/ /armel/bin/cat root at cubox:~# strace env LD_TRACE_LOADED_OBJECTS=1 /armel/lib/arm-linux-gnueabi/ld-linux.so.3 --library-path /lib/arm-linux-gnueabihf/ /armel/bin/cat
...open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\355p\1\0004\0\0\0"..., 512) = 512lseek(3, 888764, SEEK_SET) = 888764read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1360) = 1360lseek(3, 888324, SEEK_SET) = 888324read(3, "A4\0\0\0aeabi\0\1*\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 53) = 53exit_group(1) = ?
So there we have an armel dynamic linker with an armel binary encountering an armhf library and silently failing. Now let's try it the other way around:
root at cubox:~# strace env LD_TRACE_LOADED_OBJECTS=1 /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 --library-path /armel/lib/arm-linux-gnueabi/ /bin/cat
...open("/armel/lib/arm-linux-gnueabi/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\355p\1\0004\0\0\0"..., 512) = 512lseek(3, 880572, SEEK_SET) = 880572read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1360) = 1360lseek(3, 880132, SEEK_SET) = 880132
read(3, "A2\0\0\0aeabi\0\1(\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 51) = 51exit_group(1) = ?
The linker again silently throws its toys out the pram.
To prove that it's a working environment:
root at cubox:~# strace env LD_TRACE_LOADED_OBJECTS=1 /armel/lib/arm-linux-gnueabi/ld-linux.so.3 --library-path /armel/lib/arm-linux-gnueabi/ /armel/bin/cat open("/armel/lib/arm-linux-gnueabi/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\355p\1\0004\0\0\0"..., 512) = 512lseek(3, 880572, SEEK_SET) = 880572read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1360) = 1360lseek(3, 880132, SEEK_SET) = 880132
read(3, "A2\0\0\0aeabi\0\1(\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 51) = 51fstat64(3, {st_mode=S_IFREG|0755, st_size=881932, ...}) = 0
...set_tls(0xb6e544c0, 0xb6e54b98, 0xb6f59048, 0xb6e544c0, 0xb6f374f0) = 0
writev(1, [{"\t", 1}, {"libc.so.6", 9}, {" => ", 4}, {"/armel/lib/arm-linux-gnueabi/lib"..., 38}, {" (0x", 4}, {"b6e55000", 8}, {")\n", 2}], 7 libc.so.6 => /armel/lib/arm-linux-gnueabi/libc.so.6 (0xb6e55000) ) = 66
writev(1, [{"\t", 1}, {"/lib/ld-linux.so.3", 18}, {" => ", 4}, {"/armel/lib/arm-linux-gnueabi/ld-"..., 42}, {" (0x", 4}, {"b6f3a000", 8}, {")\n", 2}], 7/lib/ld-linux.so.3 => /armel/lib/arm-linux-gnueabi/ld-linux.so.3 (0xb6f3a000)
) = 79exit_group(0) = ?
and of course the armhf environment works because that's the one the machine currently boots.
The obvious question therefore is, if the dynamic linker throws its toys out if it encounters a wrong-float-ABI library during a standard library search, why would it _not_ throw its toys out on dlsym. The difference in behaviour would to me seem to be a bug - both should behave the same, though of course not throwing its toys out, but instead producing an error _or_ accepting the difference. Given that it's an ABI difference, rejecting the library is the only sane approach.
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.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 8 lines · Russell King - ARM Linux
The obvious question therefore is, if the dynamic linker throws its toys out if it encounters a wrong-float-ABI library during a standard library search, why would it _not_ throw its toys out on dlsym. The difference in behaviour would to me seem to be a bug - both should behave the same, though of course not throwing its toys out, but instead producing an error _or_ accepting the difference. Given that it's an ABI difference, rejecting the library is the only sane approach.
The VDSO would appear to not be subject to the same validation that a file-based DSO is. I'll dig deeper into this to understand exactly what's going on, but I have a guess as to why the VDSO happens to work with armhf userspace: the calling convention is different only for floating point arguments, and there are none in the VDSO routines.
v6 cover ARM: vdso gettimeofday using generic timer architecture
Quoted 10 lines · Nathan Lynch
Quoted 8 lines · Russell King - ARM Linux
The obvious question therefore is, if the dynamic linker throws its toys out if it encounters a wrong-float-ABI library during a standard library search, why would it _not_ throw its toys out on dlsym. The difference in behaviour would to me seem to be a bug - both should behave the same, though of course not throwing its toys out, but instead producing an error _or_ accepting the difference. Given that it's an ABI difference, rejecting the library is the only sane approach.
Quoted 5 lines
The VDSO would appear to not be subject to the same validation that a file-based DSO is. I'll dig deeper into this to understand exactly what's going on, but I have a guess as to why the VDSO happens to work with armhf userspace: the calling convention is different only for floating point arguments, and there are none in the VDSO routines.
I don't believe the dynamic linker has the necessary information to know whether any functions take FP arguments. I have some armel libraries which definitely make no use of FP, and the linker refuses to use them with armhf.
It's something that the linker doesn't take account of either - we've had issues in the kernel with differing float ABIs which cause hard errors when two dissimilar objects are tried to be linked, even though they make no use of FP. They just seem to need to be marked differently for stuff to complain/reject them.
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.