[PATCH] riscv: explicitly use symbol offsets for VDSO v2

0 views
Skip to first unread message

Saleem Abdulrasool

unread,
Aug 2, 2021, 5:00:49 PM8/2/21
to linux...@lists.infradead.org, linux-...@vger.kernel.org, Palmer Dabbelt, Nathan Chancellor, Nick Desaulniers, Bill Wendling, clang-bu...@googlegroups.com, Saleem Abdulrasool
The current implementation of the `__rt_sigaction` reference computed an
absolute offset relative to the mapped base of the VDSO. While this can
be handled in the medlow model, the medany model cannot handle this as
it is meant to be position independent. The current implementation
relied on the BFD linker relaxing the PC-relative relocation into an
absolute relocation as it was a near-zero address allowing it to be
referenced relative to `zero`.

We now extract the offsets and create a generated header allowing the
build with LLVM and lld to succeed as we no longer depend on the linker
rewriting address references near zero. This change was largely
modelled after the ARM64 target which does something similar.

Signed-off-by: Saleem Abdulrasool <abdu...@google.com>
---
arch/riscv/Makefile | 4 ++++
arch/riscv/include/asm/vdso.h | 11 ++--------
arch/riscv/kernel/vdso/Makefile | 25 ++++++++++------------
arch/riscv/kernel/vdso/gen_vdso_offsets.sh | 5 +++++
arch/riscv/kernel/vdso/so2s.sh | 6 ------
5 files changed, 22 insertions(+), 29 deletions(-)
create mode 100755 arch/riscv/kernel/vdso/gen_vdso_offsets.sh
delete mode 100755 arch/riscv/kernel/vdso/so2s.sh

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index bc74afdbf31e..e026b2d0a5a4 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -108,6 +108,10 @@ PHONY += vdso_install
vdso_install:
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@

+prepare: vdso_prepare
+vdso_prepare: prepare0
+ $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
+
ifneq ($(CONFIG_XIP_KERNEL),y)
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
KBUILD_IMAGE := $(boot)/loader.bin
diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
index 1453a2f563bc..098795262b92 100644
--- a/arch/riscv/include/asm/vdso.h
+++ b/arch/riscv/include/asm/vdso.h
@@ -9,24 +9,17 @@
#define _ASM_RISCV_VDSO_H

#include <linux/types.h>
+#include <generated/vdso-offsets.h>

#ifndef CONFIG_GENERIC_TIME_VSYSCALL
struct vdso_data {
};
#endif

-/*
- * The VDSO symbols are mapped into Linux so we can just use regular symbol
- * addressing to get their offsets in userspace. The symbols are mapped at an
- * offset of 0, but since the linker must support setting weak undefined
- * symbols to the absolute address 0 it also happens to support other low
- * addresses even when the code model suggests those low addresses would not
- * otherwise be availiable.
- */
#define VDSO_SYMBOL(base, name) \
({ \
extern const char __vdso_##name[]; \
- (void __user *)((unsigned long)(base) + __vdso_##name); \
+ (void __user *)((unsigned long)(base) + __vdso_##name##_offset); \
})

asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index 24d936c147cd..f8cb9144a284 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -23,10 +23,10 @@ ifneq ($(c-gettimeofday-y),)
endif

# Build rules
-targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))

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

# Disable -pg to prevent insert call site
@@ -43,20 +43,22 @@ $(obj)/vdso.o: $(obj)/vdso.so
# link rule for the .so file, .lds has to be first
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
$(call if_changed,vdsold)
-LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
+LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \
--build-id=sha1 --hash-style=both --eh-frame-hdr

-# We also create a special relocatable object that should mirror the symbol
-# table and layout of the linked DSO. With ld --just-symbols we can then
-# refer to these symbols in the kernel code rather than hand-coded addresses.
-$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
- $(call if_changed,so2s)
-
# strip rule for the .so file
$(obj)/%.so: OBJCOPYFLAGS := -S
$(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)

