-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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: Nathan Lynch <nathan_lynch@mentor.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
- Loading branch information
Nathan Lynch
authored and
Russell King
committed
Mar 27, 2015
1 parent
1713ce7
commit 8512287
Showing
8 changed files
with
700 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
vdso.lds |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <linux/linkage.h> | ||
#include <asm/asm-offsets.h> | ||
|
||
.align 2 | ||
.L_vdso_data_ptr: | ||
.long _start - . - VDSO_DATA_SIZE | ||
|
||
ENTRY(__get_datapage) | ||
.fnstart | ||
adr r0, .L_vdso_data_ptr | ||
ldr r1, [r0] | ||
add r0, r0, r1 | ||
bx lr | ||
.fnend | ||
ENDPROC(__get_datapage) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Adapted from arm64 version. | ||
* | ||
* GNU linker script for the VDSO library. | ||
* | ||
* 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> | ||
* Heavily based on the vDSO linker scripts for other archs. | ||
*/ | ||
|
||
#include <linux/const.h> | ||
#include <asm/page.h> | ||
#include <asm/vdso.h> | ||
|
||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") | ||
OUTPUT_ARCH(arm) | ||
|
||
SECTIONS | ||
{ | ||
PROVIDE(_start = .); | ||
|
||
. = SIZEOF_HEADERS; | ||
|
||
.hash : { *(.hash) } :text | ||
.gnu.hash : { *(.gnu.hash) } | ||
.dynsym : { *(.dynsym) } | ||
.dynstr : { *(.dynstr) } | ||
.gnu.version : { *(.gnu.version) } | ||
.gnu.version_d : { *(.gnu.version_d) } | ||
.gnu.version_r : { *(.gnu.version_r) } | ||
|
||
.note : { *(.note.*) } :text :note | ||
|
||
|
||
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
.eh_frame : { KEEP (*(.eh_frame)) } :text | ||
|
||
.dynamic : { *(.dynamic) } :text :dynamic | ||
|
||
.rodata : { *(.rodata*) } :text | ||
|
||
.text : { *(.text*) } :text =0xe7f001f2 | ||
|
||
.got : { *(.got) } | ||
.rel.plt : { *(.rel.plt) } | ||
|
||
/DISCARD/ : { | ||
*(.note.GNU-stack) | ||
*(.data .data.* .gnu.linkonce.d.* .sdata*) | ||
*(.bss .sbss .dynbss .dynsbss) | ||
} | ||
} | ||
|
||
/* | ||
* We must supply the ELF program headers explicitly to get just one | ||
* PT_LOAD segment, and set the flags explicitly to make segments read-only. | ||
*/ | ||
PHDRS | ||
{ | ||
text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ | ||
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
note PT_NOTE FLAGS(4); /* PF_R */ | ||
eh_frame_hdr PT_GNU_EH_FRAME; | ||
} | ||
|
||
VERSION | ||
{ | ||
LINUX_2.6 { | ||
global: | ||
__vdso_clock_gettime; | ||
__vdso_gettimeofday; | ||
local: *; | ||
}; | ||
} |
Oops, something went wrong.