Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp2904064pxb; Tue, 24 Aug 2021 10:15:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxhkiHao8b9v5ASOYTsVHjKyFbzLBdBZY5rzprh4hGr6pJBT7llLK9CCNWwD/nBVSLCsXKA X-Received: by 2002:a05:6638:f87:: with SMTP id h7mr7217778jal.77.1629825330417; Tue, 24 Aug 2021 10:15:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629825330; cv=none; d=google.com; s=arc-20160816; b=szlU98OEQtf1L9nnl5ppebdzOm1sheTeByYrlmmRCFOiPMkiU5Ux3Z7vWqzCKxu5eX awpxL3f69Pq28keP79ziT7gU0bHwZNqoxPMcvVlZRA31ZMXW54ExY/gwW7oWsdh2XkzX sWKuPaf+KTTNiQaPgm0DsBkfmq9nBLiGqD7eHu0wMlVRYee2cdsjRqs9XfOTSYwjcQ8k 3DjKOStMCtHMtcT2SLvA/Z+JmTk2L2J/yDsUhsMWEE4PXanzmNpixedApi+5gUhKfSv2 sdGZpyi6xG8RbWu5D1u8TKJQeAKdvbhFQeW7GChQv7/9CbUxUFg8QHYLucRBJzbV8IxR iQgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=e2sEkp6e0OUXPZSNdw0+189AlWVlzlyDI97aw/IrGeE=; b=JstN4c2mRt1sJ+ruvPgndhzs0BNjYtTwwLzKRHs0ZFo5hsUpLXa/2fOPBp3N0ZWNQv CEXLIoEGFKCWuezWTQilJir4LvOvDl0d/G5uIw7aSvNIS4drTKTmuc1V0+te9/B05Vna UGzf1BLYIyQPHPaXdK9iVWyI0ANFscDL/UxpiCVGMPoTQrq4WTtOPUWkMFyFT5McWv44 sO1+Xh5QxGFVEJvPShiKtJUscR8TdFcQVL1iZpYAUYWYAi/5jDMkab+dlZcCbqzfwjr2 rPSnFji4PjXhDa+H4Eklk8oWmhxMBlHc6Lfp/ZeHhUopFRPa4DfwTbrO6ZZPknubm3yD rkDg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ogA2svae; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l5si709376jaj.63.2021.08.24.10.15.17; Tue, 24 Aug 2021 10:15:30 -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; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ogA2svae; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239159AbhHXRPP (ORCPT + 99 others); Tue, 24 Aug 2021 13:15:15 -0400 Received: from mail.kernel.org ([198.145.29.99]:51854 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239353AbhHXRL0 (ORCPT ); Tue, 24 Aug 2021 13:11:26 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 300F061076; Tue, 24 Aug 2021 17:01:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1629824470; bh=5b5rrNwDGe9yvgDBECqguxRhEFwp3vKcoDsh2wsRtmk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ogA2svaerDgzO+u7pUjG7Pmm5t6zoX/3Dm8CVeym5Rf5RapmGXL7DO7gG7ec1atFN 7dFECDIHPyYBjp5hn+hukt5zbMqKska+o85Tbz4E7slup6QLXd4rRzo3ptNpFIlUKn ifYFaafGe4F5gV0MRF1WyYXhFjuxEegp+cEWTennMDDK3m91Wnlb+ZL/ChYNg1ODAr sPxczMoG9tlJGgjP6xcuimV2XuHAxayHjWACN7plXFXSr5c6y6gnSiv+CUSLnZcuKZ 4DD8U+ihZA3HFz9J7f7iB4SUIf9r+qxMc4a1PlAXKHxweStWiLVNRALDaz1BMIEiTD /RpHp/ZG7hQ7w== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Thomas Gleixner , Borislav Petkov , Greg Kroah-Hartman Subject: [PATCH 5.4 02/61] x86/fpu: Make init_fpstate correct with optimized XSAVE Date: Tue, 24 Aug 2021 13:00:07 -0400 Message-Id: <20210824170106.710221-3-sashal@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210824170106.710221-1-sashal@kernel.org> References: <20210824170106.710221-1-sashal@kernel.org> MIME-Version: 1.0 X-KernelTest-Patch: http://kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.143-rc1.gz X-KernelTest-Tree: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git X-KernelTest-Branch: linux-5.4.y X-KernelTest-Patches: git://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git X-KernelTest-Version: 5.4.143-rc1 X-KernelTest-Deadline: 2021-08-26T17:01+00:00 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Thomas Gleixner commit f9dfb5e390fab2df9f7944bb91e7705aba14cd26 upstream. The XSAVE init code initializes all enabled and supported components with XRSTOR(S) to init state. Then it XSAVEs the state of the components back into init_fpstate which is used in several places to fill in the init state of components. This works correctly with XSAVE, but not with XSAVEOPT and XSAVES because those use the init optimization and skip writing state of components which are in init state. So init_fpstate.xsave still contains all zeroes after this operation. There are two ways to solve that: 1) Use XSAVE unconditionally, but that requires to reshuffle the buffer when XSAVES is enabled because XSAVES uses compacted format. 2) Save the components which are known to have a non-zero init state by other means. Looking deeper, #2 is the right thing to do because all components the kernel supports have all-zeroes init state except the legacy features (FP, SSE). Those cannot be hard coded because the states are not identical on all CPUs, but they can be saved with FXSAVE which avoids all conditionals. Use FXSAVE to save the legacy FP/SSE components in init_fpstate along with a BUILD_BUG_ON() which reminds developers to validate that a newly added component has all zeroes init state. As a bonus remove the now unused copy_xregs_to_kernel_booting() crutch. The XSAVE and reshuffle method can still be implemented in the unlikely case that components are added which have a non-zero init state and no other means to save them. For now, FXSAVE is just simple and good enough. [ bp: Fix a typo or two in the text. ] Fixes: 6bad06b76892 ("x86, xsave: Use xsaveopt in context-switch path when supported") Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov Reviewed-by: Borislav Petkov Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210618143444.587311343@linutronix.de Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/fpu/internal.h | 30 ++++++----------------- arch/x86/kernel/fpu/xstate.c | 38 ++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index a9d1dd82d820..03b3de491b5e 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -204,6 +204,14 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave)); } +static inline void fxsave(struct fxregs_state *fx) +{ + if (IS_ENABLED(CONFIG_X86_32)) + asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx)); + else + asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx)); +} + /* These macros all use (%edi)/(%rdi) as the single memory argument. */ #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" @@ -272,28 +280,6 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ : "memory") -/* - * This function is called only during boot time when x86 caps are not set - * up and alternative can not be used yet. - */ -static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) -{ - u64 mask = -1; - u32 lmask = mask; - u32 hmask = mask >> 32; - int err; - - WARN_ON(system_state != SYSTEM_BOOTING); - - if (boot_cpu_has(X86_FEATURE_XSAVES)) - XSTATE_OP(XSAVES, xstate, lmask, hmask, err); - else - XSTATE_OP(XSAVE, xstate, lmask, hmask, err); - - /* We should never fault when copying to a kernel buffer: */ - WARN_ON_FPU(err); -} - /* * This function is called only during boot time when x86 caps are not set * up and alternative can not be used yet. diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 735d1f1bbabc..046782df37a6 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -398,6 +398,24 @@ static void __init print_xstate_offset_size(void) } } +/* + * All supported features have either init state all zeros or are + * handled in setup_init_fpu() individually. This is an explicit + * feature list and does not use XFEATURE_MASK*SUPPORTED to catch + * newly added supported features at build time and make people + * actually look at the init state for the new feature. + */ +#define XFEATURES_INIT_FPSTATE_HANDLED \ + (XFEATURE_MASK_FP | \ + XFEATURE_MASK_SSE | \ + XFEATURE_MASK_YMM | \ + XFEATURE_MASK_OPMASK | \ + XFEATURE_MASK_ZMM_Hi256 | \ + XFEATURE_MASK_Hi16_ZMM | \ + XFEATURE_MASK_PKRU | \ + XFEATURE_MASK_BNDREGS | \ + XFEATURE_MASK_BNDCSR) + /* * setup the xstate image representing the init state */ @@ -405,6 +423,8 @@ static void __init setup_init_fpu_buf(void) { static int on_boot_cpu __initdata = 1; + BUILD_BUG_ON(XCNTXT_MASK != XFEATURES_INIT_FPSTATE_HANDLED); + WARN_ON_FPU(!on_boot_cpu); on_boot_cpu = 0; @@ -423,10 +443,22 @@ static void __init setup_init_fpu_buf(void) copy_kernel_to_xregs_booting(&init_fpstate.xsave); /* - * Dump the init state again. This is to identify the init state - * of any feature which is not represented by all zero's. + * All components are now in init state. Read the state back so + * that init_fpstate contains all non-zero init state. This only + * works with XSAVE, but not with XSAVEOPT and XSAVES because + * those use the init optimization which skips writing data for + * components in init state. + * + * XSAVE could be used, but that would require to reshuffle the + * data when XSAVES is available because XSAVES uses xstate + * compaction. But doing so is a pointless exercise because most + * components have an all zeros init state except for the legacy + * ones (FP and SSE). Those can be saved with FXSAVE into the + * legacy area. Adding new features requires to ensure that init + * state is all zeroes or if not to add the necessary handling + * here. */ - copy_xregs_to_kernel_booting(&init_fpstate.xsave); + fxsave(&init_fpstate.fxsave); } static int xfeature_uncompacted_offset(int xfeature_nr) -- 2.30.2