Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp1388192pxb; Thu, 24 Mar 2022 19:30:58 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxW71FO2QBBuejx9iCoVs81pDj6/pZ9ojD4XLoHBYWahys3kDZByKFPSKITUcmAA2nvzqT/ X-Received: by 2002:a17:902:ab08:b0:154:192:40ab with SMTP id ik8-20020a170902ab0800b00154019240abmr9311993plb.80.1648175458198; Thu, 24 Mar 2022 19:30:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648175458; cv=none; d=google.com; s=arc-20160816; b=teL2+HR5SdVwPlxSW1/FtLQh+JgXOIlyp/9p+k43MSP2KGrWd6yy8BOQN9k4pN4yoi grsvAu+ADYgxO8Tpi1z6N7o+veUzhRa8iTKOi56Sh/WvFbObun1f8bhLKOpXAWXH9o4M rDIn5pS2vOJwlsTqhEfWr0j0wKayDy/IgiUTV2uHq22npsJ39LNjd1YuaQzyfN6Pyj21 GJ0XH0eqVsqror9YayLiRVFo/Zk6T740tG94GDEg0WzPq853cH0JBpVwrdsgYI9kzTQy 9wiHngw44/YkF8Wfsjf4SUTyPE5rR+BRzzOmlhBCypOQaYiV6M4feEMmByIr8ORavcjL rsdw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:date:mime-version:references:subject:cc:to:from :dkim-signature:dkim-signature:message-id; bh=2XKntiiVPPNJELg0vo1ejxeBcdE2A4TaubX0naDHtcM=; b=JpvSwuCfyC/4lGQcTYiFPcoh9+6Bh2ISm+H0MdAnPhQN3c4b0C+cbSEvnJ7E1sMrRr vFFpxZNOLTflyvpx/BU7/58Sd3wWp1g3M7Nbqtk3rQ4FSq9eYx3DgFhuGZDkVcFemWTG M5L5i2LNQIbmTHw9YLsC+CA2Y+auJjQZKUlXJCDYLSTkmJLEcSvHMfu8sx/HTlC0gBPx /UQl6W1hXoPIEDeuS2wZ+pQeArMxd9PQP1Cs/ul6LcgdsNextn+RpqBv29gXx55PkZmt J6wBWpRJoOONv6+ZUa3EDosrrK//I995aWs7/3tqabvqS127Rga8UeOroz3TojhQVaLc 7o3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=k1lOsjZ5; dkim=neutral (no key) header.i=@linutronix.de header.b=2qe0JnWf; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b3-20020a63eb43000000b003816043f176si950587pgk.875.2022.03.24.19.30.42; Thu, 24 Mar 2022 19:30:58 -0700 (PDT) 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; dkim=pass header.i=@linutronix.de header.s=2020 header.b=k1lOsjZ5; dkim=neutral (no key) header.i=@linutronix.de header.b=2qe0JnWf; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350650AbiCXNtI (ORCPT + 99 others); Thu, 24 Mar 2022 09:49:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350581AbiCXNsr (ORCPT ); Thu, 24 Mar 2022 09:48:47 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AE9FA94D9 for ; Thu, 24 Mar 2022 06:47:15 -0700 (PDT) Message-ID: <20220324134623.627636809@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1648129633; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=2XKntiiVPPNJELg0vo1ejxeBcdE2A4TaubX0naDHtcM=; b=k1lOsjZ5Vbc8wdLVXOWUDW0faS4+rF0twMNJrE+BJgZojVAwZ5wveH4HJjibRNzatZkHg+ A64IhA2LLtHKNf4o+Y2UTtAUW6rAv0G1cDXfoUZ5/SZVXpbUiEZTPGTQ7idAPFSn4f3H7I di2lZY4V210vsEJJFoEBKuYqyYfiMKyQrsCkZiWohTdWeM1Y3NSz4EV9H5yJ4cUPzSv2rq K24JQ+djdpSddUr1hJ9jWp1x2Fo28CMG2OdLyE+xrfmYWLZ5Qxk8XoefWA+HBr7oQLrLo4 /nLq6sQs0h5Tquw2yfL/56t0lmdYDGJCRzeza0ZSkDGHhAuv+axA0GjFYq+Teg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1648129633; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=2XKntiiVPPNJELg0vo1ejxeBcdE2A4TaubX0naDHtcM=; b=2qe0JnWfgLR6R0eLdNvXqk6aUmNjox+TzF4TGLX4CNdKIZWXTOW/Ggc8sIlAScRnkIW6jf iR7oDWVxyz4Pg4Dw== From: Thomas Gleixner To: LKML Cc: x86@kernel.org, "Chang S. Bae" , Paolo Bonzini , Fenghua Yu , Tony Luck Subject: [patch 5/7] x86/fpu/xsave: Handle compacted offsets correctly with supervisor states References: <20220324134548.432837672@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Date: Thu, 24 Mar 2022 14:47:13 +0100 (CET) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE 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 So far the cached fixed compacted offsets worked, but with (re)enabling of ENQCMD this does not longer work with KVM fpstate. KVM does not have supervisor features enabled for the guest FPU, which means that KVM has then a different XSAVE area layout than the host FPU state. This in turn breaks the copy from/to UABI functions when invoked for a guest state. Remove the precalculated compacted offsets and calculate the offset of each component at runtime based on the XCOMP_BV field in the XSAVE header. The runtime overhead is not interesting because these copy from/to UABI functions are not used in critical fast paths. KVM uses them to save and restore FPU state during migration. The host uses them for ptrace and for the slow path of 32bit signal handling. Fixes: 7c1ef59145f1 ("x86/cpufeatures: Re-enable ENQCMD") Signed-off-by: Thomas Gleixner Cc: Paolo Bonzini Cc: Fenghua Yu Cc: Tony Luck --- arch/x86/kernel/fpu/xstate.c | 86 ++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 45 deletions(-) --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -81,8 +81,6 @@ static unsigned int xstate_offsets[XFEAT { [ 0 ... XFEATURE_MAX - 1] = -1}; static unsigned int xstate_sizes[XFEATURE_MAX] __ro_after_init = { [ 0 ... XFEATURE_MAX - 1] = -1}; -static unsigned int xstate_comp_offsets[XFEATURE_MAX] __ro_after_init = - { [ 0 ... XFEATURE_MAX - 1] = -1}; static unsigned int xstate_flags[XFEATURE_MAX] __ro_after_init; #define XSTATE_FLAG_SUPERVISOR BIT(0) @@ -136,6 +134,33 @@ static bool xfeature_is_supervisor(int x return xstate_flags[xfeature_nr] & XSTATE_FLAG_SUPERVISOR; } +static unsigned int xfeature_get_offset(u64 xcomp_bv, int xfeature) +{ + unsigned int offs, i; + + /* + * Non-compacted format and legacy features use the cached fixed + * offsets. + */ + if (!cpu_feature_enabled(X86_FEATURE_XSAVES) || xfeature <= XFEATURE_SSE) + return xstate_offsets[xfeature]; + + /* + * Compacted format offsets depend on the actual content of the + * compacted xsave area which is determined by the xcomp_bv header + * field. + */ + offs = FXSAVE_SIZE + XSAVE_HDR_SIZE; + for_each_extended_xfeature(i, xcomp_bv) { + if (xfeature_is_aligned64(i)) + offs = ALIGN(offs, 64); + if (i == xfeature) + break; + offs += xstate_sizes[i]; + } + return offs; +} + /* * Enable the extended processor state save/restore feature. * Called once per CPU onlining. @@ -264,42 +289,6 @@ static void __init print_xstate_features } while (0) /* - * This function sets up offsets and sizes of all extended states in - * xsave area. This supports both standard format and compacted format - * of the xsave area. - */ -static void __init setup_xstate_comp_offsets(void) -{ - unsigned int next_offset; - int i; - - /* - * The FP xstates and SSE xstates are legacy states. They are always - * in the fixed offsets in the xsave area in either compacted form - * or standard form. - */ - xstate_comp_offsets[XFEATURE_FP] = 0; - xstate_comp_offsets[XFEATURE_SSE] = offsetof(struct fxregs_state, - xmm_space); - - if (!cpu_feature_enabled(X86_FEATURE_XSAVES)) { - for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) - xstate_comp_offsets[i] = xstate_offsets[i]; - return; - } - - next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE; - - for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) { - if (xfeature_is_aligned64(i)) - next_offset = ALIGN(next_offset, 64); - - xstate_comp_offsets[i] = next_offset; - next_offset += xstate_sizes[i]; - } -} - -/* * Print out xstate component offsets and sizes */ static void __init print_xstate_offset_size(void) @@ -308,7 +297,8 @@ static void __init print_xstate_offset_s for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) { pr_info("x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n", - i, xstate_comp_offsets[i], i, xstate_sizes[i]); + i, xfeature_get_offset(fpu_kernel_cfg.max_features, i), + i, xstate_sizes[i]); } } @@ -901,7 +891,6 @@ void __init fpu__init_system_xstate(unsi fpu_user_cfg.max_features); setup_init_fpu_buf(); - setup_xstate_comp_offsets(); /* * Paranoia check whether something in the setup modified the @@ -956,13 +945,19 @@ void fpu__resume_cpu(void) */ static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr) { - if (!xfeature_enabled(xfeature_nr)) { - WARN_ON_FPU(1); + u64 xcomp_bv = xsave->header.xcomp_bv; + + if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr))) return NULL; + + if (cpu_feature_enabled(X86_FEATURE_XSAVES)) { + if (WARN_ON_ONCE(!(xcomp_bv & BIT_ULL(xfeature_nr)))) + return NULL; } - return (void *)xsave + xstate_comp_offsets[xfeature_nr]; + return (void *)xsave + xfeature_get_offset(xcomp_bv, xfeature_nr); } + /* * Given the xsave area and a state inside, this function returns the * address of the state. @@ -993,8 +988,9 @@ void *get_xsave_addr(struct xregs_state * We should not ever be requesting features that we * have not enabled. */ - WARN_ONCE(!(fpu_kernel_cfg.max_features & BIT_ULL(xfeature_nr)), - "get of unsupported state"); + if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr))) + return NULL; + /* * This assumes the last 'xsave*' instruction to * have requested that 'xfeature_nr' be saved.