Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp18006380ybl; Thu, 2 Jan 2020 16:41:03 -0800 (PST) X-Google-Smtp-Source: APXvYqxUe/rqv8ROag+k8/rbxbEd9Pqnc3blmkZaWCNxiY9KK13os2OQDixn0E7edKDlyBV7IARn X-Received: by 2002:a9d:ee2:: with SMTP id 89mr33326183otj.270.1578012063436; Thu, 02 Jan 2020 16:41:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578012063; cv=none; d=google.com; s=arc-20160816; b=LjcGBD0eza+YTNeHWlYMOy/NXc4Z1RM9ICJIai30msDA8xyd12c6BYymYsfwg4kHhr B6YC2xV5reZMVAeio15HU8hJ0rqKhWJpyFYFNvHzqL7aFA+njFcbs7UcuuKeX18bQjrr 2rxRh3GXWqBhE6/m8gFPipT/V+0qGS5w6AAs84vYq4tfyJejgxfrYIn++4UlOYtsE8iy Xfz68FVPCFWQ9jZS3e5K/X9B89ttp4BsV1JIfJTbWZdTRy4yQVB+nsKbacl8g8wYhN1H EMZ2Xnk5DujQ7PL92MK/74FuER+KcTwhTkn5jS+WKA6TXVUBaS9HgYItbN2TDIY+CwlE x4Yw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=3XbpzRISsRnAWo64hPWxTD8VrNV6vVLizRH94il6B8k=; b=DB6Ht/+0BdWhUGFECdHaAoSK44Ex1HEzfIjgZSuMVYw+xWpRqCLR65+uKvZXr35PZO scuTsMmr1BUcjd8vqHdSF4GNCJzGYVHX1Jw2HRA1bn8zYZ6g8pKvTD4eZ76tSLeaaQ/i h7SZ8fkmjDGEibA36DiKoFPALm7hy1y+jSsz13c0XvMYKMiciEH5zESvJ3fRinibrwvm SflmuXb9wz58IuHJ9bOkIjAkG3lmk1D5DblPIrVOFsDH9YRcQs735yok8hVNNTA3iJnq 2j2Eg8fiQABPikGwn9Hc/KMnegxBTlIafOnQQL09rbCaRYuvpuoa/3SnzP0HYHoOt538 1ajQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z11si24946784otm.312.2020.01.02.16.40.50; Thu, 02 Jan 2020 16:41:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726118AbgACAkH (ORCPT + 99 others); Thu, 2 Jan 2020 19:40:07 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:41045 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725872AbgACAkG (ORCPT ); Thu, 2 Jan 2020 19:40:06 -0500 Received: by mail-pf1-f193.google.com with SMTP id w62so22789569pfw.8; Thu, 02 Jan 2020 16:40:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=3XbpzRISsRnAWo64hPWxTD8VrNV6vVLizRH94il6B8k=; b=Iwerr1DZ1TVJmzzy7+Mcn37Ss9n7XF5c/1Yf7A+uGaM58TUM+79fqfWGlelMwd9X/U m3X1mexxrA+l4dHeoAu+a4nJc2VjgYafOjbyDU+bv6o0MM17fhCvKbv4mKrYuiE8cF/9 EGYIxkpTZ6yzjLUTZzMqx7bPG/GxK73MAr2EOXW0MPBKVp+HPA29N56oc4gZOyamE6Aw MIKv0EGJGnUeuLjxRBdqBK5QAOPvNWhZLuT89hckJtlOo5PBnM6ILVzMIG623+e5MYa/ jnVV0EZmwfkhAQSQ15jgwB1DLCzBb5r6gRmkAoSZqWIOrZF6J/RzI2MpfAe18v9yhPN3 uAEg== X-Gm-Message-State: APjAAAX5MMcq0yATiLMCSSDtB+DA1EYG18g9FmMJs1Uzk4+LKblbfyfa kjswGLsJQZaKlVm8l0P1c/figlFFf+kXSg== X-Received: by 2002:a63:597:: with SMTP id 145mr89378717pgf.384.1578012005481; Thu, 02 Jan 2020 16:40:05 -0800 (PST) Received: from localhost ([2601:646:8a00:9810::55]) by smtp.gmail.com with ESMTPSA id k1sm12225897pjl.21.2020.01.02.16.40.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Jan 2020 16:40:04 -0800 (PST) Date: Thu, 2 Jan 2020 16:42:29 -0800 From: Paul Burton To: Vincenzo Frascino Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, "Jason A. Donenfeld" , Arnd Bergmann , Christian Brauner , stable@vger.kernel.org Subject: Re: [PATCH v2] MIPS: Avoid VDSO ABI breakage due to global register variable Message-ID: <20200103004229.lpbhocebuny6vxmf@lantea.localdomain> References: <20200102005343.GA495913@rani.riverdale.lan> <20200102045038.102772-1-paulburton@kernel.org> <754c5d05-4455-5ce1-475d-55c2191a06cf@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <754c5d05-4455-5ce1-475d-55c2191a06cf@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Vincenzo, On Thu, Jan 02, 2020 at 04:56:00PM +0000, Vincenzo Frascino wrote: > Hi Paul, > > Happy new year. Thanks; happy new year to you too! > On 02/01/2020 04:50, Paul Burton wrote: > > Declaring __current_thread_info as a global register variable has the > > effect of preventing GCC from saving & restoring its value in cases > > where the ABI would typically do so. > > > > To quote GCC documentation: > > > >> If the register is a call-saved register, call ABI is affected: the > >> register will not be restored in function epilogue sequences after the > >> variable has been assigned. Therefore, functions cannot safely return > >> to callers that assume standard ABI. > > > > When our position independent VDSO is built for the n32 or n64 ABIs all > > functions it exposes should be preserving the value of $gp/$28 for their > > caller, but in the presence of the __current_thread_info global register > > variable GCC stops doing so & simply clobbers $gp/$28 when calculating > > the address of the GOT. > > > > In cases where the VDSO returns success this problem will typically be > > masked by the caller in libc returning & restoring $gp/$28 itself, but > > that is by no means guaranteed. In cases where the VDSO returns an error > > libc will typically contain a fallback path which will now fail > > (typically with a bad memory access) if it attempts anything which > > relies upon the value of $gp/$28 - eg. accessing anything via the GOT. > > > > First of all good catch. I just came back from holidays and seems that you guys > had fun without me :) The fun never stops ;) > Did you consider the option to use "-ffixed-gp -ffixed-28" as a compilation > flags for the vDSO library (Arvind was mentioning it as well in his reply)? > According to the GCC manual "treats the register as a fixed register; generated > code should never refer to it" > (https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options) > > I did some experiments this morning an seems that on MIPS the convention is not > honored at least on GCC-9. Do you know who to contact to get it enabled/fixed in > the compiler? > > With this: > > Reviewed-by: Vincenzo Frascino > Tested-by: Vincenzo Frascino Using -ffixed-gp wouldn't be correct for the VDSO - the VDSO itself is position independent code, and will need to use $gp to access the GOT which is part of how position-independence is achieved (technically you could access the GOT using another register of course but you'd need some way to persuade the compiler to break with convention & you'd gain nothing meaningful since you'd need to use some other register anyway). If we use -ffixed-gp then we're telling GCC not to use $gp, and that doesn't make sense. If we consider -ffixed-gp as telling GCC not to use $gp as a general purpose register then it's meaningless because $gp already has a specific use & isn't used as a general purpose register. If we consider -ffixed-gp as telling GCC not to use $gp at all then it doesn't make sense because it needs to in order to access the GOT. In terms of GCC's flags we'd want to use -fcall-saved-gp, but that would just be telling GCC information it already knows about the n32 & n64 ABIs & indeed it seems to have no effect at all on the way GCC handles the global register variable - it doesn't cause gcc to save & restore $gp with the global register variable present, so you gain nothing. We could use -ffixed-gp for the kernel proper (& not the VDSO), but: 1) The kernel builds as non-PIC code with no $gp-based optimizations enabled, and since this has been fine forever it seems safe to expect the compiler not to start using $gp in new ways. 2) It would be a separate issue to fixing the VDSO anyway. So I'll go ahead with the v2 patch without changing compiler flags for now. Thanks, Paul > > One fix for this would be to move the declaration of > > __current_thread_info inside the current_thread_info() function, > > demoting it from global register variable to local register variable & > > avoiding inadvertently creating a non-standard calling ABI for the VDSO. > > Unfortunately this causes issues for clang, which doesn't support local > > register variables as pointed out by commit fe92da0f355e ("MIPS: Changed > > current_thread_info() to an equivalent supported by both clang and GCC") > > which introduced the global register variable before we had a VDSO to > > worry about. > > > > Instead, fix this by continuing to use the global register variable for > > the kernel proper but declare __current_thread_info as a simple extern > > variable when building the VDSO. It should never be referenced, and will > > cause a link error if it is. This resolves the calling convention issue > > for the VDSO without having any impact upon the build of the kernel > > itself for either clang or gcc. > > > > Signed-off-by: Paul Burton > > Reported-by: "Jason A. Donenfeld" > > Fixes: ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") > > Cc: Arnd Bergmann > > Cc: Christian Brauner > > Cc: Vincenzo Frascino > > Cc: # v4.4+ > > --- > > Changes in v2: > > - Switch to the #ifdef __VDSO__ approach rather than using a local > > register variable which clang doesn't support. > > --- > > arch/mips/include/asm/thread_info.h | 20 +++++++++++++++++++- > > 1 file changed, 19 insertions(+), 1 deletion(-) > > > > diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h > > index 4993db40482c..ee26f9a4575d 100644 > > --- a/arch/mips/include/asm/thread_info.h > > +++ b/arch/mips/include/asm/thread_info.h > > @@ -49,8 +49,26 @@ struct thread_info { > > .addr_limit = KERNEL_DS, \ > > } > > > > -/* How to get the thread information struct from C. */ > > +/* > > + * A pointer to the struct thread_info for the currently executing thread is > > + * held in register $28/$gp. > > + * > > + * We declare __current_thread_info as a global register variable rather than a > > + * local register variable within current_thread_info() because clang doesn't > > + * support explicit local register variables. > > + * > > + * When building the VDSO we take care not to declare the global register > > + * variable because this causes GCC to not preserve the value of $28/$gp in > > + * functions that change its value (which is common in the PIC VDSO when > > + * accessing the GOT). Since the VDSO shouldn't be accessing > > + * __current_thread_info anyway we declare it extern in order to cause a link > > + * failure if it's referenced. > > + */ > > +#ifdef __VDSO__ > > +extern struct thread_info *__current_thread_info; > > +#else > > register struct thread_info *__current_thread_info __asm__("$28"); > > +#endif > > > > static inline struct thread_info *current_thread_info(void) > > { > > > > -- > Regards, > Vincenzo