From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753654AbdCBACy (ORCPT ); Wed, 1 Mar 2017 19:02:54 -0500 Received: from mail-sn1nam02on0086.outbound.protection.outlook.com ([104.47.36.86]:21742 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753233AbdCBACw (ORCPT ); Wed, 1 Mar 2017 19:02:52 -0500 Authentication-Results: lists.infradead.org; dkim=none (message not signed) header.d=none;lists.infradead.org; dmarc=none action=none header.from=caviumnetworks.com; From: Yury Norov To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Arnd Bergmann , Catalin Marinas Cc: Yury Norov , Andrew Pinski , Andrew Pinski , Adam Borowski , Chris Metcalf , Steve Ellcey , Maxim Kuvyrkov , Ramana Radhakrishnan , Florian Weimer , Bamvor Zhangjian , Andreas Schwab , Chris Metcalf , Heiko Carstens , schwidefsky@de.ibm.com, broonie@kernel.org, Joseph Myers , christoph.muellner@theobroma-systems.com, szabolcs.nagy@arm.com, klimov.linux@gmail.com, Nathan_Lynch@mentor.com, agraf@suse.de, Prasun.Kapoor@caviumnetworks.com, geert@linux-m68k.org, philipp.tomsich@theobroma-systems.com, manuel.montezelo@gmail.com, linyongting@huawei.com, davem@davemloft.net, zhouchengming1@huawei.com, Bamvor Jian Zhang Subject: [PATCH 19/20] arm64:ilp32: add vdso-ilp32 and use for signal return Date: Thu, 2 Mar 2017 00:49:27 +0530 Message-Id: <1488395968-14313-20-git-send-email-ynorov@caviumnetworks.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488395968-14313-1-git-send-email-ynorov@caviumnetworks.com> References: <1488395968-14313-1-git-send-email-ynorov@caviumnetworks.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [27.97.135.110] X-ClientProxiedBy: VI1PR0901CA0076.eurprd09.prod.outlook.com (10.167.203.172) To DM3PR07MB2249.namprd07.prod.outlook.com (10.164.33.147) X-MS-Office365-Filtering-Correlation-Id: 6500cbe5-1b5e-43c6-d8dd-08d460d86f09 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:DM3PR07MB2249; X-Microsoft-Exchange-Diagnostics: 1;DM3PR07MB2249;3:yIX0/Cob4t81ooqIAtc3PRr0j2eWIqD3Z60R7AWvrp5ZKvvbdfym5n/WwOgUIvyLRaw0pXpi0IoRvRCWlPhIrMVT6bEUBbSeb5lyGK0Ov2C8tzEYfFPYK+6G/+45PzepQRTw5WTzVV/zO2dvP6GQLceGjzdkwHKJb96KUarE1sOgpasU7PiNfiZ8CVpGcPPwws6tT4gzLr6nL9eT80Ur6K0FdpGwGvRcNK94NRWj+lQMHakQHPJsl6+kaMBkBkUNW7vNNgjInNouA3lYlRbdsw==;25:9PujCgmRpZbFCERsxnIejEKhPBA9jTFwmPx9LsYrdnbx7o1zKMtIpEfDWnJDEuVWgMYMTCDWvVuLScqU8jS1nKDiscwLrFLciCi+06TJDm6KFWHZgqdcobGNvfLhkqr5E0v1xM0iRfjUi92CjyYFGhki2FGwr49sZb2bMoY/ZkGJ46ZPLQpDsKuj8IQBNMhJiAu9mtPyCMemdJUwrI48EapPIhqhUUo7/qmlOnQNmzXqlTYOdv5U6bQDcepqSXvzupGmVGg3Yhm8cZ3H/eN708tanurFxirXgRSQQ5Ioam4LttRzFFSLe3rJPnLcy74LPcwITliw6itttNhfXt+ZJeNCybF9dDTmD9CroYKHfK36XZ4+gyZ7u+xAw6XFzeVORAN/aZ1mkJeEh2I+Qqb0fBLsu9ySKRF54QaeMKG94tDSZl2E9eWHWW0T+TTaMU+A X-Microsoft-Exchange-Diagnostics: 1;DM3PR07MB2249;31:IWsLeIXZsBOtuNjWw7r67qjZHg8x3Rt/NxWqGPNswneZNiKI/2+4CFyHGSzFNWEHkYGgxROwyk/C7EZCbZPpRbZ28r7zQ9tynlmF9Jle9GEhS1Ps0SHMlS3UDVHlivCKM+8mGj6Q69sb61TFndrgC1Vc56yLu6+g+0lXl1QKV1hOWk61D4e8KfDyF0wBWRsfX9IVgw90YrYYoiDDHBiKpeOyab4QmMHVxe9AAuDu8hqWnPYayxwdWHnUtBYhVvByM8kX43VrmnEoBAtW8tIc/w==;20:0DT5d39/uwPyfduom/s1fONQHJwr1mCkm9/8Xcpt9sckkgW1tD049sF4qLqFsnHSWzSAPe0s5hUtA91DHzxEQS/QLxwF1d/qRJBwzSPQ2mRZp4fL/ZdV+EBDA8HS8HLrpALLY2ZvUoqvWpNvjzAgxm3xI262WnttJOjiVSwYQVrHlwFrAQDak6fmq7SKr2tZy74J9agBJ2vhiPF4OOZmRJLk/XeUHBnN0AJMWm7Azs78gIu+yIyDg39oKi4EvY7VMlp61ESRDtiafxnqz+XUfHT+6nAnlo7JbYtaiWwWFWWZJ+WRCcQcQ9U8H9Pkzo4WSjeSxpFAz9Z/BenSGd3aP+J7EOaOmFy4rdxsz4y/1KQwde5yk43wdJfxqHxz4rWW9dF12CqNFezKm3xMTTQaQPQPgORhf7mtBX6O3NXqOxdqRPK01RghHi+9nMoXnzhMEvgnmg/4fdeMRbkzWlLd+ubxP1/EYMUELk1fz52JVYYm6xKY9+L5zNQumtTkWMqCNyxdutMy+waOnpbkPhCZjieK8zbsuUyk2A9l1SWnzy8ppHBqep+xKl1vJwUE4TmEE4DH2gm1G4LDTA0/drwSO17n2zKLZUO8x4RgwJ6QG/M= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(180628864354917)(22074186197030); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6041248)(20161123555025)(20161123564025)(20161123558025)(20161123562025)(20161123560025)(6072148);SRVR:DM3PR07MB2249;BCL:0;PCL:0;RULEID:;SRVR:DM3PR07MB2249; X-Microsoft-Exchange-Diagnostics: 1;DM3PR07MB2249;4:6ffRhF0KRf2EAGyk8i1VbJB5XgFmoPaUKaM5zcYg4AYrus83w75dx+NcQtQGgO5fVZ5bzWOOPgSt7hI8uDRq39f55ouDtiNq9iaxuDoJazuLi31TqxWh8kQ5AyrojW8yT5blhgsvkdJ5PDORznsRobko3dOUdEyvQY4rhyHmCRl1ClS3RWjlNvUYImEM4xsKhcttXTVVcip6In0hhPtkqsV0zKvA8f7co/LaDkRhbbWbia6fdLPF4GXgA0Tl/vhtuOPoT0GEDcNr+M8Q0UHLFTFRB9MYT1vL8YnlnbnXClLXW5gmlf2Fa+uAH5lrTQPkekX4gXUOukVeLj9OQATUr7rmKHN8yiSgRi7rhS5vvh5hIih/BiZ4WNdOld5j3wTbC9akUjDbTdWAWMIh3RayVKoBIWz3gcQ8lyp2nm5oxDks1FmFAxiQQaYVtL7ICzSSn3WNTXHhrBIotKrpVqqR4D2HgbKYy+WnR6adnXp2F+U5ilIAvm0Rdh/tSxgsYxr6SizvuH7db+4PuXW7iIokaPz8Wk7VNdeGp/g8hA4smd/DuVcctqDyMAOj0/9c4fLlcc6ZHmniJ3tCwRE0zZzboqTGbZ1ibBi4s/hd1YmLU/yO6HuPCf3dOh68y6/ALFz6cKcvUYv4mP6z+4mHxegGXrxgalI+E7lasHJsjjvQ/dwl8NNIbo8c9jz3XQqdoN+kD2M1QSNrcHevScUYhX1/ng== X-Forefront-PRVS: 0233768B38 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6069001)(6009001)(7916002)(39450400003)(76506005)(92566002)(50226002)(6496005)(7416002)(54906002)(5660300001)(8676002)(5009440100003)(7736002)(4326008)(81166006)(305945005)(6486002)(66066001)(189998001)(76176999)(48376002)(5003940100001)(42186005)(2906002)(2950100002)(6116002)(50466002)(50986999)(36756003)(47776003)(3846002)(33646002)(6306002)(53936002)(25786008)(38730400002);DIR:OUT;SFP:1101;SCL:1;SRVR:DM3PR07MB2249;H:localhost;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DM3PR07MB2249;23:YnGd4Raw4+VVX6V0u72YyB4ueLJmwAZFEL3j6y3Ji?= =?us-ascii?Q?NSMyFEmBuv1Uy5SBnVPbYCIydDH/m9qx+xUZs06b5OzrjHH+e3HdSm7nlYl6?= =?us-ascii?Q?j4enli56JfdC0UxNfGy6N88kLLzSmRNZI70XQqOd8jfo7c/SX+KnLyRsW6KH?= =?us-ascii?Q?tLv2hWlGcPAY07EKkBXWBzJWAujVqwpyewzWKCq1i0KAyI6rW+8hpqiDMnSE?= =?us-ascii?Q?a4CVJEarh59KD4oh65NgIq3phgby5NrUlEkAA075CFr7FqJiXVVsZrEXsUPK?= =?us-ascii?Q?ArwocrPa3qQJ//aw3dJnPojrcgp1H0VGaiiwgcaxUAK458/jZXnhQzHDtilZ?= =?us-ascii?Q?GPUoAP7lP7NpzED57y2Nuzv6MwZFJDz7PeMUkbawzW+FUNjEZOxHTwJR4cYn?= =?us-ascii?Q?V0d54KgyRtv/4ah91aRCjEJWDj4njpSWZxVs3hX7DvEs+Kc1WMdXQd6D2l/H?= =?us-ascii?Q?iBTFUsvBfrrkBrlLkNpMztf7tKvxTh004GklqSfYAQLpqEeLEQbaybrjL3y1?= =?us-ascii?Q?z/kna3G08yHIFreumPFCH3dKmEGamqZLWLf2CNCShnakudksrICTMvURoRoo?= =?us-ascii?Q?SR/fSAJq1H+3bFMsiSg09gfT3NQo4J3C6bwa9roewKaDT31NBExdwiwRSqtv?= =?us-ascii?Q?Oaw89v0amtjzP2d1NOCPFnPohcjQbek6yXdxzsQ3zBj7TloMrKUlfYdpVUma?= =?us-ascii?Q?1XFdLlS7EA9VTVXHBrpdRmFWRzzzD6N25GBIUNbY4H3B45IgJ4gXkHj2GDdg?= =?us-ascii?Q?LlcPWqJgb+Fw1Nx7pYIqHV29UaLxPpSOxp0Yqo7bXxrBY3KclcWH8IJhVAMS?= =?us-ascii?Q?8DjDj/Hl7IN8wxECmniyVQ7dDs/G0gH1F6xqhDvZp5pOaxSb2VwGpJKtlAsR?= =?us-ascii?Q?23lQgu64vx7jqR/YeONVlmORc/OBq4/cB+VUdmQQLkEp8Yu9UeWT3SwBU7x9?= =?us-ascii?Q?N8SMREsIXBrb7MjJ+AzImnQQPp7fgIoSTAUcPgIGA=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;DM3PR07MB2249;6:ZRXksTiIQl+vFx/ZFdZjTvnD3QUxvNpRmfPYpEFgcHQdWdd3Z/mQ/RHi/4JOKBST5Br+VBtl99Er4+XgdXM9IibtG7dTNrv1NFWxLiPTlW403WecIIwba8WhBY/FvmlEHyrZnadPQ8k7G4iX1pqYVc2PHzhcMs+Y+XJFPqUFImOW+JuefnEA9qnfWxeGI7nI7VOGl9BQJX1fhxdop6B2++WSrWYzsjtMvxaz5IOMRHx2+7+qjgpqrcLwgNQwvvfVMAehbd+xmyhYC4dVI8OZUTIvBiQsLFgFOm+ceDMnBn+2JiLaf6NI+UAo0YNjiZHsw8nxcYkYcERpC8SLxH/9m3CSyaOvp3AcEaNkUdjVwwmE61GcYZQhXn5H7N/+FuFw0fQCGpFlxtnMpxnLywHykg==;5:2J6CCBs3rZBM4su0W8b7olqnK171+L9Kd5tz8rjMP281uKhuaP2//nOM14TEAKV4hEDA+ysF/tOQ5CxXm/UIVB77M3LzxWBZXqZ/ao/0NkkCXB+OAG5WgRD9TTnxUCZhqJImJdMf/ffYepjE8kiU5NTHTc++tUrlIdUtK1LjECQ=;24:J12M0sofg50r/o25oxX/DrKnNYnbuKbCC4QRKui/0IdVZOMDddFJc4kPB+wVeXpI6Umvg9RvLVt4vK2aVTAJGwiCKty6Wkyf3TRGylQFJr0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DM3PR07MB2249;7:SAQ6j940JBt0QwqvGj2zMBPamzD8ePH1y9o3bEMF5+O6ofJxmtngqouiARcWWOWtrYszsGwWtjN3uRwRC4VzHahYRWCxA5UHUDnYxED8vMll+kXJKXJyq7yPf7+V0Fz2OSwi1+Ao8bHMpYveZfAOOfJ3a97mqpouda0TR2h0glchEilB2ivRcjsTFhwUW+LoaXAWs8L/gKOX4FucPTESJMyidjO/6CPZ2MrlJdENXJxcx/l8JsOEbjlU3rZiRw5X+DlPTY96vOxGdZYTOgp/yEUirgwhL9R4uKNETtXtUSunYqVfTsHqcBqmx9wSQwgxofT1Eu9ZD498YdwD3eZnrA== X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Mar 2017 19:23:24.8293 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM3PR07MB2249 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Philipp Tomsich ILP32 VDSO exports next symbols: __kernel_rt_sigreturn; __kernel_gettimeofday; __kernel_clock_gettime; __kernel_clock_getres. What shared object to use, kernel selects depending on result of is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes correct pages and spec. Adjusted to move the data page before code pages in sync with commit 601255ae3c98 ("arm64: vdso: move data page before code pages") Signed-off-by: Philipp Tomsich Signed-off-by: Christoph Muellner Signed-off-by: Yury Norov Signed-off-by: Bamvor Jian Zhang --- arch/arm64/include/asm/vdso.h | 6 ++ arch/arm64/kernel/Makefile | 11 ++++ arch/arm64/kernel/asm-offsets.c | 7 ++ arch/arm64/kernel/signal.c | 2 + arch/arm64/kernel/vdso-ilp32/.gitignore | 2 + arch/arm64/kernel/vdso-ilp32/Makefile | 74 +++++++++++++++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++ arch/arm64/kernel/vdso.c | 65 +++++++++++++++--- arch/arm64/kernel/vdso/gettimeofday.S | 20 +++++- arch/arm64/kernel/vdso/vdso.S | 6 +- 11 files changed, 305 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h index 839ce00..649a9a4 100644 --- a/arch/arm64/include/asm/vdso.h +++ b/arch/arm64/include/asm/vdso.h @@ -29,6 +29,12 @@ #include +#ifdef CONFIG_ARM64_ILP32 +#include +#else +#define vdso_offset_sigtramp_ilp32 +#endif + #define VDSO_SYMBOL(base, name) \ ({ \ (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index d6089e5..8720416 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -55,6 +55,7 @@ arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ cpu-reset.o obj-y += $(arm64-obj-y) vdso/ probes/ +obj-$(CONFIG_ARM64_ILP32) += vdso-ilp32/ obj-m += $(arm64-obj-m) head-y := head.o extra-y += $(head-y) vmlinux.lds @@ -62,3 +63,13 @@ extra-y += $(head-y) vmlinux.lds ifeq ($(CONFIG_DEBUG_EFI),y) AFLAGS_head.o += -DVMLINUX_PATH="\"$(realpath $(objtree)/vmlinux)\"" endif + +# vDSO - this must be built first to generate the symbol offsets +$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h +$(obj)/vdso/vdso-offsets.h: $(obj)/vdso + +ifeq ($(CONFIG_ARM64_ILP32),y) +# vDSO - this must be built first to generate the symbol offsets +$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h +$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32 +endif diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index aec5b6c..c8a0971 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -121,6 +121,13 @@ int main(void) DEFINE(TSPEC_TV_SEC, offsetof(struct timespec, tv_sec)); DEFINE(TSPEC_TV_NSEC, offsetof(struct timespec, tv_nsec)); BLANK(); +#ifdef CONFIG_COMPAT + DEFINE(COMPAT_TVAL_TV_SEC, offsetof(struct compat_timeval, tv_sec)); + DEFINE(COMPAT_TVAL_TV_USEC, offsetof(struct compat_timeval, tv_usec)); + DEFINE(COMPAT_TSPEC_TV_SEC, offsetof(struct compat_timespec, tv_sec)); + DEFINE(COMPAT_TSPEC_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); + BLANK(); +#endif DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); BLANK(); diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index b78f4c2..a7f201d 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -267,6 +267,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) sigtramp = ka->sa.sa_restorer; + else if (is_ilp32_compat_task()) + sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32); else sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore new file mode 100644 index 0000000..61806c3 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/.gitignore @@ -0,0 +1,2 @@ +vdso-ilp32.lds +vdso-ilp32-offsets.h diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile new file mode 100644 index 0000000..0671e88 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/Makefile @@ -0,0 +1,74 @@ +# +# Building a vDSO image for AArch64. +# +# Author: Will Deacon +# Heavily based on the vDSO Makefiles for other archs. +# + +obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o + +# Build rules +targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg +obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso)) + +ccflags-y := -shared -fno-common -fno-builtin +ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) + +obj-y += vdso-ilp32.o +extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h +CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32 + +# Force dependency (incbin is bad) +$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so + +# Link rule for the .so file, .lds has to be first +$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso) + $(call if_changed,vdso-ilp32ld) + +# 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)/../vdso/gen_vdso_offsets.sh +quiet_cmd_vdsosym = VDSOSYM $@ +define cmd_vdsosym + $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \ + cp $@ include/generated/ +endef + +$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE + $(call if_changed,vdsosym) + +# Assembly rules for the .S files +#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S) +# $(call if_changed_dep,vdso-ilp32as) + +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S + $(call if_changed_dep,vdso-ilp32as) + +$(obj)/note-ilp32.o: $(src)/../vdso/note.S + $(call if_changed_dep,vdso-ilp32as) + +# This one should be fine because ILP32 uses the same generic +# __NR_rt_sigreturn syscall number. +$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S + $(call if_changed_dep,vdso-ilp32as) + +# Actual build commands +quiet_cmd_vdso-ilp32ld = VDSOILP32L $@ + cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32 -Wl,-n -Wl,-T $^ -o $@ +quiet_cmd_vdso-ilp32as = VDSOILP32A $@ + cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $< + +# Install commands for the unstripped file +quiet_cmd_vdso_install = INSTALL $@ + cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ + +vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg + @mkdir -p $(MODLIB)/vdso + $(call cmd,vdso_install) + +vdso_install: vdso-ilp32.so diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S new file mode 100644 index 0000000..46ac072 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S @@ -0,0 +1,33 @@ +/* + * 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 . + * + * Author: Will Deacon + */ + +#include +#include +#include +#include + + __PAGE_ALIGNED_DATA + + .globl vdso_ilp32_start, vdso_ilp32_end + .balign PAGE_SIZE +vdso_ilp32_start: + .incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so" + .balign PAGE_SIZE +vdso_ilp32_end: + + .previous diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S new file mode 100644 index 0000000..ba98794 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S @@ -0,0 +1,95 @@ +/* + * 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 . + * + * Author: Will Deacon + * Heavily based on the vDSO linker scripts for other archs. + */ + +#include +#include +#include + +SECTIONS +{ + PROVIDE(_vdso_data = . - PAGE_SIZE); + . = VDSO_LBASE + 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 + + . = ALIGN(16); + + .text : { *(.text*) } :text =0xd503201f + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + + .dynamic : { *(.dynamic) } :text :dynamic + + .rodata : { *(.rodata*) } :text + + _end = .; + PROVIDE(end = .); + + /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; +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_4.10 { + global: + __kernel_rt_sigreturn; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + local: *; + }; +} + +/* + * Make the sigreturn code visible to the kernel. + */ +VDSO_sigtramp_ilp32 = __kernel_rt_sigreturn; diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 9d44902..71bee92 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -37,8 +37,13 @@ #include #include -extern char vdso_start, vdso_end; -static unsigned long vdso_pages __ro_after_init; +extern char vdso_lp64_start, vdso_lp64_end; +static unsigned long vdso_lp64_pages __ro_after_init; + +#ifdef CONFIG_ARM64_ILP32 +extern char vdso_ilp32_start, vdso_ilp32_end; +static unsigned long vdso_ilp32_pages __ro_after_init; +#endif /* * The vDSO data page. @@ -110,7 +115,17 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) } #endif /* CONFIG_AARCH32_EL0 */ -static struct vm_special_mapping vdso_spec[2] __ro_after_init = { +static struct vm_special_mapping vdso_lp64_spec[2] __ro_after_init = { + { + .name = "[vvar]", + }, + { + .name = "[vdso]", + }, +}; + +#ifdef CONFIG_ARM64_ILP32 +static struct vm_special_mapping vdso_ilp32_spec[2] __ro_after_init = { { .name = "[vvar]", }, @@ -118,21 +133,27 @@ static struct vm_special_mapping vdso_spec[2] __ro_after_init = { .name = "[vdso]", }, }; +#endif -static int __init vdso_init(void) +static int __init vdso_init(char *vdso_start, char *vdso_end, + unsigned long *vdso_pagesp, + struct vm_special_mapping *vdso_spec) { int i; + unsigned long vdso_pages; struct page **vdso_pagelist; unsigned long pfn; - if (memcmp(&vdso_start, "\177ELF", 4)) { + if (memcmp(vdso_start, "\177ELF", 4)) { pr_err("vDSO is not a valid ELF object!\n"); return -EINVAL; } - vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; + vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; + *vdso_pagesp = vdso_pages; pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n", - vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data); + vdso_pages + 1, vdso_pages, + vdso_start, 1L, vdso_data); /* Allocate the vDSO pagelist, plus a page for the data. */ vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *), @@ -145,7 +166,7 @@ static int __init vdso_init(void) /* Grab the vDSO code pages. */ - pfn = sym_to_pfn(&vdso_start); + pfn = sym_to_pfn(vdso_start); for (i = 0; i < vdso_pages; i++) vdso_pagelist[i + 1] = pfn_to_page(pfn + i); @@ -155,7 +176,22 @@ static int __init vdso_init(void) return 0; } -arch_initcall(vdso_init); + +static int __init vdso_lp64_init(void) +{ + return vdso_init(&vdso_lp64_start, &vdso_lp64_end, + &vdso_lp64_pages, vdso_lp64_spec); +} +arch_initcall(vdso_lp64_init); + +#ifdef CONFIG_ARM64_ILP32 +static int __init vdso_ilp32_init(void) +{ + return vdso_init(&vdso_ilp32_start, &vdso_ilp32_end, + &vdso_ilp32_pages, vdso_ilp32_spec); +} +arch_initcall(vdso_ilp32_init); +#endif int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) @@ -163,8 +199,17 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, struct mm_struct *mm = current->mm; unsigned long vdso_base, vdso_text_len, vdso_mapping_len; void *ret; + unsigned long pages = vdso_lp64_pages; + struct vm_special_mapping *vdso_spec = vdso_lp64_spec; + +#ifdef CONFIG_ARM64_ILP32 + if (is_ilp32_compat_task()) { + pages = vdso_ilp32_pages; + vdso_spec = vdso_ilp32_spec; + } +#endif - vdso_text_len = vdso_pages << PAGE_SHIFT; + vdso_text_len = pages << PAGE_SHIFT; /* Be sure to map the data page */ vdso_mapping_len = vdso_text_len + PAGE_SIZE; diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index e00b467..062a33d 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S @@ -25,6 +25,16 @@ #define NSEC_PER_SEC_LO16 0xca00 #define NSEC_PER_SEC_HI16 0x3b9a +#ifdef __LP64__ +#define PTR_REG(n) x##n +#define OFFSET(n) n +#define DELOUSE(n) +#else +#define PTR_REG(n) w##n +#define OFFSET(n) COMPAT_##n +#define DELOUSE(n) mov w##n, w##n +#endif + vdso_data .req x6 seqcnt .req w7 w_tmp .req w8 @@ -119,7 +129,7 @@ x_tmp .req x8 .if \shift == 1 lsr x11, x11, x12 .endif - stp x10, x11, [x1, #TSPEC_TV_SEC] + stp PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)] mov x0, xzr ret .endm @@ -136,6 +146,8 @@ x_tmp .req x8 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */ ENTRY(__kernel_gettimeofday) .cfi_startproc + DELOUSE(0) + DELOUSE(1) adr vdso_data, _vdso_data /* If tv is NULL, skip to the timezone code. */ cbz x0, 2f @@ -160,7 +172,7 @@ ENTRY(__kernel_gettimeofday) mov x13, #1000 lsl x13, x13, x12 udiv x11, x11, x13 - stp x10, x11, [x0, #TVAL_TV_SEC] + stp PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)] 2: /* If tz is NULL, return 0. */ cbz x1, 3f @@ -182,6 +194,7 @@ ENDPROC(__kernel_gettimeofday) /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */ ENTRY(__kernel_clock_gettime) .cfi_startproc + DELOUSE(1) cmp w0, #JUMPSLOT_MAX b.hi syscall adr vdso_data, _vdso_data @@ -297,6 +310,7 @@ ENDPROC(__kernel_clock_gettime) /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */ ENTRY(__kernel_clock_getres) .cfi_startproc + DELOUSE(1) cmp w0, #CLOCK_REALTIME ccmp w0, #CLOCK_MONOTONIC, #0x4, ne ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne @@ -311,7 +325,7 @@ ENTRY(__kernel_clock_getres) ldr x2, 6f 2: cbz w1, 3f - stp xzr, x2, [x1] + stp PTR_REG(zr), PTR_REG(2), [x1] 3: /* res == NULL. */ mov w0, wzr diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S index 82379a7..a40ae24 100644 --- a/arch/arm64/kernel/vdso/vdso.S +++ b/arch/arm64/kernel/vdso/vdso.S @@ -21,12 +21,12 @@ #include #include - .globl vdso_start, vdso_end + .globl vdso_lp64_start, vdso_lp64_end .section .rodata .balign PAGE_SIZE -vdso_start: +vdso_lp64_start: .incbin "arch/arm64/kernel/vdso/vdso.so" .balign PAGE_SIZE -vdso_end: +vdso_lp64_end: .previous -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: ynorov@caviumnetworks.com (Yury Norov) Date: Thu, 2 Mar 2017 00:49:27 +0530 Subject: [PATCH 19/20] arm64:ilp32: add vdso-ilp32 and use for signal return In-Reply-To: <1488395968-14313-1-git-send-email-ynorov@caviumnetworks.com> References: <1488395968-14313-1-git-send-email-ynorov@caviumnetworks.com> Message-ID: <1488395968-14313-20-git-send-email-ynorov@caviumnetworks.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: Philipp Tomsich ILP32 VDSO exports next symbols: __kernel_rt_sigreturn; __kernel_gettimeofday; __kernel_clock_gettime; __kernel_clock_getres. What shared object to use, kernel selects depending on result of is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes correct pages and spec. Adjusted to move the data page before code pages in sync with commit 601255ae3c98 ("arm64: vdso: move data page before code pages") Signed-off-by: Philipp Tomsich Signed-off-by: Christoph Muellner Signed-off-by: Yury Norov Signed-off-by: Bamvor Jian Zhang --- arch/arm64/include/asm/vdso.h | 6 ++ arch/arm64/kernel/Makefile | 11 ++++ arch/arm64/kernel/asm-offsets.c | 7 ++ arch/arm64/kernel/signal.c | 2 + arch/arm64/kernel/vdso-ilp32/.gitignore | 2 + arch/arm64/kernel/vdso-ilp32/Makefile | 74 +++++++++++++++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++ arch/arm64/kernel/vdso.c | 65 +++++++++++++++--- arch/arm64/kernel/vdso/gettimeofday.S | 20 +++++- arch/arm64/kernel/vdso/vdso.S | 6 +- 11 files changed, 305 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h index 839ce00..649a9a4 100644 --- a/arch/arm64/include/asm/vdso.h +++ b/arch/arm64/include/asm/vdso.h @@ -29,6 +29,12 @@ #include +#ifdef CONFIG_ARM64_ILP32 +#include +#else +#define vdso_offset_sigtramp_ilp32 +#endif + #define VDSO_SYMBOL(base, name) \ ({ \ (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index d6089e5..8720416 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -55,6 +55,7 @@ arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ cpu-reset.o obj-y += $(arm64-obj-y) vdso/ probes/ +obj-$(CONFIG_ARM64_ILP32) += vdso-ilp32/ obj-m += $(arm64-obj-m) head-y := head.o extra-y += $(head-y) vmlinux.lds @@ -62,3 +63,13 @@ extra-y += $(head-y) vmlinux.lds ifeq ($(CONFIG_DEBUG_EFI),y) AFLAGS_head.o += -DVMLINUX_PATH="\"$(realpath $(objtree)/vmlinux)\"" endif + +# vDSO - this must be built first to generate the symbol offsets +$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h +$(obj)/vdso/vdso-offsets.h: $(obj)/vdso + +ifeq ($(CONFIG_ARM64_ILP32),y) +# vDSO - this must be built first to generate the symbol offsets +$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h +$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32 +endif diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index aec5b6c..c8a0971 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -121,6 +121,13 @@ int main(void) DEFINE(TSPEC_TV_SEC, offsetof(struct timespec, tv_sec)); DEFINE(TSPEC_TV_NSEC, offsetof(struct timespec, tv_nsec)); BLANK(); +#ifdef CONFIG_COMPAT + DEFINE(COMPAT_TVAL_TV_SEC, offsetof(struct compat_timeval, tv_sec)); + DEFINE(COMPAT_TVAL_TV_USEC, offsetof(struct compat_timeval, tv_usec)); + DEFINE(COMPAT_TSPEC_TV_SEC, offsetof(struct compat_timespec, tv_sec)); + DEFINE(COMPAT_TSPEC_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); + BLANK(); +#endif DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); BLANK(); diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index b78f4c2..a7f201d 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -267,6 +267,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) sigtramp = ka->sa.sa_restorer; + else if (is_ilp32_compat_task()) + sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32); else sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore new file mode 100644 index 0000000..61806c3 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/.gitignore @@ -0,0 +1,2 @@ +vdso-ilp32.lds +vdso-ilp32-offsets.h diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile new file mode 100644 index 0000000..0671e88 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/Makefile @@ -0,0 +1,74 @@ +# +# Building a vDSO image for AArch64. +# +# Author: Will Deacon +# Heavily based on the vDSO Makefiles for other archs. +# + +obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o + +# Build rules +targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg +obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso)) + +ccflags-y := -shared -fno-common -fno-builtin +ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) + +obj-y += vdso-ilp32.o +extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h +CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32 + +# Force dependency (incbin is bad) +$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so + +# Link rule for the .so file, .lds has to be first +$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso) + $(call if_changed,vdso-ilp32ld) + +# 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)/../vdso/gen_vdso_offsets.sh +quiet_cmd_vdsosym = VDSOSYM $@ +define cmd_vdsosym + $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \ + cp $@ include/generated/ +endef + +$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE + $(call if_changed,vdsosym) + +# Assembly rules for the .S files +#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S) +# $(call if_changed_dep,vdso-ilp32as) + +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S + $(call if_changed_dep,vdso-ilp32as) + +$(obj)/note-ilp32.o: $(src)/../vdso/note.S + $(call if_changed_dep,vdso-ilp32as) + +# This one should be fine because ILP32 uses the same generic +# __NR_rt_sigreturn syscall number. +$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S + $(call if_changed_dep,vdso-ilp32as) + +# Actual build commands +quiet_cmd_vdso-ilp32ld = VDSOILP32L $@ + cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32 -Wl,-n -Wl,-T $^ -o $@ +quiet_cmd_vdso-ilp32as = VDSOILP32A $@ + cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $< + +# Install commands for the unstripped file +quiet_cmd_vdso_install = INSTALL $@ + cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ + +vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg + @mkdir -p $(MODLIB)/vdso + $(call cmd,vdso_install) + +vdso_install: vdso-ilp32.so diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S new file mode 100644 index 0000000..46ac072 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S @@ -0,0 +1,33 @@ +/* + * 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 . + * + * Author: Will Deacon + */ + +#include +#include +#include +#include + + __PAGE_ALIGNED_DATA + + .globl vdso_ilp32_start, vdso_ilp32_end + .balign PAGE_SIZE +vdso_ilp32_start: + .incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so" + .balign PAGE_SIZE +vdso_ilp32_end: + + .previous diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S new file mode 100644 index 0000000..ba98794 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S @@ -0,0 +1,95 @@ +/* + * 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 . + * + * Author: Will Deacon + * Heavily based on the vDSO linker scripts for other archs. + */ + +#include +#include +#include + +SECTIONS +{ + PROVIDE(_vdso_data = . - PAGE_SIZE); + . = VDSO_LBASE + 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 + + . = ALIGN(16); + + .text : { *(.text*) } :text =0xd503201f + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + + .dynamic : { *(.dynamic) } :text :dynamic + + .rodata : { *(.rodata*) } :text + + _end = .; + PROVIDE(end = .); + + /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; +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_4.10 { + global: + __kernel_rt_sigreturn; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + local: *; + }; +} + +/* + * Make the sigreturn code visible to the kernel. + */ +VDSO_sigtramp_ilp32 = __kernel_rt_sigreturn; diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 9d44902..71bee92 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -37,8 +37,13 @@ #include #include -extern char vdso_start, vdso_end; -static unsigned long vdso_pages __ro_after_init; +extern char vdso_lp64_start, vdso_lp64_end; +static unsigned long vdso_lp64_pages __ro_after_init; + +#ifdef CONFIG_ARM64_ILP32 +extern char vdso_ilp32_start, vdso_ilp32_end; +static unsigned long vdso_ilp32_pages __ro_after_init; +#endif /* * The vDSO data page. @@ -110,7 +115,17 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) } #endif /* CONFIG_AARCH32_EL0 */ -static struct vm_special_mapping vdso_spec[2] __ro_after_init = { +static struct vm_special_mapping vdso_lp64_spec[2] __ro_after_init = { + { + .name = "[vvar]", + }, + { + .name = "[vdso]", + }, +}; + +#ifdef CONFIG_ARM64_ILP32 +static struct vm_special_mapping vdso_ilp32_spec[2] __ro_after_init = { { .name = "[vvar]", }, @@ -118,21 +133,27 @@ static struct vm_special_mapping vdso_spec[2] __ro_after_init = { .name = "[vdso]", }, }; +#endif -static int __init vdso_init(void) +static int __init vdso_init(char *vdso_start, char *vdso_end, + unsigned long *vdso_pagesp, + struct vm_special_mapping *vdso_spec) { int i; + unsigned long vdso_pages; struct page **vdso_pagelist; unsigned long pfn; - if (memcmp(&vdso_start, "\177ELF", 4)) { + if (memcmp(vdso_start, "\177ELF", 4)) { pr_err("vDSO is not a valid ELF object!\n"); return -EINVAL; } - vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; + vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; + *vdso_pagesp = vdso_pages; pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n", - vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data); + vdso_pages + 1, vdso_pages, + vdso_start, 1L, vdso_data); /* Allocate the vDSO pagelist, plus a page for the data. */ vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *), @@ -145,7 +166,7 @@ static int __init vdso_init(void) /* Grab the vDSO code pages. */ - pfn = sym_to_pfn(&vdso_start); + pfn = sym_to_pfn(vdso_start); for (i = 0; i < vdso_pages; i++) vdso_pagelist[i + 1] = pfn_to_page(pfn + i); @@ -155,7 +176,22 @@ static int __init vdso_init(void) return 0; } -arch_initcall(vdso_init); + +static int __init vdso_lp64_init(void) +{ + return vdso_init(&vdso_lp64_start, &vdso_lp64_end, + &vdso_lp64_pages, vdso_lp64_spec); +} +arch_initcall(vdso_lp64_init); + +#ifdef CONFIG_ARM64_ILP32 +static int __init vdso_ilp32_init(void) +{ + return vdso_init(&vdso_ilp32_start, &vdso_ilp32_end, + &vdso_ilp32_pages, vdso_ilp32_spec); +} +arch_initcall(vdso_ilp32_init); +#endif int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) @@ -163,8 +199,17 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, struct mm_struct *mm = current->mm; unsigned long vdso_base, vdso_text_len, vdso_mapping_len; void *ret; + unsigned long pages = vdso_lp64_pages; + struct vm_special_mapping *vdso_spec = vdso_lp64_spec; + +#ifdef CONFIG_ARM64_ILP32 + if (is_ilp32_compat_task()) { + pages = vdso_ilp32_pages; + vdso_spec = vdso_ilp32_spec; + } +#endif - vdso_text_len = vdso_pages << PAGE_SHIFT; + vdso_text_len = pages << PAGE_SHIFT; /* Be sure to map the data page */ vdso_mapping_len = vdso_text_len + PAGE_SIZE; diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index e00b467..062a33d 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S @@ -25,6 +25,16 @@ #define NSEC_PER_SEC_LO16 0xca00 #define NSEC_PER_SEC_HI16 0x3b9a +#ifdef __LP64__ +#define PTR_REG(n) x##n +#define OFFSET(n) n +#define DELOUSE(n) +#else +#define PTR_REG(n) w##n +#define OFFSET(n) COMPAT_##n +#define DELOUSE(n) mov w##n, w##n +#endif + vdso_data .req x6 seqcnt .req w7 w_tmp .req w8 @@ -119,7 +129,7 @@ x_tmp .req x8 .if \shift == 1 lsr x11, x11, x12 .endif - stp x10, x11, [x1, #TSPEC_TV_SEC] + stp PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)] mov x0, xzr ret .endm @@ -136,6 +146,8 @@ x_tmp .req x8 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */ ENTRY(__kernel_gettimeofday) .cfi_startproc + DELOUSE(0) + DELOUSE(1) adr vdso_data, _vdso_data /* If tv is NULL, skip to the timezone code. */ cbz x0, 2f @@ -160,7 +172,7 @@ ENTRY(__kernel_gettimeofday) mov x13, #1000 lsl x13, x13, x12 udiv x11, x11, x13 - stp x10, x11, [x0, #TVAL_TV_SEC] + stp PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)] 2: /* If tz is NULL, return 0. */ cbz x1, 3f @@ -182,6 +194,7 @@ ENDPROC(__kernel_gettimeofday) /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */ ENTRY(__kernel_clock_gettime) .cfi_startproc + DELOUSE(1) cmp w0, #JUMPSLOT_MAX b.hi syscall adr vdso_data, _vdso_data @@ -297,6 +310,7 @@ ENDPROC(__kernel_clock_gettime) /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */ ENTRY(__kernel_clock_getres) .cfi_startproc + DELOUSE(1) cmp w0, #CLOCK_REALTIME ccmp w0, #CLOCK_MONOTONIC, #0x4, ne ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne @@ -311,7 +325,7 @@ ENTRY(__kernel_clock_getres) ldr x2, 6f 2: cbz w1, 3f - stp xzr, x2, [x1] + stp PTR_REG(zr), PTR_REG(2), [x1] 3: /* res == NULL. */ mov w0, wzr diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S index 82379a7..a40ae24 100644 --- a/arch/arm64/kernel/vdso/vdso.S +++ b/arch/arm64/kernel/vdso/vdso.S @@ -21,12 +21,12 @@ #include #include - .globl vdso_start, vdso_end + .globl vdso_lp64_start, vdso_lp64_end .section .rodata .balign PAGE_SIZE -vdso_start: +vdso_lp64_start: .incbin "arch/arm64/kernel/vdso/vdso.so" .balign PAGE_SIZE -vdso_end: +vdso_lp64_end: .previous -- 2.7.4