[PATCH v7 7/9] ARM: add vdso user-space code
Andy Lutomirski
luto at amacapital.net
Mon Jun 30 14:29:28 PDT 2014
On 06/22/2014 08:11 PM, Nathan Lynch wrote:
> 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.
>
> Signed-off-by: Nathan Lynch <nathan_lynch at mentor.com>
> diff --git a/arch/arm/kernel/vdso/Makefile b/arch/arm/kernel/vdso/Makefile
> new file mode 100644
> index 000000000000..ceb712a7626c
> --- /dev/null
> +++ b/arch/arm/kernel/vdso/Makefile
> @@ -0,0 +1,59 @@
> +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 \
> + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
Does this need -DDISABLE_BRANCH_PROFILING?
> diff --git a/arch/arm/kernel/vdso/checkundef.sh b/arch/arm/kernel/vdso/checkundef.sh
> new file mode 100755
> index 000000000000..185c30da202b
> --- /dev/null
> +++ b/arch/arm/kernel/vdso/checkundef.sh
> @@ -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?
> diff --git a/arch/arm/kernel/vdso/datapage.S b/arch/arm/kernel/vdso/datapage.S
> new file mode 100644
> index 000000000000..fbf36d75da06
> --- /dev/null
> +++ b/arch/arm/kernel/vdso/datapage.S
> @@ -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)
Can you translate this into English for the non-ARM-speakers here?
> +
> +#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;
> +}
> +
> +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
More information about the linux-arm-kernel
mailing list