From nobody Sun Oct 5 00:09:21 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68E652E54D8; Tue, 12 Aug 2025 02:56:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754967395; cv=none; b=Fyo/7uYq/u0ia+r4tUyGydhD5fsNoOmif0tdjEKvUmCT/r8rrMDdwNHW11bfkYThZ1TVmahZuXrUvD0H+tFHhimh8PjVXwsOqvFCnCYT9XWxLS1H7ViRQtB8RO980j8Pzyat+dk5AKzzbxnX03A6erY5f27yC71B6+UwkLKz704= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754967395; c=relaxed/simple; bh=3tFOaFBOSeZjmll7xLj8eingh7ebZS7GcZeBuOUBow0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qtvCcTMtMqk7slfXr1Yf7fYNWtSxkxXqDrNqfSHJ+vU95ViAPlAvI0br5RJyYSYZ8bLiplfIO8TXBZz/OnavsgITxVSWDVghKx0Qib15a+2VTFRqCuqK80WPXh99Gu547u5EkWAXOS1KzYlN5a8QlZ2iKmxZQxS7MEeRFkDcseU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=S/Ih9DoP; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="S/Ih9DoP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1754967393; x=1786503393; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3tFOaFBOSeZjmll7xLj8eingh7ebZS7GcZeBuOUBow0=; b=S/Ih9DoPHkTGBru8LSq2R7u1CbH8ORvZSalINENJKl4l9RQKFIn8Kk/V v4ttGoIJZnYICc4yuDrpYvK5QjFt1cUnpBRIcJ5Tn3+sCI4AvThitDugj 6JFJxPZAIDzTNOseo9xYr+Qfkr5p1eu5UjrQlKVWF2wkGB3HzQ8ARH7JI l5HCTjoMJJXmomVBrYuLCVzW+SKjY8NsEsmlWpjsCuXn+m/ZC2BNt/xSw xUa/NXAjxISKaDSySg84PzPK41NHIUdbBvPsCNIJ2/eJXW6xE4Cr5eiL9 tTEbHipvl59aeeAkNKgH6xSPjDPjpyCxaGJwBzrUK+6iT+6ljrH2VOXDh w==; X-CSE-ConnectionGUID: ODNaG4QgQvC2TF9Wj4B8ng== X-CSE-MsgGUID: n8qbM/dhTr60T/sMYWzfNA== X-IronPort-AV: E=McAfee;i="6800,10657,11518"; a="57100521" X-IronPort-AV: E=Sophos;i="6.17,284,1747724400"; d="scan'208";a="57100521" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Aug 2025 19:56:30 -0700 X-CSE-ConnectionGUID: PGnre2yrQhG8qtaZrzQDhA== X-CSE-MsgGUID: MsVbQP96T/2tIc1FwDWZyQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,284,1747724400"; d="scan'208";a="171321283" Received: from 984fee019967.jf.intel.com ([10.165.54.94]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Aug 2025 19:56:30 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: mlevitsk@redhat.com, rick.p.edgecombe@intel.com, weijiang.yang@intel.com, xin@zytor.com, Sean Christopherson , Mathias Krause , John Allen , Chao Gao , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v12 10/24] KVM: x86: Load guest FPU state when access XSAVE-managed MSRs Date: Mon, 11 Aug 2025 19:55:18 -0700 Message-ID: <20250812025606.74625-11-chao.gao@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250812025606.74625-1-chao.gao@intel.com> References: <20250812025606.74625-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sean Christopherson Load the guest's FPU state if userspace is accessing MSRs whose values are managed by XSAVES. Introduce two helpers, kvm_{get,set}_xstate_msr(), to facilitate access to such kind of MSRs. If MSRs supported in kvm_caps.supported_xss are passed through to guest, the guest MSRs are swapped with host's before vCPU exits to userspace and after it reenters kernel before next VM-entry. Because the modified code is also used for the KVM_GET_MSRS device ioctl(), explicitly check @vcpu is non-null before attempting to load guest state. The XSAVE-managed MSRs cannot be retrieved via the device ioctl() without loading guest FPU state (which doesn't exist). Note that guest_cpuid_has() is not queried as host userspace is allowed to access MSRs that have not been exposed to the guest, e.g. it might do KVM_SET_MSRS prior to KVM_SET_CPUID2. The two helpers are put here in order to manifest accessing xsave-managed MSRs requires special check and handling to guarantee the correctness of read/write to the MSRs. Signed-off-by: Sean Christopherson Co-developed-by: Yang Weijiang Signed-off-by: Yang Weijiang Reviewed-by: Maxim Levitsky Tested-by: Mathias Krause Tested-by: John Allen Signed-off-by: Chao Gao --- arch/x86/kvm/x86.c | 35 ++++++++++++++++++++++++++++++++++- arch/x86/kvm/x86.h | 24 ++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 235a5de66e68..f87974e0682b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -136,6 +136,9 @@ static int __set_sregs2(struct kvm_vcpu *vcpu, struct k= vm_sregs2 *sregs2); static void __get_sregs2(struct kvm_vcpu *vcpu, struct kvm_sregs2 *sregs2); =20 static DEFINE_MUTEX(vendor_module_lock); +static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); +static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); + struct kvm_x86_ops kvm_x86_ops __read_mostly; =20 #define KVM_X86_OP(func) \ @@ -4553,6 +4556,21 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct= msr_data *msr_info) } EXPORT_SYMBOL_GPL(kvm_get_msr_common); =20 +/* + * Returns true if the MSR in question is managed via XSTATE, i.e. is con= text + * switched with the rest of guest FPU state. + */ +static bool is_xstate_managed_msr(u32 index) +{ + switch (index) { + case MSR_IA32_U_CET: + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + return true; + default: + return false; + } +} + /* * Read or write a bunch of msrs. All parameters are kernel addresses. * @@ -4563,11 +4581,26 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct k= vm_msrs *msrs, int (*do_msr)(struct kvm_vcpu *vcpu, unsigned index, u64 *data)) { + bool fpu_loaded =3D false; int i; =20 - for (i =3D 0; i < msrs->nmsrs; ++i) + for (i =3D 0; i < msrs->nmsrs; ++i) { + /* + * If userspace is accessing one or more XSTATE-managed MSRs, + * temporarily load the guest's FPU state so that the guest's + * MSR value(s) is resident in hardware, i.e. so that KVM can + * get/set the MSR via RDMSR/WRMSR. + */ + if (vcpu && !fpu_loaded && kvm_caps.supported_xss && + is_xstate_managed_msr(entries[i].index)) { + kvm_load_guest_fpu(vcpu); + fpu_loaded =3D true; + } if (do_msr(vcpu, entries[i].index, &entries[i].data)) break; + } + if (fpu_loaded) + kvm_put_guest_fpu(vcpu); =20 return i; } diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index bcfd9b719ada..31ce76369cc7 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -699,4 +699,28 @@ int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu, i= nt cpl, =20 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu); =20 +/* + * Lock and/or reload guest FPU and access xstate MSRs. For accesses initi= ated + * by host, guest FPU is loaded in __msr_io(). For accesses initiated by g= uest, + * guest FPU should have been loaded already. + */ + +static inline void kvm_get_xstate_msr(struct kvm_vcpu *vcpu, + struct msr_data *msr_info) +{ + KVM_BUG_ON(!vcpu->arch.guest_fpu.fpstate->in_use, vcpu->kvm); + kvm_fpu_get(); + rdmsrl(msr_info->index, msr_info->data); + kvm_fpu_put(); +} + +static inline void kvm_set_xstate_msr(struct kvm_vcpu *vcpu, + struct msr_data *msr_info) +{ + KVM_BUG_ON(!vcpu->arch.guest_fpu.fpstate->in_use, vcpu->kvm); + kvm_fpu_get(); + wrmsrl(msr_info->index, msr_info->data); + kvm_fpu_put(); +} + #endif --=20 2.47.1