+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+ cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
# actual build commands
# The DSO images are built using a special linker script
# Make sure only to export the intended __vdso_xxx symbol offsets.
@@ -65,11 +67,6 @@ quiet_cmd_vdsold = VDSOLD $@
$(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
rm $@.tmp

-# Extracts symbol offsets from the VDSO, converting them into an assembly file
-# that contains the same symbols at the same offsets.
-quiet_cmd_so2s = SO2S $@
- cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
-
# install commands for the unstripped file
quiet_cmd_vdso_install = INSTALL $@
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
diff --git a/arch/riscv/kernel/vdso/gen_vdso_offsets.sh b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
new file mode 100755
index 000000000000..c2e5613f3495
--- /dev/null
+++ b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+LC_ALL=C
+sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p'
diff --git a/arch/riscv/kernel/vdso/so2s.sh b/arch/riscv/kernel/vdso/so2s.sh
deleted file mode 100755
index e64cb6d9440e..000000000000
--- a/arch/riscv/kernel/vdso/so2s.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0+
-# Copyright 2020 Palmer Dabbelt <palmer...@google.com>
-
-sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \
-| grep '^\.'
--
2.32.0.554.ge1b32706d8-goog

kernel test robot

unread,
Aug 2, 2021, 7:15:04 PM8/2/21
to Saleem Abdulrasool, linux...@lists.infradead.org, linux-...@vger.kernel.org, kbuil...@lists.01.org, Palmer Dabbelt, Nathan Chancellor, Nick Desaulniers, Bill Wendling, clang-bu...@googlegroups.com, Saleem Abdulrasool
Hi Saleem,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linux/master]
[also build test ERROR on linus/master v5.14-rc3 next-20210730]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Saleem-Abdulrasool/riscv-explicitly-use-symbol-offsets-for-VDSO-v2/20210803-050150
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 349a2d52ffe59b7a0c5876fa7ee9f3eaf188b830
config: riscv-nommu_k210_defconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 10.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/82dd1f24fc79924938e3633ecf573c7973d938f6
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Saleem-Abdulrasool/riscv-explicitly-use-symbol-offsets-for-VDSO-v2/20210803-050150
git checkout 82dd1f24fc79924938e3633ecf573c7973d938f6
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-10.3.0 make.cross ARCH=riscv

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <l...@intel.com>

All errors (new ones prefixed by >>):

arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_clock_gettime':
>> arch/riscv/kernel/vdso/vgettimeofday.c:16:9: error: implicit declaration of function '__cvdso_clock_gettime'; did you mean '__vdso_clock_gettime'? [-Werror=implicit-function-declaration]
16 | return __cvdso_clock_gettime(clock, ts);
| ^~~~~~~~~~~~~~~~~~~~~
| __vdso_clock_gettime
arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_gettimeofday':
>> arch/riscv/kernel/vdso/vgettimeofday.c:23:9: error: implicit declaration of function '__cvdso_gettimeofday'; did you mean '__vdso_gettimeofday'? [-Werror=implicit-function-declaration]
23 | return __cvdso_gettimeofday(tv, tz);
| ^~~~~~~~~~~~~~~~~~~~
| __vdso_gettimeofday
arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_clock_getres':
>> arch/riscv/kernel/vdso/vgettimeofday.c:30:9: error: implicit declaration of function '__cvdso_clock_getres'; did you mean '__vdso_clock_getres'? [-Werror=implicit-function-declaration]
30 | return __cvdso_clock_getres(clock_id, res);
| ^~~~~~~~~~~~~~~~~~~~
| __vdso_clock_getres
cc1: some warnings being treated as errors
--
arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_clock_gettime':
>> arch/riscv/kernel/vdso/vgettimeofday.c:16:9: error: implicit declaration of function '__cvdso_clock_gettime'; did you mean '__vdso_clock_gettime'? [-Werror=implicit-function-declaration]
16 | return __cvdso_clock_gettime(clock, ts);
| ^~~~~~~~~~~~~~~~~~~~~
| __vdso_clock_gettime
arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_gettimeofday':
>> arch/riscv/kernel/vdso/vgettimeofday.c:23:9: error: implicit declaration of function '__cvdso_gettimeofday'; did you mean '__vdso_gettimeofday'? [-Werror=implicit-function-declaration]
23 | return __cvdso_gettimeofday(tv, tz);
| ^~~~~~~~~~~~~~~~~~~~
| __vdso_gettimeofday
arch/riscv/kernel/vdso/vgettimeofday.c: In function '__vdso_clock_getres':
>> arch/riscv/kernel/vdso/vgettimeofday.c:30:9: error: implicit declaration of function '__cvdso_clock_getres'; did you mean '__vdso_clock_getres'? [-Werror=implicit-function-declaration]
30 | return __cvdso_clock_getres(clock_id, res);
| ^~~~~~~~~~~~~~~~~~~~
| __vdso_clock_getres
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:273: arch/riscv/kernel/vdso/vgettimeofday.o] Error 1
make[2]: Target 'include/generated/vdso-offsets.h' not remade because of errors.
make[1]: *** [arch/riscv/Makefile:114: vdso_prepare] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:215: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.


