From patchwork Mon Apr 29 18:28:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13647501 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7846AC4345F for ; Mon, 29 Apr 2024 18:28:49 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.714344.1115528 (Exim 4.92) (envelope-from ) id 1s1Vjr-0002oU-9l; Mon, 29 Apr 2024 18:28:31 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 714344.1115528; Mon, 29 Apr 2024 18:28:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjr-0002oJ-3M; Mon, 29 Apr 2024 18:28:31 +0000 Received: by outflank-mailman (input) for mailman id 714344; Mon, 29 Apr 2024 18:28:29 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjp-0002kh-HT for xen-devel@lists.xenproject.org; Mon, 29 Apr 2024 18:28:29 +0000 Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [2a00:1450:4864:20::52a]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 4539d4d4-0656-11ef-b4bb-af5377834399; Mon, 29 Apr 2024 20:28:27 +0200 (CEST) Received: by mail-ed1-x52a.google.com with SMTP id 4fb4d7f45d1cf-56e69a51a33so4309468a12.1 for ; Mon, 29 Apr 2024 11:28:27 -0700 (PDT) Received: from andrewcoop.citrite.net (default-46-102-197-194.interdsl.co.uk. [46.102.197.194]) by smtp.gmail.com with ESMTPSA id h25-20020a0564020e9900b0056bc0c44f02sm13241293eda.96.2024.04.29.11.28.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Apr 2024 11:28:26 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4539d4d4-0656-11ef-b4bb-af5377834399 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1714415306; x=1715020106; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=RUdqn8yUPt0MflCFKO44Jy4f931QdjFQX4/EF2ueLbI=; b=ZlJQTcT8Kgcp/GaZvjkHOihS5Iv/MahsITYBuS3gBoOcxJBBSuyThxbgcsN30pLrUN E4LGBbhobTd+bxWWlspiRkVBLM36NeeW2FJsydHCUpRYQ+gPmy/lHorNDiu0e/gYNbWg Tzz/czM9gjUyMNaTTKV7g09GAnt5GNSajXZQA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714415306; x=1715020106; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RUdqn8yUPt0MflCFKO44Jy4f931QdjFQX4/EF2ueLbI=; b=EtYHpifRT27DoK0wa7YNAH8UyrWQEy2ykQffHJEgn/1GapmqsLp6Xm4ClT98EYaJv3 AyqSzzcg8+NmPFBujyX+5qnKLLw6nNGqK80NKInxoaND13V6prINjGoSsON5TVwF+lpL tMP1d14l9jlhpwce4jg/tHQE4G4Q+G0sGC+TnmELzQQ8Z1WYr3tC2YfbGmylJ/Dme1eY A5j/reSaD8qEEz6OAAk+xOVBnEg2cuuelSmgiHT0Q5sQdz6yppRlyMcmYg913oihf4Ue QOnxJRcPCNTA5eRI8ceng/ity/YP53QXDnboWtaRD1c/OOV/e+eXBcMGzM37TFuTa9q2 uIvg== X-Gm-Message-State: AOJu0YztKPIoxHDfLg0B1fmYw4vzABLJRD3/3NCSrySnNef4v1HOUCUJ sy9jETHtF6lXKRKM/E59tzXPLSjKO+kItfCSM/ZsQ6sI5HYWUw9AlJ87kbzT+KfOSJiUJzJBBBs M X-Google-Smtp-Source: AGHT+IHXBawz6JpDRHazp+O1fHnxg6joyWlQlXd46cii/bn/mOjqqALSQkG6sVyPZRnPl/V1xOEuZQ== X-Received: by 2002:a50:875e:0:b0:56b:cfef:b2de with SMTP id 30-20020a50875e000000b0056bcfefb2demr7789583edv.26.1714415306494; Mon, 29 Apr 2024 11:28:26 -0700 (PDT) From: Andrew Cooper To: Xen-devel Cc: Andrew Cooper , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v2 1/4] x86/hvm: Defer the size calculation in hvm_save_cpu_xsave_states() Date: Mon, 29 Apr 2024 19:28:20 +0100 Message-Id: <20240429182823.1130436-2-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240429182823.1130436-1-andrew.cooper3@citrix.com> References: <20240429182823.1130436-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 HVM_CPU_XSAVE_SIZE() may rewrite %xcr0 twice. Defer the caluclation it until after we've decided to write out an XSAVE record. Note in hvm_load_cpu_xsave_states() that there were versions of Xen which wrote out a useless XSAVE record. This sadly limits out ability to tidy up the existing infrastructure. Also leave a note in xstate_ctxt_size() that 0 still needs tolerating for now. No functional change. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Roger Pau Monné v2: * New --- xen/arch/x86/hvm/hvm.c | 10 ++++++++-- xen/arch/x86/xstate.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 0ce45b177cf4..9594e0a5c530 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1197,12 +1197,13 @@ static int cf_check hvm_save_cpu_xsave_states( struct vcpu *v, hvm_domain_context_t *h) { struct hvm_hw_cpu_xsave *ctxt; - unsigned int size = HVM_CPU_XSAVE_SIZE(v->arch.xcr0_accum); + unsigned int size; int err; - if ( !cpu_has_xsave || !xsave_enabled(v) ) + if ( !xsave_enabled(v) ) return 0; /* do nothing */ + size = HVM_CPU_XSAVE_SIZE(v->arch.xcr0_accum); err = _hvm_init_entry(h, CPU_XSAVE_CODE, v->vcpu_id, size); if ( err ) return err; @@ -1255,6 +1256,11 @@ static int cf_check hvm_load_cpu_xsave_states( if ( !cpu_has_xsave ) return -EOPNOTSUPP; + /* + * Note: Xen prior to 4.12 would write out empty XSAVE records for VMs + * running on XSAVE-capable hardware but without XSAVE active. + */ + /* Customized checking for entry since our entry is of variable length */ desc = (struct hvm_save_descriptor *)&h->data[h->cur]; if ( sizeof (*desc) > h->size - h->cur) diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index cf94761d0542..99cedb4f5e24 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -573,7 +573,7 @@ unsigned int xstate_ctxt_size(u64 xcr0) if ( xcr0 == xfeature_mask ) return xsave_cntxt_size; - if ( xcr0 == 0 ) + if ( xcr0 == 0 ) /* TODO: clean up paths passing 0 in here. */ return 0; return hw_uncompressed_size(xcr0); From patchwork Mon Apr 29 18:28:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13647502 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1211AC04FFE for ; Mon, 29 Apr 2024 18:28:50 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.714346.1115543 (Exim 4.92) (envelope-from ) id 1s1Vjs-00037e-3n; Mon, 29 Apr 2024 18:28:32 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 714346.1115543; Mon, 29 Apr 2024 18:28:32 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjr-00035K-TQ; Mon, 29 Apr 2024 18:28:31 +0000 Received: by outflank-mailman (input) for mailman id 714346; Mon, 29 Apr 2024 18:28:30 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjq-0002kh-Hl for xen-devel@lists.xenproject.org; Mon, 29 Apr 2024 18:28:30 +0000 Received: from mail-ed1-x531.google.com (mail-ed1-x531.google.com [2a00:1450:4864:20::531]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 45eade52-0656-11ef-b4bb-af5377834399; Mon, 29 Apr 2024 20:28:28 +0200 (CEST) Received: by mail-ed1-x531.google.com with SMTP id 4fb4d7f45d1cf-56e56ee8d5cso6061257a12.2 for ; Mon, 29 Apr 2024 11:28:28 -0700 (PDT) Received: from andrewcoop.citrite.net (default-46-102-197-194.interdsl.co.uk. [46.102.197.194]) by smtp.gmail.com with ESMTPSA id h25-20020a0564020e9900b0056bc0c44f02sm13241293eda.96.2024.04.29.11.28.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Apr 2024 11:28:26 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 45eade52-0656-11ef-b4bb-af5377834399 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1714415307; x=1715020107; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pC3Swr6XvpWJc3cdnmHIIik9FCKy/gZ4FBg4Litx/6I=; b=uiaIVB0BC34ET6Y0nwIPwLy3HEMD7gdXxXeVW+P0SnpjrMX1ckviqrUtVVCbyzpUtk u6dPDoX9WXEX2LLY2NQoicy21LL6w22mAT/YZFKA2Wa4Cfx9bdPYknSe0yR4Zza3vVzm ZAJyikqW61R/xKpwyiMLByfZQO4w2iiTamChU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714415307; x=1715020107; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pC3Swr6XvpWJc3cdnmHIIik9FCKy/gZ4FBg4Litx/6I=; b=M+fACG5NNben4XY0lKSBYRaH8+6UpBDuikMrzC86XlqMT1l6LfQAMI6B0XJ5oiBk0B ZzCLGaJoPzFSpEalJXn8MJBukNzn1EJw8aCSg9Yw9YYcbuROpbh2T85AZ6/wNh0emh6A LnL0vOh4E8ujOU6ZeH6nQ+IWw/No0n6AKhamqmUBuW3DPQSTArxtqcqDcQB2ovJiHvCQ OkkbsR9Jhy+yt+93/rG/RErdo/VurK03b3jKyTxxTCx1yfJm3nNkySbXSPGDP4SWOukd ySe7tFGZ1z31xrqhXU7NUqdTN+bVbog9emwD9N8P20zqwU/7kF8UhOJCI62VuytZG7zn 4BHA== X-Gm-Message-State: AOJu0YxOBQzfK7v6nbVhkC9GbSOnCOmiJk51cs/G6f3cQUm4eET0TIwm IRsjYQK6UrIMyk9tk8M+J+K4cQtqvPcBucWMFT4S2lYvKRBiFSvLAR1vmwAlLl20zCzHTGqLybM 1 X-Google-Smtp-Source: AGHT+IEuaaNH5iGXpIJ1LxyYqhTrmlO2SaeQ6GksKFcQS8LcQ8lirD9hlUU5/aZut0n/dAHKAgjMhg== X-Received: by 2002:a50:d54b:0:b0:568:d55c:1bb3 with SMTP id f11-20020a50d54b000000b00568d55c1bb3mr9244494edj.31.1714415307298; Mon, 29 Apr 2024 11:28:27 -0700 (PDT) From: Andrew Cooper To: Xen-devel Cc: Andrew Cooper , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v2 2/4] x86/xstate: Rework xstate_ctxt_size() as xstate_uncompressed_size() Date: Mon, 29 Apr 2024 19:28:21 +0100 Message-Id: <20240429182823.1130436-3-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240429182823.1130436-1-andrew.cooper3@citrix.com> References: <20240429182823.1130436-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 We're soon going to need a compressed helper of the same form. The size of the uncompressed image depends on the single element with the largest offset+size. Sadly this isn't always the element with the largest index. Retain the cross-check with hardware in debug builds, but forgo it normal builds. In particular, this means that the migration paths don't need to mess with XCR0 just to sanity check the buffer size. No practical change. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Roger Pau Monné v2: * Scan all features. LWP/APX_F are out-of-order. --- xen/arch/x86/domctl.c | 2 +- xen/arch/x86/hvm/hvm.c | 2 +- xen/arch/x86/include/asm/xstate.h | 2 +- xen/arch/x86/xstate.c | 45 +++++++++++++++++++++++++++---- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 9a72d57333e9..c2f2016ed45a 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -833,7 +833,7 @@ long arch_do_domctl( uint32_t offset = 0; #define PV_XSAVE_HDR_SIZE (2 * sizeof(uint64_t)) -#define PV_XSAVE_SIZE(xcr0) (PV_XSAVE_HDR_SIZE + xstate_ctxt_size(xcr0)) +#define PV_XSAVE_SIZE(xcr0) (PV_XSAVE_HDR_SIZE + xstate_uncompressed_size(xcr0)) ret = -ESRCH; if ( (evc->vcpu >= d->max_vcpus) || diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 9594e0a5c530..9e677d891d6c 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1191,7 +1191,7 @@ HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, NULL, hvm_load_cpu_ctxt, 1, #define HVM_CPU_XSAVE_SIZE(xcr0) (offsetof(struct hvm_hw_cpu_xsave, \ save_area) + \ - xstate_ctxt_size(xcr0)) + xstate_uncompressed_size(xcr0)) static int cf_check hvm_save_cpu_xsave_states( struct vcpu *v, hvm_domain_context_t *h) diff --git a/xen/arch/x86/include/asm/xstate.h b/xen/arch/x86/include/asm/xstate.h index c08c267884f0..f5115199d4f9 100644 --- a/xen/arch/x86/include/asm/xstate.h +++ b/xen/arch/x86/include/asm/xstate.h @@ -107,7 +107,7 @@ void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size); void xstate_free_save_area(struct vcpu *v); int xstate_alloc_save_area(struct vcpu *v); void xstate_init(struct cpuinfo_x86 *c); -unsigned int xstate_ctxt_size(u64 xcr0); +unsigned int xstate_uncompressed_size(uint64_t xcr0); static inline uint64_t xgetbv(unsigned int index) { diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index 99cedb4f5e24..a94f4025fce5 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -183,7 +183,7 @@ void expand_xsave_states(const struct vcpu *v, void *dest, unsigned int size) /* Check there is state to serialise (i.e. at least an XSAVE_HDR) */ BUG_ON(!v->arch.xcr0_accum); /* Check there is the correct room to decompress into. */ - BUG_ON(size != xstate_ctxt_size(v->arch.xcr0_accum)); + BUG_ON(size != xstate_uncompressed_size(v->arch.xcr0_accum)); if ( !(xstate->xsave_hdr.xcomp_bv & XSTATE_COMPACTION_ENABLED) ) { @@ -245,7 +245,7 @@ void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size) u64 xstate_bv, valid; BUG_ON(!v->arch.xcr0_accum); - BUG_ON(size != xstate_ctxt_size(v->arch.xcr0_accum)); + BUG_ON(size != xstate_uncompressed_size(v->arch.xcr0_accum)); ASSERT(!xsave_area_compressed(src)); xstate_bv = ((const struct xsave_struct *)src)->xsave_hdr.xstate_bv; @@ -567,16 +567,51 @@ static unsigned int hw_uncompressed_size(uint64_t xcr0) return size; } -/* Fastpath for common xstate size requests, avoiding reloads of xcr0. */ -unsigned int xstate_ctxt_size(u64 xcr0) +unsigned int xstate_uncompressed_size(uint64_t xcr0) { + unsigned int size = XSTATE_AREA_MIN_SIZE, i; + if ( xcr0 == xfeature_mask ) return xsave_cntxt_size; if ( xcr0 == 0 ) /* TODO: clean up paths passing 0 in here. */ return 0; - return hw_uncompressed_size(xcr0); + if ( xcr0 <= (X86_XCR0_SSE | X86_XCR0_FP) ) + return size; + + /* + * For the non-legacy states, search all activate states and find the + * maximum offset+size. Some states (e.g. LWP, APX_F) are out-of-order + * with respect their index. + */ + xcr0 &= ~XSTATE_FP_SSE; + for_each_set_bit ( i, &xcr0, 63 ) + { + unsigned int s; + + ASSERT(xstate_offsets[i] && xstate_sizes[i]); + + s = xstate_offsets[i] && xstate_sizes[i]; + + size = max(size, s); + } + + /* In debug builds, cross-check our calculation with hardware. */ + if ( IS_ENABLED(CONFIG_DEBUG) ) + { + unsigned int hwsize; + + xcr0 |= XSTATE_FP_SSE; + hwsize = hw_uncompressed_size(xcr0); + + if ( size != hwsize ) + printk_once(XENLOG_ERR "%s(%#"PRIx64") size %#x != hwsize %#x\n", + __func__, xcr0, size, hwsize); + size = hwsize; + } + + return size; } static bool valid_xcr0(uint64_t xcr0) From patchwork Mon Apr 29 18:28:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13647504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C4D7FC19F53 for ; Mon, 29 Apr 2024 18:28:50 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.714347.1115548 (Exim 4.92) (envelope-from ) id 1s1Vjs-0003FG-BX; Mon, 29 Apr 2024 18:28:32 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 714347.1115548; Mon, 29 Apr 2024 18:28:32 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjs-0003DE-7X; Mon, 29 Apr 2024 18:28:32 +0000 Received: by outflank-mailman (input) for mailman id 714347; Mon, 29 Apr 2024 18:28:31 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjr-0002ks-2r for xen-devel@lists.xenproject.org; Mon, 29 Apr 2024 18:28:31 +0000 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [2a00:1450:4864:20::532]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 46403e34-0656-11ef-909b-e314d9c70b13; Mon, 29 Apr 2024 20:28:29 +0200 (CEST) Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-5727dc6d3edso1811922a12.0 for ; Mon, 29 Apr 2024 11:28:29 -0700 (PDT) Received: from andrewcoop.citrite.net (default-46-102-197-194.interdsl.co.uk. [46.102.197.194]) by smtp.gmail.com with ESMTPSA id h25-20020a0564020e9900b0056bc0c44f02sm13241293eda.96.2024.04.29.11.28.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Apr 2024 11:28:27 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 46403e34-0656-11ef-909b-e314d9c70b13 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1714415308; x=1715020108; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ADttxadCLt/zjGm7XTarV6R8WGqoXwrChWdb25bmPX8=; b=vWTWydZ/c2lq5JBF8AASOtai1+1TKuqbvdtbSniZ0AKmrIV32ozu4oLXXHuaW+mHnT MGYYQ9CzDMJpe7XvJeF4EImC+X5e4/boA1vVfMWAChHHSyGzb7pJCFBu3jXjV38DvqrV ztQT3pZKcTSqRaZKXD3fM9aglyfn/OQ69LIAE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714415308; x=1715020108; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ADttxadCLt/zjGm7XTarV6R8WGqoXwrChWdb25bmPX8=; b=Uxwp4wMmG8N1Hxl8X9czCD3WfnafoOuaYDNabQA5udF3acFo3nSusv/ecd1tBXM5HW VIqjnBent05mUGRwLgLlhVQsceZ/NJQbfiVZWQg5+nuc4tTU6n7clsEp48Bp9xehpdDD RXT1yomwd0udb89r04SsuRcFmNzpG4C25Xst45ugkxjmylmNRie46gBVVAUVVPxqsEwk 8P93n9GSitoBfk9Ob3TctGKgUxO5RQwp+9w3QYLxkawLkMJEA65PtX3Uwd/hXulfZQKw 0h0Ss33zTRvITTB4CmwCp8+K8Uq3WRJgAEt/Tfjcf70vhFcta9mORo66Cc46IT+UMaph BLgg== X-Gm-Message-State: AOJu0YwI/qrC/ZeUYGwModn8FPGeCdi3w7CivwCBhWoVTLMzEGypSI2A qR7lyRh5WNlgOjyXtp6E/ivKuB+TRiwxFNM/W1S5DqUJSExOe2GP8r9v4ymIGsG27Z+/2SCwPP8 j X-Google-Smtp-Source: AGHT+IFbObEyCM4M9hc8uz2/lK+eLhxDUzZ7f8HmBGaZaWbDO4IJ5dD4x0jTniAkFNSf4VaOx7ZdDQ== X-Received: by 2002:a50:bac6:0:b0:570:5e7f:62cb with SMTP id x64-20020a50bac6000000b005705e7f62cbmr294949ede.29.1714415307936; Mon, 29 Apr 2024 11:28:27 -0700 (PDT) From: Andrew Cooper To: Xen-devel Cc: Andrew Cooper , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v2 3/4] x86/cpu-policy: Simplify recalculate_xstate() Date: Mon, 29 Apr 2024 19:28:22 +0100 Message-Id: <20240429182823.1130436-4-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240429182823.1130436-1-andrew.cooper3@citrix.com> References: <20240429182823.1130436-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Make use of the new xstate_uncompressed_size() helper rather than maintaining the running calculation while accumulating feature components. The rest of the CPUID data can come direct from the raw cpu policy. All per-component data form an ABI through the behaviour of the X{SAVE,RSTOR}* instructions. Use for_each_set_bit() rather than opencoding a slightly awkward version of it. Mask the attributes in ecx down based on the visible features. This isn't actually necessary for any components or attributes defined at the time of writing (up to AMX), but is added out of an abundance of caution. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Roger Pau Monné v2: * Tie ALIGN64 to xsavec rather than xsaves. --- xen/arch/x86/cpu-policy.c | 55 +++++++++++-------------------- xen/arch/x86/include/asm/xstate.h | 1 + 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/xen/arch/x86/cpu-policy.c b/xen/arch/x86/cpu-policy.c index 4b6d96276399..fc7933be8577 100644 --- a/xen/arch/x86/cpu-policy.c +++ b/xen/arch/x86/cpu-policy.c @@ -193,8 +193,7 @@ static void sanitise_featureset(uint32_t *fs) static void recalculate_xstate(struct cpu_policy *p) { uint64_t xstates = XSTATE_FP_SSE; - uint32_t xstate_size = XSTATE_AREA_MIN_SIZE; - unsigned int i, Da1 = p->xstate.Da1; + unsigned int i, ecx_mask = 0, Da1 = p->xstate.Da1; /* * The Da1 leaf is the only piece of information preserved in the common @@ -206,61 +205,47 @@ static void recalculate_xstate(struct cpu_policy *p) return; if ( p->basic.avx ) - { xstates |= X86_XCR0_YMM; - xstate_size = max(xstate_size, - xstate_offsets[X86_XCR0_YMM_POS] + - xstate_sizes[X86_XCR0_YMM_POS]); - } if ( p->feat.mpx ) - { xstates |= X86_XCR0_BNDREGS | X86_XCR0_BNDCSR; - xstate_size = max(xstate_size, - xstate_offsets[X86_XCR0_BNDCSR_POS] + - xstate_sizes[X86_XCR0_BNDCSR_POS]); - } if ( p->feat.avx512f ) - { xstates |= X86_XCR0_OPMASK | X86_XCR0_ZMM | X86_XCR0_HI_ZMM; - xstate_size = max(xstate_size, - xstate_offsets[X86_XCR0_HI_ZMM_POS] + - xstate_sizes[X86_XCR0_HI_ZMM_POS]); - } if ( p->feat.pku ) - { xstates |= X86_XCR0_PKRU; - xstate_size = max(xstate_size, - xstate_offsets[X86_XCR0_PKRU_POS] + - xstate_sizes[X86_XCR0_PKRU_POS]); - } - p->xstate.max_size = xstate_size; + /* Subleaf 0 */ + p->xstate.max_size = + xstate_uncompressed_size(xstates & ~XSTATE_XSAVES_ONLY); p->xstate.xcr0_low = xstates & ~XSTATE_XSAVES_ONLY; p->xstate.xcr0_high = (xstates & ~XSTATE_XSAVES_ONLY) >> 32; + /* Subleaf 1 */ p->xstate.Da1 = Da1; + if ( p->xstate.xsavec ) + ecx_mask |= XSTATE_ALIGN64; + if ( p->xstate.xsaves ) { + ecx_mask |= XSTATE_XSS; p->xstate.xss_low = xstates & XSTATE_XSAVES_ONLY; p->xstate.xss_high = (xstates & XSTATE_XSAVES_ONLY) >> 32; } - else - xstates &= ~XSTATE_XSAVES_ONLY; - for ( i = 2; i < min(63UL, ARRAY_SIZE(p->xstate.comp)); ++i ) + /* Subleafs 2+ */ + xstates &= ~XSTATE_FP_SSE; + BUILD_BUG_ON(ARRAY_SIZE(p->xstate.comp) < 63); + for_each_set_bit ( i, &xstates, 63 ) { - uint64_t curr_xstate = 1UL << i; - - if ( !(xstates & curr_xstate) ) - continue; - - p->xstate.comp[i].size = xstate_sizes[i]; - p->xstate.comp[i].offset = xstate_offsets[i]; - p->xstate.comp[i].xss = curr_xstate & XSTATE_XSAVES_ONLY; - p->xstate.comp[i].align = curr_xstate & xstate_align; + /* + * Pass through size (eax) and offset (ebx) directly. Visbility of + * attributes in ecx limited by visible features in Da1. + */ + p->xstate.raw[i].a = raw_cpu_policy.xstate.raw[i].a; + p->xstate.raw[i].b = raw_cpu_policy.xstate.raw[i].b; + p->xstate.raw[i].c = raw_cpu_policy.xstate.raw[i].c & ecx_mask; } } diff --git a/xen/arch/x86/include/asm/xstate.h b/xen/arch/x86/include/asm/xstate.h index f5115199d4f9..bfb66dd766b6 100644 --- a/xen/arch/x86/include/asm/xstate.h +++ b/xen/arch/x86/include/asm/xstate.h @@ -40,6 +40,7 @@ extern uint32_t mxcsr_mask; #define XSTATE_XSAVES_ONLY 0 #define XSTATE_COMPACTION_ENABLED (1ULL << 63) +#define XSTATE_XSS (1U << 0) #define XSTATE_ALIGN64 (1U << 1) extern u64 xfeature_mask; From patchwork Mon Apr 29 18:28:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 13647505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 29052C25B5C for ; Mon, 29 Apr 2024 18:28:51 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.714345.1115535 (Exim 4.92) (envelope-from ) id 1s1Vjr-00030K-NB; Mon, 29 Apr 2024 18:28:31 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 714345.1115535; Mon, 29 Apr 2024 18:28:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjr-0002xz-K4; Mon, 29 Apr 2024 18:28:31 +0000 Received: by outflank-mailman (input) for mailman id 714345; Mon, 29 Apr 2024 18:28:30 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1s1Vjq-0002ks-Dr for xen-devel@lists.xenproject.org; Mon, 29 Apr 2024 18:28:30 +0000 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [2a00:1450:4864:20::536]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4665ca60-0656-11ef-909b-e314d9c70b13; Mon, 29 Apr 2024 20:28:29 +0200 (CEST) Received: by mail-ed1-x536.google.com with SMTP id 4fb4d7f45d1cf-57258c90899so5727413a12.1 for ; Mon, 29 Apr 2024 11:28:29 -0700 (PDT) Received: from andrewcoop.citrite.net (default-46-102-197-194.interdsl.co.uk. [46.102.197.194]) by smtp.gmail.com with ESMTPSA id h25-20020a0564020e9900b0056bc0c44f02sm13241293eda.96.2024.04.29.11.28.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Apr 2024 11:28:28 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4665ca60-0656-11ef-909b-e314d9c70b13 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1714415308; x=1715020108; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iyIIuM0MTD0m2fODC0sTW6s/htaUI9+d26Ij/6rc7Jc=; b=YPjuwI4nXCYgOzBAg+JvIXncGSiwH1bl9AObD1qG7sRZj1SHeTxIJ7fbzRb5pEed9m XRYIE5uSaJ7xA4j68jeEdPxZVcacistQurw6I+IxofCp+SDbDW8sDFRoh6UwayMAea/9 Dp+uTrysI7sVBpfSVVyJcvQeZTQbCpHHGwuYk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714415308; x=1715020108; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iyIIuM0MTD0m2fODC0sTW6s/htaUI9+d26Ij/6rc7Jc=; b=UioCzmi5v15vbnD+oG7ZfnP4WQ8gfbOBc4pZRHtOMi53ffMeNvOoMpjUqCpBSFgr3j ZyP/qo32J85o2bx+Sy8kPl6O4PJnNhz9rZeE1mpK11DBcegAg8xDHySVOrXHlmUgrvB2 CSDacisvQO1eQCARAd4qK9N4AIQWaUCBljtjw05wTMykhO4rC5dbaIGG/TBrLa7/Ck9r 3av0SpXx1XuxvElvQB1aAVhVQAEXY0jwVMivZElRKMqfC84hmEtHWw/6dhfHP6QJ22E1 82vXejUs2gU1p3LgzIEBsxybJ1DCUJsb46d6OD/bldTYvGT19RrT2qd8gNnQPz93kTFA OFBg== X-Gm-Message-State: AOJu0Yw0TecCjeM99hrzLyqZJ0sl4PfkcPN6gUHfH4NkbMczUwKlMk0u dF6ttljMYRwA5sIKRadyr/KcVRf4jn6pzJm55dskHFew91QMe+siqFiAJRHESzN+JkJV1wEl9Z5 O X-Google-Smtp-Source: AGHT+IGBH906trFMksi2dFbsLtezstfc77WQj3FYL1DAKBHkBY4+QnPCA0N4pBG/uAeGvfetV+SqAw== X-Received: by 2002:a50:d7dd:0:b0:572:67de:5fd2 with SMTP id m29-20020a50d7dd000000b0057267de5fd2mr531977edj.0.1714415308473; Mon, 29 Apr 2024 11:28:28 -0700 (PDT) From: Andrew Cooper To: Xen-devel Cc: Andrew Cooper , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v2 4/4] x86/cpuid: Fix handling of xsave dynamic leaves Date: Mon, 29 Apr 2024 19:28:23 +0100 Message-Id: <20240429182823.1130436-5-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240429182823.1130436-1-andrew.cooper3@citrix.com> References: <20240429182823.1130436-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 If max leaf is greater than 0xd but xsave not available to the guest, then the current XSAVE size should not be filled in. This is a latent bug for now as the guest max leaf is 0xd, but will become problematic in the future. The comment concerning XSS state is wrong. VT-x doesn't manage host/guest state automatically, but there is provision for "host only" bits to be set, so the implications are still accurate. Introduce {xstate,hw}_compressed_size() helpers to mirror the uncompressed ones. This in turn higlights a bug in xstate_init(). Defaulting this_cpu(xss) to ~0 requires a forced write to clear it back out. This in turn highlights that it's only a safe default on systems with XSAVES. Signed-off-by: Andrew Cooper --- CC: Jan Beulich CC: Roger Pau Monné The more I think about it, the more I think that cross-checking with hardware is a bad move. It's horribly expensive, and for supervisor states in particular, liable to interfere with functionality. v2: * Cope with blind reads of CPUID.0xD[1] prior to %xcr0 having been set up. --- xen/arch/x86/cpuid.c | 24 ++++-------- xen/arch/x86/include/asm/xstate.h | 1 + xen/arch/x86/xstate.c | 64 ++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index 7a38e032146a..a822e80c7ea7 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -330,23 +330,15 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, case XSTATE_CPUID: switch ( subleaf ) { - case 1: - if ( !p->xstate.xsavec && !p->xstate.xsaves ) - break; - - /* - * TODO: Figure out what to do for XSS state. VT-x manages host - * vs guest MSR_XSS automatically, so as soon as we start - * supporting any XSS states, the wrong XSS will be in context. - */ - BUILD_BUG_ON(XSTATE_XSAVES_ONLY != 0); - fallthrough; case 0: - /* - * Read CPUID[0xD,0/1].EBX from hardware. They vary with enabled - * XSTATE, and appropriate XCR0|XSS are in context. - */ - res->b = cpuid_count_ebx(leaf, subleaf); + if ( p->basic.xsave ) + res->b = xstate_uncompressed_size(v->arch.xcr0); + break; + + case 1: + if ( p->xstate.xsavec ) + res->b = xstate_compressed_size(v->arch.xcr0 | + v->arch.msrs->xss.raw); break; } break; diff --git a/xen/arch/x86/include/asm/xstate.h b/xen/arch/x86/include/asm/xstate.h index bfb66dd766b6..da1d89d2f416 100644 --- a/xen/arch/x86/include/asm/xstate.h +++ b/xen/arch/x86/include/asm/xstate.h @@ -109,6 +109,7 @@ void xstate_free_save_area(struct vcpu *v); int xstate_alloc_save_area(struct vcpu *v); void xstate_init(struct cpuinfo_x86 *c); unsigned int xstate_uncompressed_size(uint64_t xcr0); +unsigned int xstate_compressed_size(uint64_t xstates); static inline uint64_t xgetbv(unsigned int index) { diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index a94f4025fce5..b2cf3ae6acee 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -614,6 +614,65 @@ unsigned int xstate_uncompressed_size(uint64_t xcr0) return size; } +static unsigned int hw_compressed_size(uint64_t xstates) +{ + uint64_t curr_xcr0 = get_xcr0(), curr_xss = get_msr_xss(); + unsigned int size; + bool ok; + + ok = set_xcr0(xstates & ~XSTATE_XSAVES_ONLY); + ASSERT(ok); + set_msr_xss(xstates & XSTATE_XSAVES_ONLY); + + size = cpuid_count_ebx(XSTATE_CPUID, 1); + + ok = set_xcr0(curr_xcr0); + ASSERT(ok); + set_msr_xss(curr_xss); + + return size; +} + +unsigned int xstate_compressed_size(uint64_t xstates) +{ + unsigned int i, size = XSTATE_AREA_MIN_SIZE; + + if ( xstates == 0 ) /* TODO: clean up paths passing 0 in here. */ + return 0; + + if ( xstates <= (X86_XCR0_SSE | X86_XCR0_FP) ) + return size; + + /* + * For the compressed size, every component matters. Some are + * automatically rounded up to 64 first. + */ + xstates &= ~XSTATE_FP_SSE; + for_each_set_bit ( i, &xstates, 63 ) + { + if ( test_bit(i, &xstate_align) ) + size = ROUNDUP(size, 64); + + size += xstate_sizes[i]; + } + + /* In debug builds, cross-check our calculation with hardware. */ + if ( IS_ENABLED(CONFIG_DEBUG) ) + { + unsigned int hwsize; + + xstates |= XSTATE_FP_SSE; + hwsize = hw_compressed_size(xstates); + + if ( size != hwsize ) + printk_once(XENLOG_ERR "%s(%#"PRIx64") size %#x != hwsize %#x\n", + __func__, xstates, size, hwsize); + size = hwsize; + } + + return size; +} + static bool valid_xcr0(uint64_t xcr0) { /* FP must be unconditionally set. */ @@ -681,7 +740,8 @@ void xstate_init(struct cpuinfo_x86 *c) * write it. */ this_cpu(xcr0) = 0; - this_cpu(xss) = ~0; + if ( cpu_has_xsaves ) + this_cpu(xss) = ~0; cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx); feature_mask = (((u64)edx << 32) | eax) & XCNTXT_MASK; @@ -694,6 +754,8 @@ void xstate_init(struct cpuinfo_x86 *c) set_in_cr4(X86_CR4_OSXSAVE); if ( !set_xcr0(feature_mask) ) BUG(); + if ( cpu_has_xsaves ) + set_msr_xss(0); if ( bsp ) {