Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp1339944ybk; Sat, 16 May 2020 08:13:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzwqIKQfgg/yIMCpm2SQPD1jw3ILWxPB5ZzRrkzqKpkv660UXmDFdtk7Ep38Y41RkKRPyoc X-Received: by 2002:a17:906:29d9:: with SMTP id y25mr7557960eje.198.1589642036367; Sat, 16 May 2020 08:13:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589642036; cv=none; d=google.com; s=arc-20160816; b=Fq3Cnuu8JAEh1Z642jt/NLRpWT7HSr9GYRPWcoFKTNoXCRH1zESoqJFqIjl009lWKr 7dvg68M/a6bCyw9V/Sd778yxoGk9t5Eoygk/PQ+q27qy06i2HTfNQm0wjVaaBGFUgigu /eibhpOwHhmKjR6wAJhx5x5qsbmN5xzCaZG2bXu/m9gG9CzDMAeK5WQ24znqDZD+ii90 G7IY4MjVgHAjqMxnIk0Tar62p31b1lztWD/1jjZ6wSF4EH42aifiITqebvwGIKCe3umo 5jsrr30BXWnSnPqpMQeoIqo744PyuT/uxd+FGby5TrIJhtadKLsaKMpX1MPuLAkRv2Sc y/VA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :robot-unsubscribe:robot-id:message-id:mime-version:references :in-reply-to:cc:subject:to:reply-to:from:date; bh=s/IyI1CaT3EUe+wfde7Jc2ik+sg3dtu5YmwW77A61+Y=; b=Dsy2zycY7p7Y0hyUx3C9euOv2o1TMKXUMp1Uf3jmOv7XkF+fh2w2OIf77dpMTltkd5 i3xP/HtsEcH8a2ODEZgU1bT0M2GHTzLeNvtAGaU2Gf6Ff6EYqacQziZDFxTopbW/ObNE fCOW4sg1WKpr2UCR9Gs0LujaIth1ipXzqebQzCyqhAvO5fTWs8MMfYbKU1jrFc4ujxm3 41GgnmWRvPCSuKMLXbOXCaHsYVINEC+kIU0jGm0HPSF1Wn+3VDuq9jELR4KwmglSN598 WE07V1IPZAjYtDaJ8AVedMbLN1XB2x0SVapMUstkyFasfyR60HbwwFA3abkMHsQnFnIq Frkg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dj12si3177578edb.173.2020.05.16.08.13.33; Sat, 16 May 2020 08:13:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727050AbgEPPK5 (ORCPT + 99 others); Sat, 16 May 2020 11:10:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41082 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726907AbgEPPK3 (ORCPT ); Sat, 16 May 2020 11:10:29 -0400 Received: from Galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92EFDC05BD0A; Sat, 16 May 2020 08:10:29 -0700 (PDT) Received: from [5.158.153.53] (helo=tip-bot2.lab.linutronix.de) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1jZyS9-0000rM-VK; Sat, 16 May 2020 17:10:18 +0200 Received: from [127.0.1.1] (localhost [IPv6:::1]) by tip-bot2.lab.linutronix.de (Postfix) with ESMTP id 03F091C01BB; Sat, 16 May 2020 17:10:16 +0200 (CEST) Date: Sat, 16 May 2020 15:10:15 -0000 From: "tip-bot2 for Yu-cheng Yu" Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/fpu] x86/fpu/xstate: Restore supervisor states for signal return Cc: "Yu-cheng Yu" , Borislav Petkov , Dave Hansen , x86 , LKML In-Reply-To: <20200512145444.15483-11-yu-cheng.yu@intel.com> References: <20200512145444.15483-11-yu-cheng.yu@intel.com> MIME-Version: 1.0 Message-ID: <158964181586.17951.14503333423157907999.tip-bot2@tip-bot2> X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the x86/fpu branch of tip: Commit-ID: 55e00fb66fd5048f4a3ee357018fd26fc527abca Gitweb: https://git.kernel.org/tip/55e00fb66fd5048f4a3ee357018fd26fc527abca Author: Yu-cheng Yu AuthorDate: Tue, 12 May 2020 07:54:44 -07:00 Committer: Borislav Petkov CommitterDate: Sat, 16 May 2020 12:20:50 +02:00 x86/fpu/xstate: Restore supervisor states for signal return The signal return fast path directly restores user states from the user buffer. Once that succeeds, restore supervisor states (but only when they are not yet restored). For the slow path, save supervisor states to preserve them across context switches, and restore after the user states are restored. The previous version has the overhead of an XSAVES in both the fast and the slow paths. It is addressed as the following: - In the fast path, only do an XRSTORS. - In the slow path, do a supervisor-state-only XSAVES, and relocate the buffer contents. Some thoughts in the implementation: - In the slow path, can any supervisor state become stale between save/restore? Answer: set_thread_flag(TIF_NEED_FPU_LOAD) protects the xstate buffer. - In the slow path, can any code reference a stale supervisor state register between save/restore? Answer: In the current lazy-restore scheme, any reference to xstate registers needs fpregs_lock()/fpregs_unlock() and __fpregs_load_activate(). - Are there other options? One other option is eagerly restoring all supervisor states. Currently, CET user-mode states and ENQCMD's PASID do not need to be eagerly restored. The upcoming CET kernel-mode states (24 bytes) need to be eagerly restored. To me, eagerly restoring all supervisor states adds more overhead then benefit at this point. Signed-off-by: Yu-cheng Yu Signed-off-by: Borislav Petkov Reviewed-by: Dave Hansen Link: https://lkml.kernel.org/r/20200512145444.15483-11-yu-cheng.yu@intel.com --- arch/x86/kernel/fpu/signal.c | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 6184fe7..9393a44 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -347,6 +347,23 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) ret = copy_user_to_fpregs_zeroing(buf_fx, user_xfeatures, fx_only); pagefault_enable(); if (!ret) { + + /* + * Restore supervisor states: previous context switch + * etc has done XSAVES and saved the supervisor states + * in the kernel buffer from which they can be restored + * now. + * + * We cannot do a single XRSTORS here - which would + * be nice - because the rest of the FPU registers are + * being restored from a user buffer directly. The + * single XRSTORS happens below, when the user buffer + * has been copied to the kernel one. + */ + if (test_thread_flag(TIF_NEED_FPU_LOAD) && + xfeatures_mask_supervisor()) + copy_kernel_to_xregs(&fpu->state.xsave, + xfeatures_mask_supervisor()); fpregs_mark_activate(); fpregs_unlock(); return 0; @@ -364,14 +381,25 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) } /* - * The current state of the FPU registers does not matter. By setting - * TIF_NEED_FPU_LOAD unconditionally it is ensured that the our xstate - * is not modified on context switch and that the xstate is considered + * By setting TIF_NEED_FPU_LOAD it is ensured that our xstate is + * not modified on context switch and that the xstate is considered * to be loaded again on return to userland (overriding last_cpu avoids * the optimisation). */ - set_thread_flag(TIF_NEED_FPU_LOAD); + fpregs_lock(); + + if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { + + /* + * Supervisor states are not modified by user space input. Save + * current supervisor states first and invalidate the FPU regs. + */ + if (xfeatures_mask_supervisor()) + copy_supervisor_to_kernel(&fpu->state.xsave); + set_thread_flag(TIF_NEED_FPU_LOAD); + } __fpu_invalidate_fpregs_state(fpu); + fpregs_unlock(); if (use_xsave() && !fx_only) { u64 init_bv = xfeatures_mask_user() & ~user_xfeatures; @@ -393,7 +421,13 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) fpregs_lock(); if (unlikely(init_bv)) copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); - ret = copy_kernel_to_xregs_err(&fpu->state.xsave, user_xfeatures); + + /* + * Restore previously saved supervisor xstates along with + * copied-in user xstates. + */ + ret = copy_kernel_to_xregs_err(&fpu->state.xsave, + user_xfeatures | xfeatures_mask_supervisor()); } else if (use_fxsr()) { ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);