Received: by 2002:a05:6358:16cc:b0:ea:6187:17c9 with SMTP id r12csp5890867rwl; Mon, 9 Jan 2023 00:58:30 -0800 (PST) X-Google-Smtp-Source: AMrXdXuSV1aB+DPpZzqImgNF1kU0/OpF80rCLzE3Wm2oVL+mUdS6tULaauBnLiXXvsq+MdthtRWS X-Received: by 2002:a17:90b:215:b0:225:bf26:4928 with SMTP id fy21-20020a17090b021500b00225bf264928mr65519095pjb.38.1673254710045; Mon, 09 Jan 2023 00:58:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673254710; cv=none; d=google.com; s=arc-20160816; b=qJlB302KE2nZskrAcvON7ijgm6PZeoQc6NDAsRiKoGjP3f1wtdkO5Snmmjf6/sH7ca 00pKzflwPshjLFW1CgdJBr7oQYcSxlabr0EBQeAIMRPzc6x2kUfzCP+nkvRgcIs/LRmb iukbuavgb/NfNue4Ir90mDhcOe9evwovTqnjfLsGaTC0m1gyfGnU4XTuEKlPh+N39fts 0a8l125d+d08CZ43t9Wcel8aJksAGuq8drjzloJf6BN96eLBPOLvSiwalPKmUsPRCU9n ILhGhUzafRF9yoO8GdvAcysAchEscGdci+11LkJocb6SwWlTBgeTlcGBt7EgFputlyxN MtbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=keNyq6h/XjSl/s4eShHesqnlC9PvUeVBgtmAEPuNfJc=; b=xxXbhp6c9ztDBPwDyUb9BOXPjUbF6eoiVJaamM1su8/GHMOMHw5eDIC6Mh1Wq3DGUp 1ZzZN9OmrdJp05uN5BBBfZJekvnJfqj5tBRsI614cAehE5r/Ln/fdxV5ov0FHmYdGPpx OiX78zQltcA66nLwffVX0xM+qyIqXOMTR/VrMQLWb2eFhRKhZ0vQ0DflyRzS3t7W+hmw aw7q+t0jJM9r2HLdPid53PB7XrjeqnvbitTfpc5vXjKg7cX8Gg9ddnq+VQ8NulKLx+FH awvPpdk7GSg1EZGv5JP37L9KdqVCgy/hyFI3lKjm56mtdD6KZrUQtPWc5AkHWK6GhJ4y pubQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id me9-20020a17090b17c900b002264b91f24bsi8166440pjb.176.2023.01.09.00.58.23; Mon, 09 Jan 2023 00:58:30 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236733AbjAIIqB (ORCPT + 54 others); Mon, 9 Jan 2023 03:46:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236852AbjAIIn6 (ORCPT ); Mon, 9 Jan 2023 03:43:58 -0500 Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6342414013 for ; Mon, 9 Jan 2023 00:42:42 -0800 (PST) Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id 3098gCUY027422; Mon, 9 Jan 2023 09:42:12 +0100 From: Willy Tarreau To: "Paul E. McKenney" Cc: linux-kernel@vger.kernel.org, Willy Tarreau Subject: [PATCH 03/22] tools/nolibc: support thumb mode with frame pointers on ARM Date: Mon, 9 Jan 2023 09:41:49 +0100 Message-Id: <20230109084208.27355-4-w@1wt.eu> X-Mailer: git-send-email 2.17.5 In-Reply-To: <20230109084208.27355-1-w@1wt.eu> References: <20230109084208.27355-1-w@1wt.eu> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In Thumb mode, register r7 is normally used to store the frame pointer. By default when optimizing at -Os there's no frame pointer so this works fine. But if no optimization is set, then build errors occur, indicating that r7 cannot not be used. It's difficult to cheat because it's the compiler that is complaining, not the assembler, so it's not even possible to report that the register was clobbered. The solution consists in saving and restoring r7 around the syscall, but this slightly inflates the code. The syscall number is passed via r6 which is never used by syscalls. The current patch adds a few macroes which do that only in Thumb mode, and which continue to directly assign the syscall number to register r7 in ARM mode. Now this always builds and works for all modes (tested on Arm, Thumbv1, Thumbv2 modes, at -Os, -O0, -O0 -fomit-frame-pointer). The code is very slightly inflated in thumb-mode without frame-pointers compared to previously (e.g. 7928 vs 7864 bytes for nolibc-test) but at least it's always operational. And it's possible to disable this mechanism by setting NOLIBC_OMIT_FRAME_POINTER. Signed-off-by: Willy Tarreau --- tools/include/nolibc/arch-arm.h | 60 ++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h index e4ba77b0310f..ef94df2d93d5 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -70,20 +70,44 @@ struct sys_stat_struct { * don't have to experience issues with register constraints. * - the syscall number is always specified last in order to allow to force * some registers before (gcc refuses a %-register at the last position). + * - in thumb mode without -fomit-frame-pointer, r7 is also used to store the + * frame pointer, and we cannot directly assign it as a register variable, + * nor can we clobber it. Instead we assign the r6 register and swap it + * with r7 before calling svc, and r6 is marked as clobbered. + * We're just using any regular register which we assign to r7 after saving + * it. * * Also, ARM supports the old_select syscall if newselect is not available */ #define __ARCH_WANT_SYS_OLD_SELECT +#if (defined(__THUMBEB__) || defined(__THUMBEL__)) && \ + !defined(NOLIBC_OMIT_FRAME_POINTER) +/* swap r6,r7 needed in Thumb mode since we can't use nor clobber r7 */ +#define _NOLIBC_SYSCALL_REG "r6" +#define _NOLIBC_THUMB_SET_R7 "eor r7, r6\neor r6, r7\neor r7, r6\n" +#define _NOLIBC_THUMB_RESTORE_R7 "mov r7, r6\n" + +#else /* we're in ARM mode */ +/* in Arm mode we can directly use r7 */ +#define _NOLIBC_SYSCALL_REG "r7" +#define _NOLIBC_THUMB_SET_R7 "" +#define _NOLIBC_THUMB_RESTORE_R7 "" + +#endif /* end THUMB */ + #define my_syscall0(num) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0"); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ - : "r"(_num) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r"(_num) \ + : "r"(_arg1), \ + "r"(_num) \ : "memory", "cc", "lr" \ ); \ _arg1; \ @@ -91,12 +115,14 @@ struct sys_stat_struct { #define my_syscall1(num, arg1) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -106,13 +132,15 @@ struct sys_stat_struct { #define my_syscall2(num, arg1, arg2) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -122,14 +150,16 @@ struct sys_stat_struct { #define my_syscall3(num, arg1, arg2, arg3) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -139,15 +169,17 @@ struct sys_stat_struct { #define my_syscall4(num, arg1, arg2, arg3, arg4) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ register long _arg4 __asm__ ("r3") = (long)(arg4); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -157,7 +189,7 @@ struct sys_stat_struct { #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ @@ -165,8 +197,10 @@ struct sys_stat_struct { register long _arg5 __asm__ ("r4") = (long)(arg5); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r" (_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ "r"(_num) \ : "memory", "cc", "lr" \ -- 2.17.5