Takashi Iwai 0cac74
From 3631280713464ab9078bde9e6467f244f897c204 Mon Sep 17 00:00:00 2001
Takashi Iwai 0cac74
From: Saleem Abdulrasool <abdulras@google.com>
Takashi Iwai 0cac74
Date: Wed, 4 Aug 2021 17:32:14 +0000
Takashi Iwai 0cac74
Subject: [PATCH] riscv: explicitly use symbol offsets for VDSO
Takashi Iwai 0cac74
Git-commit: fde9c59aebafb91caeed816cc510b56f14aa63ae
Takashi Iwai 0cac74
Patch-mainline: v5.15-rc1
Takashi Iwai 0cac74
References: stable-5.14.12
Takashi Iwai 0cac74
Takashi Iwai 0cac74
[ Upstream commit fde9c59aebafb91caeed816cc510b56f14aa63ae ]
Takashi Iwai 0cac74
Takashi Iwai 0cac74
The current implementation of the `__rt_sigaction` reference computed an
Takashi Iwai 0cac74
absolute offset relative to the mapped base of the VDSO.  While this can
Takashi Iwai 0cac74
be handled in the medlow model, the medany model cannot handle this as
Takashi Iwai 0cac74
it is meant to be position independent.  The current implementation
Takashi Iwai 0cac74
relied on the BFD linker relaxing the PC-relative relocation into an
Takashi Iwai 0cac74
absolute relocation as it was a near-zero address allowing it to be
Takashi Iwai 0cac74
referenced relative to `zero`.
Takashi Iwai 0cac74
Takashi Iwai 0cac74
We now extract the offsets and create a generated header allowing the
Takashi Iwai 0cac74
build with LLVM and lld to succeed as we no longer depend on the linker
Takashi Iwai 0cac74
rewriting address references near zero.  This change was largely
Takashi Iwai 0cac74
modelled after the ARM64 target which does something similar.
Takashi Iwai 0cac74
Takashi Iwai 0cac74
Signed-off-by: Saleem Abdulrasool <abdulras@google.com>
Takashi Iwai 0cac74
Tested-by: Nathan Chancellor <nathan@kernel.org>
Takashi Iwai 0cac74
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
Takashi Iwai 0cac74
Signed-off-by: Sasha Levin <sashal@kernel.org>
Takashi Iwai 0cac74
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 0cac74
Takashi Iwai 0cac74
---
Takashi Iwai 0cac74
 arch/riscv/Makefile                        |  4 ++++
Takashi Iwai 0cac74
 arch/riscv/include/asm/vdso.h              | 14 ++----------
Takashi Iwai 0cac74
 arch/riscv/kernel/vdso/Makefile            | 25 ++++++++++------------
Takashi Iwai 0cac74
 arch/riscv/kernel/vdso/gen_vdso_offsets.sh |  5 +++++
Takashi Iwai 0cac74
 arch/riscv/kernel/vdso/so2s.sh             |  6 ------
Takashi Iwai 0cac74
 5 files changed, 22 insertions(+), 32 deletions(-)
Takashi Iwai 0cac74
 create mode 100755 arch/riscv/kernel/vdso/gen_vdso_offsets.sh
Takashi Iwai 0cac74
 delete mode 100755 arch/riscv/kernel/vdso/so2s.sh
Takashi Iwai 0cac74
Takashi Iwai 0cac74
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
Takashi Iwai 0cac74
index bc74afdbf31e..e026b2d0a5a4 100644
Takashi Iwai 0cac74
--- a/arch/riscv/Makefile
Takashi Iwai 0cac74
+++ b/arch/riscv/Makefile
Takashi Iwai 0cac74
@@ -108,6 +108,10 @@ PHONY += vdso_install
Takashi Iwai 0cac74
 vdso_install:
Takashi Iwai 0cac74
 	$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
