forked from Freescale/linux-fslc
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide the arm64 compat (AArch32) vDSO in kernel/vdso32 in a similar way to what happens in kernel/vdso. The compat vDSO leverages on an adaptation of the arm architecture code with few changes: - Use of lib/vdso for gettimeofday - Implement a syscall based fallback - Introduce clock_getres() for the compat library - Implement trampolines - Implement elf note To build the compat vDSO a 32 bit compiler is required and needs to be specified via CONFIG_CROSS_COMPILE_COMPAT_VDSO. The code is not yet enabled as other prerequisites are missing. Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Shijith Thotton <sthotton@marvell.com> Tested-by: Andre Przywara <andre.przywara@arm.com> Cc: linux-arch@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@vger.kernel.org Cc: linux-kselftest@vger.kernel.org Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Russell King <linux@armlinux.org.uk> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Paul Burton <paul.burton@mips.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Mark Salyzyn <salyzyn@android.com> Cc: Peter Collingbourne <pcc@google.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Huw Davies <huw@codeweavers.com> Link: https://lkml.kernel.org/r/20190621095252.32307-11-vincenzo.frascino@arm.com
- Loading branch information
Showing
9 changed files
with
584 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2018 ARM Limited | ||
*/ | ||
#ifndef __COMPAT_BARRIER_H | ||
#define __COMPAT_BARRIER_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
/* | ||
* Warning: This code is meant to be used with | ||
* ENABLE_COMPAT_VDSO only. | ||
*/ | ||
#ifndef ENABLE_COMPAT_VDSO | ||
#error This header is meant to be used with ENABLE_COMPAT_VDSO only | ||
#endif | ||
|
||
#ifdef dmb | ||
#undef dmb | ||
#endif | ||
|
||
#if __LINUX_ARM_ARCH__ >= 7 | ||
#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory") | ||
#elif __LINUX_ARM_ARCH__ == 6 | ||
#define dmb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ | ||
: : "r" (0) : "memory") | ||
#else | ||
#define dmb(x) __asm__ __volatile__ ("" : : : "memory") | ||
#endif | ||
|
||
#if __LINUX_ARM_ARCH__ >= 8 | ||
#define aarch32_smp_mb() dmb(ish) | ||
#define aarch32_smp_rmb() dmb(ishld) | ||
#define aarch32_smp_wmb() dmb(ishst) | ||
#else | ||
#define aarch32_smp_mb() dmb(ish) | ||
#define aarch32_smp_rmb() aarch32_smp_mb() | ||
#define aarch32_smp_wmb() dmb(ishst) | ||
#endif | ||
|
||
|
||
#undef smp_mb | ||
#undef smp_rmb | ||
#undef smp_wmb | ||
|
||
#define smp_mb() aarch32_smp_mb() | ||
#define smp_rmb() aarch32_smp_rmb() | ||
#define smp_wmb() aarch32_smp_wmb() | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __COMPAT_BARRIER_H */ |
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,108 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2018 ARM Limited | ||
*/ | ||
#ifndef __ASM_VDSO_GETTIMEOFDAY_H | ||
#define __ASM_VDSO_GETTIMEOFDAY_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <asm/unistd.h> | ||
#include <uapi/linux/time.h> | ||
|
||
#include <asm/vdso/compat_barrier.h> | ||
|
||
#define VDSO_HAS_CLOCK_GETRES 1 | ||
|
||
static __always_inline | ||
int gettimeofday_fallback(struct __kernel_old_timeval *_tv, | ||
struct timezone *_tz) | ||
{ | ||
register struct timezone *tz asm("r1") = _tz; | ||
register struct __kernel_old_timeval *tv asm("r0") = _tv; | ||
register long ret asm ("r0"); | ||
register long nr asm("r7") = __NR_compat_gettimeofday; | ||
|
||
asm volatile( | ||
" swi #0\n" | ||
: "=r" (ret) | ||
: "r" (tv), "r" (tz), "r" (nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline | ||
long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) | ||
{ | ||
register struct __kernel_timespec *ts asm("r1") = _ts; | ||
register clockid_t clkid asm("r0") = _clkid; | ||
register long ret asm ("r0"); | ||
register long nr asm("r7") = __NR_compat_clock_gettime64; | ||
|
||
asm volatile( | ||
" swi #0\n" | ||
: "=r" (ret) | ||
: "r" (clkid), "r" (ts), "r" (nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline | ||
int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) | ||
{ | ||
register struct __kernel_timespec *ts asm("r1") = _ts; | ||
register clockid_t clkid asm("r0") = _clkid; | ||
register long ret asm ("r0"); | ||
register long nr asm("r7") = __NR_compat_clock_getres_time64; | ||
|
||
/* The checks below are required for ABI consistency with arm */ | ||
if ((_clkid >= MAX_CLOCKS) && (_ts == NULL)) | ||
return -EINVAL; | ||
|
||
asm volatile( | ||
" swi #0\n" | ||
: "=r" (ret) | ||
: "r" (clkid), "r" (ts), "r" (nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) | ||
{ | ||
u64 res; | ||
|
||
isb(); | ||
asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (res)); | ||
|
||
return res; | ||
} | ||
|
||
static __always_inline const struct vdso_data *__arch_get_vdso_data(void) | ||
{ | ||
const struct vdso_data *ret; | ||
|
||
/* | ||
* This simply puts &_vdso_data into ret. The reason why we don't use | ||
* `ret = _vdso_data` is that the compiler tends to optimise this in a | ||
* very suboptimal way: instead of keeping &_vdso_data in a register, | ||
* it goes through a relocation almost every time _vdso_data must be | ||
* accessed (even in subfunctions). This is both time and space | ||
* consuming: each relocation uses a word in the code section, and it | ||
* has to be loaded at runtime. | ||
* | ||
* This trick hides the assignment from the compiler. Since it cannot | ||
* track where the pointer comes from, it will only use one relocation | ||
* where __arch_get_vdso_data() is called, and then keep the result in | ||
* a register. | ||
*/ | ||
asm volatile("mov %0, %1" : "=r"(ret) : "r"(_vdso_data)); | ||
|
||
return ret; | ||
} | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ |
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,2 @@ | ||
vdso.lds | ||
vdso.so.raw |
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,186 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# | ||
# Makefile for vdso32 | ||
# | ||
|
||
# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before | ||
# the inclusion of generic Makefile. | ||
ARCH_REL_TYPE_ABS := R_ARM_JUMP_SLOT|R_ARM_GLOB_DAT|R_ARM_ABS32 | ||
include $(srctree)/lib/vdso/Makefile | ||
|
||
COMPATCC := $(CROSS_COMPILE_COMPAT)gcc | ||
|
||
# Same as cc-*option, but using COMPATCC instead of CC | ||
cc32-option = $(call try-run,\ | ||
$(COMPATCC) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) | ||
cc32-disable-warning = $(call try-run,\ | ||
$(COMPATCC) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) | ||
cc32-ldoption = $(call try-run,\ | ||
$(COMPATCC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) | ||
|
||
# We cannot use the global flags to compile the vDSO files, the main reason | ||
# being that the 32-bit compiler may be older than the main (64-bit) compiler | ||
# and therefore may not understand flags set using $(cc-option ...). Besides, | ||
# arch-specific options should be taken from the arm Makefile instead of the | ||
# arm64 one. | ||
# As a result we set our own flags here. | ||
|
||
# From top-level Makefile | ||
# NOSTDINC_FLAGS | ||
VDSO_CPPFLAGS := -nostdinc -isystem $(shell $(COMPATCC) -print-file-name=include) | ||
VDSO_CPPFLAGS += $(LINUXINCLUDE) | ||
VDSO_CPPFLAGS += $(KBUILD_CPPFLAGS) | ||
|
||
# Common C and assembly flags | ||
# From top-level Makefile | ||
VDSO_CAFLAGS := $(VDSO_CPPFLAGS) | ||
VDSO_CAFLAGS += $(call cc32-option,-fno-PIE) | ||
ifdef CONFIG_DEBUG_INFO | ||
VDSO_CAFLAGS += -g | ||
endif | ||
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(COMPATCC)), y) | ||
VDSO_CAFLAGS += -DCC_HAVE_ASM_GOTO | ||
endif | ||
|
||
# From arm Makefile | ||
VDSO_CAFLAGS += $(call cc32-option,-fno-dwarf2-cfi-asm) | ||
VDSO_CAFLAGS += -mabi=aapcs-linux -mfloat-abi=soft | ||
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) | ||
VDSO_CAFLAGS += -mbig-endian | ||
else | ||
VDSO_CAFLAGS += -mlittle-endian | ||
endif | ||
|
||
# From arm vDSO Makefile | ||
VDSO_CAFLAGS += -fPIC -fno-builtin -fno-stack-protector | ||
VDSO_CAFLAGS += -DDISABLE_BRANCH_PROFILING | ||
|
||
# Try to compile for ARMv8. If the compiler is too old and doesn't support it, | ||
# fall back to v7. There is no easy way to check for what architecture the code | ||
# is being compiled, so define a macro specifying that (see arch/arm/Makefile). | ||
VDSO_CAFLAGS += $(call cc32-option,-march=armv8-a -D__LINUX_ARM_ARCH__=8,\ | ||
-march=armv7-a -D__LINUX_ARM_ARCH__=7) | ||
|
||
VDSO_CFLAGS := $(VDSO_CAFLAGS) | ||
VDSO_CFLAGS += -DENABLE_COMPAT_VDSO=1 | ||
# KBUILD_CFLAGS from top-level Makefile | ||
VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ | ||
-fno-strict-aliasing -fno-common \ | ||
-Werror-implicit-function-declaration \ | ||
-Wno-format-security \ | ||
-std=gnu89 | ||
VDSO_CFLAGS += -O2 | ||
# Some useful compiler-dependent flags from top-level Makefile | ||
VDSO_CFLAGS += $(call cc32-option,-Wdeclaration-after-statement,) | ||
VDSO_CFLAGS += $(call cc32-option,-Wno-pointer-sign) | ||
VDSO_CFLAGS += $(call cc32-option,-fno-strict-overflow) | ||
VDSO_CFLAGS += $(call cc32-option,-Werror=strict-prototypes) | ||
VDSO_CFLAGS += $(call cc32-option,-Werror=date-time) | ||
VDSO_CFLAGS += $(call cc32-option,-Werror=incompatible-pointer-types) | ||
|
||
# The 32-bit compiler does not provide 128-bit integers, which are used in | ||
# some headers that are indirectly included from the vDSO code. | ||
# This hack makes the compiler happy and should trigger a warning/error if | ||
# variables of such type are referenced. | ||
VDSO_CFLAGS += -D__uint128_t='void*' | ||
# Silence some warnings coming from headers that operate on long's | ||
# (on GCC 4.8 or older, there is unfortunately no way to silence this warning) | ||
VDSO_CFLAGS += $(call cc32-disable-warning,shift-count-overflow) | ||
VDSO_CFLAGS += -Wno-int-to-pointer-cast | ||
|
||
VDSO_AFLAGS := $(VDSO_CAFLAGS) | ||
VDSO_AFLAGS += -D__ASSEMBLY__ | ||
|
||
VDSO_LDFLAGS := $(VDSO_CPPFLAGS) | ||
# From arm vDSO Makefile | ||
VDSO_LDFLAGS += -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 | ||
VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 | ||
VDSO_LDFLAGS += -nostdlib -shared -mfloat-abi=soft | ||
VDSO_LDFLAGS += $(call cc32-ldoption,-Wl$(comma)--hash-style=sysv) | ||
VDSO_LDFLAGS += $(call cc32-ldoption,-Wl$(comma)--build-id) | ||
VDSO_LDFLAGS += $(call cc32-ldoption,-fuse-ld=bfd) | ||
|
||
|
||
# Borrow vdsomunge.c from the arm vDSO | ||
# We have to use a relative path because scripts/Makefile.host prefixes | ||
# $(hostprogs-y) with $(obj) | ||
munge := ../../../arm/vdso/vdsomunge | ||
hostprogs-y := $(munge) | ||
|
||
c-obj-vdso := note.o | ||
c-obj-vdso-gettimeofday := vgettimeofday.o | ||
asm-obj-vdso := sigreturn.o | ||
|
||
ifneq ($(c-gettimeofday-y),) | ||
VDSO_CFLAGS_gettimeofday_o += -include $(c-gettimeofday-y) | ||
endif | ||
|
||
VDSO_CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os | ||
|
||
# Build rules | ||
targets := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw | ||
c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso)) | ||
c-obj-vdso-gettimeofday := $(addprefix $(obj)/, $(c-obj-vdso-gettimeofday)) | ||
asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso)) | ||
obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) | ||
|
||
obj-y += vdso.o | ||
extra-y += vdso.lds | ||
CPPFLAGS_vdso.lds += -P -C -U$(ARCH) | ||
|
||
# Force dependency (vdso.s includes vdso.so through incbin) | ||
$(obj)/vdso.o: $(obj)/vdso.so | ||
|
||
include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE | ||
$(call if_changed,vdsosym) | ||
|
||
# Strip rule for vdso.so | ||
$(obj)/vdso.so: OBJCOPYFLAGS := -S | ||
$(obj)/vdso.so: $(obj)/vdso.so.dbg FORCE | ||
$(call if_changed,objcopy) | ||
|
||
$(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/$(munge) FORCE | ||
$(call if_changed,vdsomunge) | ||
|
||
# Link rule for the .so file, .lds has to be first | ||
$(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE | ||
$(call if_changed,vdsold) | ||
$(call if_changed,vdso_check) | ||
|
||
# Compilation rules for the vDSO sources | ||
$(c-obj-vdso): %.o: %.c FORCE | ||
$(call if_changed_dep,vdsocc) | ||
$(c-obj-vdso-gettimeofday): %.o: %.c FORCE | ||
$(call if_changed_dep,vdsocc_gettimeofday) | ||
$(asm-obj-vdso): %.o: %.S FORCE | ||
$(call if_changed_dep,vdsoas) | ||
|
||
# Actual build commands | ||
quiet_cmd_vdsold = VDSOL $@ | ||
cmd_vdsold = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_LDFLAGS) \ | ||
-Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@ | ||
quiet_cmd_vdsocc = VDSOC $@ | ||
cmd_vdsocc = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) -c -o $@ $< | ||
quiet_cmd_vdsocc_gettimeofday = VDSOC_GTD $@ | ||
cmd_vdsocc_gettimeofday = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) $(VDSO_CFLAGS_gettimeofday_o) -c -o $@ $< | ||
quiet_cmd_vdsoas = VDSOA $@ | ||
cmd_vdsoas = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_AFLAGS) -c -o $@ $< | ||
|
||
quiet_cmd_vdsomunge = MUNGE $@ | ||
cmd_vdsomunge = $(obj)/$(munge) $< $@ | ||
|
||
# Generate vDSO offsets using helper script (borrowed from the 64-bit vDSO) | ||
gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh | ||
quiet_cmd_vdsosym = VDSOSYM $@ | ||
# The AArch64 nm should be able to read an AArch32 binary | ||
cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ | ||
|
||
# Install commands for the unstripped file | ||
quiet_cmd_vdso_install = INSTALL $@ | ||
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so | ||
|
||
vdso.so: $(obj)/vdso.so.dbg | ||
@mkdir -p $(MODLIB)/vdso | ||
$(call cmd,vdso_install) | ||
|
||
vdso_install: vdso.so |
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 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (C) 2012-2018 ARM Limited | ||
* | ||
* This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. | ||
* Here we can supply some information useful to userland. | ||
*/ | ||
|
||
#include <linux/uts.h> | ||
#include <linux/version.h> | ||
#include <linux/elfnote.h> | ||
#include <linux/build-salt.h> | ||
|
||
ELFNOTE32("Linux", 0, LINUX_VERSION_CODE); | ||
BUILD_SALT; |
Oops, something went wrong.