Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8512287a authored by Nathan Lynch's avatar Nathan Lynch Committed by Russell King
Browse files

ARM: 8330/1: add VDSO user-space code



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.

The VDSO can service gettimeofday and clock_gettime when
CONFIG_ARM_ARCH_TIMER is enabled and the architected timer is present
(and correctly configured).  It reads the CP15-based virtual counter
to compute high-resolution timestamps.

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.

Signed-off-by: default avatarNathan Lynch <nathan_lynch@mentor.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 1713ce7c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -25,6 +25,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>

@@ -209,6 +210,10 @@ int main(void)
  DEFINE(KVM_VGIC_VCTRL,	offsetof(struct kvm, arch.vgic.vctrl_base));
#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; 
}
+1 −0
Original line number Diff line number Diff line
vdso.lds

arch/arm/vdso/Makefile

0 → 100644
+74 −0
Original line number Diff line number Diff line
hostprogs-y := vdsomunge

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 -DDISABLE_BRANCH_PROFILING
ccflags-y += -Wl,--no-undefined $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)

obj-y += vdso.o
extra-y += vdso.lds
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)

CFLAGS_REMOVE_vdso.o = -pg

# Force -O2 to avoid libgcc dependencies
CFLAGS_REMOVE_vgettimeofday.o = -pg -Os
CFLAGS_vgettimeofday.o = -O2

# Disable gcov profiling for VDSO code
GCOV_PROFILE := n

# Force dependency
$(obj)/vdso.o : $(obj)/vdso.so

# Link rule for the .so file
$(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE
	$(call if_changed,vdsold)

$(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/vdsomunge FORCE
	$(call if_changed,vdsomunge)

# Strip rule for the .so file
$(obj)/%.so: OBJCOPYFLAGS := -S
$(obj)/%.so: $(obj)/%.so.dbg FORCE
	$(call if_changed,objcopy)

# Actual build commands
quiet_cmd_vdsold = VDSO    $@
      cmd_vdsold = $(CC) $(c_flags) -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) \
                   $(call cc-ldoption, -Wl$(comma)--build-id) \
                   -Wl,-Bsymbolic -Wl,-z,max-page-size=4096 \
                   -Wl,-z,common-page-size=4096 -o $@

quiet_cmd_vdsomunge = MUNGE   $@
      cmd_vdsomunge = $(objtree)/$(obj)/vdsomunge $< $@

#
# Install the unstripped copy of vdso.so.dbg.  If our toolchain
# supports build-id, install .build-id links as well.
#
# Cribbed from arch/x86/vdso/Makefile.
#
quiet_cmd_vdso_install = INSTALL $<
define cmd_vdso_install
	cp $< "$(MODLIB)/vdso/vdso.so"; \
	if readelf -n $< | grep -q 'Build ID'; then \
	  buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
	  first=`echo $$buildid | cut -b-2`; \
	  last=`echo $$buildid | cut -b3-`; \
	  mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
	  ln -sf "../../vdso.so" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
	fi
endef

$(MODLIB)/vdso: FORCE
	@mkdir -p $(MODLIB)/vdso

PHONY += vdso_install
vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso FORCE
	$(call cmd,vdso_install)
+15 −0
Original line number Diff line number Diff line
#include <linux/linkage.h>
#include <asm/asm-offsets.h>

	.align 2
.L_vdso_data_ptr:
	.long	_start - . - VDSO_DATA_SIZE

ENTRY(__get_datapage)
	.fnstart
	adr	r0, .L_vdso_data_ptr
	ldr	r1, [r0]
	add	r0, r0, r1
	bx	lr
	.fnend
ENDPROC(__get_datapage)

arch/arm/vdso/vdso.S

0 → 100644
+35 −0
Original line number Diff line number Diff line
/*
 * 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 <will.deacon@arm.com>
 */

#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/const.h>
#include <asm/page.h>

	__PAGE_ALIGNED_DATA

	.globl vdso_start, vdso_end
	.balign PAGE_SIZE
vdso_start:
	.incbin "arch/arm/vdso/vdso.so"
	.balign PAGE_SIZE
vdso_end:

	.previous
Loading