+prepare: vdso_prepare
Takashi Iwai 0cac74
+vdso_prepare: prepare0
Takashi Iwai 0cac74
+	$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
Takashi Iwai 0cac74
+
Takashi Iwai 0cac74
 ifneq ($(CONFIG_XIP_KERNEL),y)
Takashi Iwai 0cac74
 ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
Takashi Iwai 0cac74
 KBUILD_IMAGE := $(boot)/loader.bin
Takashi Iwai 0cac74
diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
Takashi Iwai 0cac74
index 1453a2f563bc..d8d003c2b5a3 100644
Takashi Iwai 0cac74
--- a/arch/riscv/include/asm/vdso.h
Takashi Iwai 0cac74
+++ b/arch/riscv/include/asm/vdso.h
Takashi Iwai 0cac74
@@ -9,25 +9,15 @@
Takashi Iwai 0cac74
 #define _ASM_RISCV_VDSO_H
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
 #include <linux/types.h>
Takashi Iwai 0cac74
+#include <generated/vdso-offsets.h>
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
 #ifndef CONFIG_GENERIC_TIME_VSYSCALL
Takashi Iwai 0cac74
 struct vdso_data {
Takashi Iwai 0cac74
 };
Takashi Iwai 0cac74
 #endif
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
-/*
Takashi Iwai 0cac74
- * The VDSO symbols are mapped into Linux so we can just use regular symbol
Takashi Iwai 0cac74
- * addressing to get their offsets in userspace.  The symbols are mapped at an
Takashi Iwai 0cac74
- * offset of 0, but since the linker must support setting weak undefined
Takashi Iwai 0cac74
- * symbols to the absolute address 0 it also happens to support other low
Takashi Iwai 0cac74
- * addresses even when the code model suggests those low addresses would not
Takashi Iwai 0cac74
- * otherwise be availiable.
Takashi Iwai 0cac74
- */
Takashi Iwai 0cac74
 #define VDSO_SYMBOL(base, name)							\