vim +16 arch/riscv/kernel/vdso/vgettimeofday.c

ad5d1122b82fbd Vincent Chen 2020-06-09 11
e93b327dbf3d37 Vincent Chen 2020-06-23 12 extern
e93b327dbf3d37 Vincent Chen 2020-06-23 13 int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
ad5d1122b82fbd Vincent Chen 2020-06-09 14 int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
ad5d1122b82fbd Vincent Chen 2020-06-09 15 {
ad5d1122b82fbd Vincent Chen 2020-06-09 @16 return __cvdso_clock_gettime(clock, ts);
ad5d1122b82fbd Vincent Chen 2020-06-09 17 }
ad5d1122b82fbd Vincent Chen 2020-06-09 18
e93b327dbf3d37 Vincent Chen 2020-06-23 19 extern
e93b327dbf3d37 Vincent Chen 2020-06-23 20 int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
ad5d1122b82fbd Vincent Chen 2020-06-09 21 int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
ad5d1122b82fbd Vincent Chen 2020-06-09 22 {
ad5d1122b82fbd Vincent Chen 2020-06-09 @23 return __cvdso_gettimeofday(tv, tz);
ad5d1122b82fbd Vincent Chen 2020-06-09 24 }
ad5d1122b82fbd Vincent Chen 2020-06-09 25
e93b327dbf3d37 Vincent Chen 2020-06-23 26 extern
e93b327dbf3d37 Vincent Chen 2020-06-23 27 int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
ad5d1122b82fbd Vincent Chen 2020-06-09 28 int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res)
ad5d1122b82fbd Vincent Chen 2020-06-09 29 {
ad5d1122b82fbd Vincent Chen 2020-06-09 @30 return __cvdso_clock_getres(clock_id, res);

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuil...@lists.01.org
.config.gz

Palmer Dabbelt

unread,
Aug 3, 2021, 11:55:01 PM8/3/21
to abdu...@google.com, linux...@lists.infradead.org, linux-...@vger.kernel.org, nat...@kernel.org, ndesau...@google.com, mo...@google.com, clang-bu...@googlegroups.com, abdu...@google.com
This is giving me some unused variable warnings:

In file included from arch/riscv/kernel/signal.c:16:
arch/riscv/kernel/signal.c: In function ‘setup_rt_frame’:
./arch/riscv/include/asm/vdso.h:21:20: warning: unused variable ‘__vdso_rt_sigreturn’ [-Wunused-variable]
21 | extern const char __vdso_##name[]; \
| ^~~~~~~
arch/riscv/kernel/signal.c:197:28: note: in expansion of macro ‘VDSO_SYMBOL’
197 | regs->ra = (unsigned long)VDSO_SYMBOL(
| ^~~~~~~~~~~

Saleem Abdulrasool

unread,
Aug 4, 2021, 1:35:43 PM8/4/21
to Palmer Dabbelt, linux...@lists.infradead.org, linux-...@vger.kernel.org, nat...@kernel.org, Nick Desaulniers, Bill Wendling, clang-bu...@googlegroups.com
Thanks Palmer,

It seems that there was a difference in diagnostics between gcc and
clang. The diagnostic indicated that I didn't scrub hard enough
during the cleanups. I've sent out an updated version. Thank you for
informing me of this missed cleanup!
Reply all
Reply to author
Forward
0 new messages