Takashi Iwai 0cac74
-({										\
Takashi Iwai 0cac74
-	extern const char __vdso_##name[];					\
Takashi Iwai 0cac74
-	(void __user *)((unsigned long)(base) + __vdso_##name);			\
Takashi Iwai 0cac74
-})
Takashi Iwai 0cac74
+	(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
 asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
Takashi Iwai 0cac74
index 24d936c147cd..f8cb9144a284 100644
Takashi Iwai 0cac74
--- a/arch/riscv/kernel/vdso/Makefile
Takashi Iwai 0cac74
+++ b/arch/riscv/kernel/vdso/Makefile
Takashi Iwai 0cac74
@@ -23,10 +23,10 @@ ifneq ($(c-gettimeofday-y),)
Takashi Iwai 0cac74
 endif
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
 # Build rules
Takashi Iwai 0cac74
-targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S
Takashi Iwai 0cac74
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
Takashi Iwai 0cac74
 obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
-obj-y += vdso.o vdso-syms.o
Takashi Iwai 0cac74
+obj-y += vdso.o
Takashi Iwai 0cac74
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
 # Disable -pg to prevent insert call site
Takashi Iwai 0cac74
@@ -43,20 +43,22 @@ $(obj)/vdso.o: $(obj)/vdso.so
Takashi Iwai 0cac74
 # link rule for the .so file, .lds has to be first
Takashi Iwai 0cac74
 $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
Takashi Iwai 0cac74
 	$(call if_changed,vdsold)
Takashi Iwai 0cac74
-LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
Takashi Iwai 0cac74
+LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \
Takashi Iwai 0cac74
 	--build-id=sha1 --hash-style=both --eh-frame-hdr
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
-# We also create a special relocatable object that should mirror the symbol
Takashi Iwai 0cac74
-# table and layout of the linked DSO. With ld --just-symbols we can then
Takashi Iwai 0cac74
-# refer to these symbols in the kernel code rather than hand-coded addresses.
Takashi Iwai 0cac74
-$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
Takashi Iwai 0cac74
-	$(call if_changed,so2s)
Takashi Iwai 0cac74
-
Takashi Iwai 0cac74
 # strip rule for the .so file
Takashi Iwai 0cac74
 $(obj)/%.so: OBJCOPYFLAGS := -S
Takashi Iwai 0cac74
 $(obj)/%.so: $(obj)/%.so.dbg FORCE
Takashi Iwai 0cac74
 	$(call if_changed,objcopy)
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
+# Generate VDSO offsets using helper script
Takashi Iwai 0cac74
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
Takashi Iwai 0cac74
+quiet_cmd_vdsosym = VDSOSYM $@
Takashi Iwai 0cac74
+	cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
Takashi Iwai 0cac74
+
Takashi Iwai 0cac74
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
Takashi Iwai 0cac74
+	$(call if_changed,vdsosym)
Takashi Iwai 0cac74
+
Takashi Iwai 0cac74
 # actual build commands
Takashi Iwai 0cac74
 # The DSO images are built using a special linker script
Takashi Iwai 0cac74
 # Make sure only to export the intended __vdso_xxx symbol offsets.
Takashi Iwai 0cac74
@@ -65,11 +67,6 @@ quiet_cmd_vdsold = VDSOLD  $@
Takashi Iwai 0cac74
                    $(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
Takashi Iwai 0cac74
                    rm $@.tmp
Takashi Iwai 0cac74
 
Takashi Iwai 0cac74
-# Extracts symbol offsets from the VDSO, converting them into an assembly file
Takashi Iwai 0cac74
-# that contains the same symbols at the same offsets.
Takashi Iwai 0cac74
-quiet_cmd_so2s = SO2S    $@
Takashi Iwai 0cac74
-      cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
Takashi Iwai 0cac74
-
Takashi Iwai 0cac74
 # install commands for the unstripped file
Takashi Iwai 0cac74
 quiet_cmd_vdso_install = INSTALL $@
Takashi Iwai 0cac74
       cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
Takashi Iwai 0cac74
diff --git a/arch/riscv/kernel/vdso/gen_vdso_offsets.sh b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
Takashi Iwai 0cac74
new file mode 100755
Takashi Iwai 0cac74
index 000000000000..c2e5613f3495
Takashi Iwai 0cac74
--- /dev/null
Takashi Iwai 0cac74
+++ b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
Takashi Iwai 0cac74
@@ -0,0 +1,5 @@
Takashi Iwai 0cac74
+#!/bin/sh
Takashi Iwai 0cac74
+# SPDX-License-Identifier: GPL-2.0
Takashi Iwai 0cac74
+
Takashi Iwai 0cac74
+LC_ALL=C
Takashi Iwai 0cac74
+sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p'
Takashi Iwai 0cac74
diff --git a/arch/riscv/kernel/vdso/so2s.sh b/arch/riscv/kernel/vdso/so2s.sh
Takashi Iwai 0cac74
deleted file mode 100755
Takashi Iwai 0cac74
index e64cb6d9440e..000000000000
Takashi Iwai 0cac74
--- a/arch/riscv/kernel/vdso/so2s.sh
Takashi Iwai 0cac74
+++ /dev/null
Takashi Iwai 0cac74
@@ -1,6 +0,0 @@
Takashi Iwai 0cac74
-#!/bin/sh
Takashi Iwai 0cac74
-# SPDX-License-Identifier: GPL-2.0+
Takashi Iwai 0cac74
-# Copyright 2020 Palmer Dabbelt <palmerdabbelt@google.com>
Takashi Iwai 0cac74
-
Takashi Iwai 0cac74
-sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \
Takashi Iwai 0cac74
-| grep '^\.'
Takashi Iwai 0cac74
-- 
Takashi Iwai 0cac74
2.26.2
Takashi Iwai 0cac74