Received: by 2002:a05:6359:6284:b0:131:369:b2a3 with SMTP id se4csp195496rwb; Fri, 4 Aug 2023 11:08:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGvpQ+OGr1rMDLsqxRArmFJOnrqkCphuqUF6xEXUNRY9QiyjmGxiyCitlEFKA78IcgZtJma X-Received: by 2002:a05:6870:6491:b0:1b3:dfb4:6431 with SMTP id cz17-20020a056870649100b001b3dfb46431mr2814879oab.8.1691172527813; Fri, 04 Aug 2023 11:08:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691172527; cv=none; d=google.com; s=arc-20160816; b=BPkYGrTydPW1sbYpBKZvFghV2uKMsS1HYvSQBwbCY1R6nY859xqk71Bxa2kMuNt0nQ UnxKq77NQoalxY/sBvxuJTOQEtzG4hhd9B5wpW+l5zfEkVCUqP4Ogpp8gbrX1U+gc/pF Wk+3SFz1LRGMjwP8bTQEGyZ8MQpZN09WzOWLl8zvXFuIUsxs8fd7d9PC1AVchKbdGcdQ g9BL/Y9QmBm6K7aA08n/Z3nkWjoO4I8NXRBoDecmKlpwaSoRRGSt628whrgQQ0FiK8v4 tTzcjnX/LR5/FgdZjW4njlMIQ6kxpml0af1/YlQcFDBcDFMNwAR+MW3A7dTO7Mr0pF3S Yx1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=aR8D0fIoPoIFpwFxu77XAzwqicqZyfbYQ6tlR8sCTLM=; fh=g9qa1g9usllrcyVDf2W3cgvSV4VG7s4cMo+mIKOgDQc=; b=js0DkyFBnxPv1K6mb6ek8PXWBdLL9Tzl8fyOaGOt4PhVgRr12/sw8LB3r8yD1mBMYm VuIy/nfPsU7fxmnUwFZUUr3Gp9jmUsxl86hwHKhXT/36Adohv41WpVfV/c7SUr84yr09 CK83zcJAvmH556IgCcsQLlkDsnVqdeHqVGLZmHWRY0tVGNI+LzxLubHE1wiM9P1IA2am N9x9FSE8lhZgxmHz/uTsn4ZV39Lq9IMN4GDvUJG4Ep2lAmBNDmRPp2yZL+2CM9klbbvj 9xPt2NdZlyk33CqhKonWRa3lgoKQXZL4B8vKQOs0HPAwFa7IW7Bl+ESIlu/qsX+4S+le qAEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=VB2vjCRj; 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=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v21-20020a17090abb9500b0026925bf4059si1431283pjr.106.2023.08.04.11.08.34; Fri, 04 Aug 2023 11:08:47 -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=@google.com header.s=20221208 header.b=VB2vjCRj; 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=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231660AbjHDP0U (ORCPT + 99 others); Fri, 4 Aug 2023 11:26:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231651AbjHDP0B (ORCPT ); Fri, 4 Aug 2023 11:26:01 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AFA2F4C34 for ; Fri, 4 Aug 2023 08:25:28 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-d13e11bb9ecso2457615276.0 for ; Fri, 04 Aug 2023 08:25:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691162727; x=1691767527; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=aR8D0fIoPoIFpwFxu77XAzwqicqZyfbYQ6tlR8sCTLM=; b=VB2vjCRjKu/M8EILnB2LknxCC3MRsvscHBiYxjGCZfU4CXGZs/aun9ZkDGLItrffno u/4xyaKIFT4iOE7WkNhsj+pHWZxCL0eTiWVNzV5IY2reU54oSXMtoDoI0Vpw8kv81s2H +vVmcdMXl2uMTLm/JPrNiX0NFBebcCVcssywEYeaOzEbpNa8u6T865k2ya4BnuOKTZ4g DcsovjcVAHPveM5Y7YitDoe97lPI8Yns/imCGOwmke5hxTTJBhtxyqfh42faTsci7IUS 2YSVmxC22m3O9UBfoDDFllJBv6ik9KUtqryWjNFIKgXVMAL0RGdjuuvDoUD3BcT8cd8S N6Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691162727; x=1691767527; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=aR8D0fIoPoIFpwFxu77XAzwqicqZyfbYQ6tlR8sCTLM=; b=Hs7G3FygusZkNqYIe5f+KAnj5ZRssbqwGkXWs4UKMJ44ALjjjlSexnHqyh33/+hgJP sycY2dSTi3nLfp1Ml1p1FIH9Kk0FqCiw0E0vtjrlkkJ1Zo3LcWWW/YLdsd8yC3Oc6/iX valzCxCRM3PF77m/RH6WNiYqroP8fCILHkknRc36l9Rgi2k+vZB2luT7te93blHD1FJL EqloFtP6wgxFxAjL3lj9zciDjMI0xPsIk96cu6EDvAIbP+/HR6fLXXfHjKETd6m8F9Uu edKjvGMoy6S5LGKAWJ47FsRIumj5oSJJZdFv3LhM/ooaxZCSYMUFEBaTn6Au3pxmKnki u7Rg== X-Gm-Message-State: AOJu0YxjN3TvG1mufZIzJtr2NO3t8gv1hrYRjQXgoWy65CejkmEBwbmY LmUhF58PiRQ2uNFBTtnlm6w7c8TFKbw= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a25:a2c6:0:b0:d0b:d8cd:e661 with SMTP id c6-20020a25a2c6000000b00d0bd8cde661mr8642ybn.12.1691162727571; Fri, 04 Aug 2023 08:25:27 -0700 (PDT) Date: Fri, 4 Aug 2023 08:25:26 -0700 In-Reply-To: Mime-Version: 1.0 References: <20230803042732.88515-1-weijiang.yang@intel.com> <20230803042732.88515-13-weijiang.yang@intel.com> Message-ID: Subject: Re: [PATCH v5 12/19] KVM:x86: Save and reload SSP to/from SMRAM From: Sean Christopherson To: Chao Gao Cc: Yang Weijiang , pbonzini@redhat.com, peterz@infradead.org, john.allen@amd.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, rick.p.edgecombe@intel.com, binbin.wu@linux.intel.com Content-Type: text/plain; charset="us-ascii" X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=unavailable 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 On Fri, Aug 04, 2023, Chao Gao wrote: > On Thu, Aug 03, 2023 at 12:27:25AM -0400, Yang Weijiang wrote: > >Save CET SSP to SMRAM on SMI and reload it on RSM. > >KVM emulates architectural behavior when guest enters/leaves SMM > >mode, i.e., save registers to SMRAM at the entry of SMM and reload > >them at the exit of SMM. Per SDM, SSP is defined as one of > >the fields in SMRAM for 64-bit mode, so handle the state accordingly. > > > >Check is_smm() to determine whether kvm_cet_is_msr_accessible() > >is called in SMM mode so that kvm_{set,get}_msr() works in SMM mode. > > > >Signed-off-by: Yang Weijiang > >--- > > arch/x86/kvm/smm.c | 11 +++++++++++ > > arch/x86/kvm/smm.h | 2 +- > > arch/x86/kvm/x86.c | 11 ++++++++++- > > 3 files changed, 22 insertions(+), 2 deletions(-) > > > >diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c > >index b42111a24cc2..e0b62d211306 100644 > >--- a/arch/x86/kvm/smm.c > >+++ b/arch/x86/kvm/smm.c > >@@ -309,6 +309,12 @@ void enter_smm(struct kvm_vcpu *vcpu) > > > > kvm_smm_changed(vcpu, true); > > > >+#ifdef CONFIG_X86_64 > >+ if (guest_can_use(vcpu, X86_FEATURE_SHSTK) && > >+ kvm_get_msr(vcpu, MSR_KVM_GUEST_SSP, &smram.smram64.ssp)) > >+ goto error; > >+#endif > > SSP save/load should go to enter_smm_save_state_64() and rsm_load_state_64(), > where other fields of SMRAM are handled. +1. The right way to get/set MSRs like this is to use __kvm_get_msr() and pass %true for @host_initiated. Though I would add a prep patch to provide wrappers for __kvm_get_msr() and __kvm_set_msr(). Naming will be hard, but I think we can use kvm_{read,write}_msr() to go along with the KVM-initiated register accessors/mutators, e.g. kvm_register_read(), kvm_pdptr_write(), etc. Then you don't need to wait until after kvm_smm_changed(), and kvm_cet_is_msr_accessible() doesn't need the confusing (and broken) SMM waiver, e.g. as Chao points out below, that would allow the guest to access the synthetic MSR. Delta patch at the bottom (would need to be split up, rebased, etc.). > > if (kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, &smram, sizeof(smram))) > > goto error; > > > >@@ -586,6 +592,11 @@ int emulator_leave_smm(struct x86_emulate_ctxt *ctxt) > > if ((vcpu->arch.hflags & HF_SMM_INSIDE_NMI_MASK) == 0) > > static_call(kvm_x86_set_nmi_mask)(vcpu, false); > > > >+#ifdef CONFIG_X86_64 > >+ if (guest_can_use(vcpu, X86_FEATURE_SHSTK) && > >+ kvm_set_msr(vcpu, MSR_KVM_GUEST_SSP, smram.smram64.ssp)) > >+ return X86EMUL_UNHANDLEABLE; > >+#endif > > kvm_smm_changed(vcpu, false); > > > > /* > >diff --git a/arch/x86/kvm/smm.h b/arch/x86/kvm/smm.h > >index a1cf2ac5bd78..1e2a3e18207f 100644 > >--- a/arch/x86/kvm/smm.h > >+++ b/arch/x86/kvm/smm.h > >@@ -116,8 +116,8 @@ struct kvm_smram_state_64 { > > u32 smbase; > > u32 reserved4[5]; > > > >- /* ssp and svm_* fields below are not implemented by KVM */ > > u64 ssp; > >+ /* svm_* fields below are not implemented by KVM */ > > u64 svm_guest_pat; > > u64 svm_host_efer; > > u64 svm_host_cr4; > >diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > >index 98f3ff6078e6..56aa5a3d3913 100644 > >--- a/arch/x86/kvm/x86.c > >+++ b/arch/x86/kvm/x86.c > >@@ -3644,8 +3644,17 @@ static bool kvm_cet_is_msr_accessible(struct kvm_vcpu *vcpu, > > if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK)) > > return false; > > > >- if (msr->index == MSR_KVM_GUEST_SSP) > >+ /* > >+ * This MSR is synthesized mainly for userspace access during > >+ * Live Migration, it also can be accessed in SMM mode by VMM. > >+ * Guest is not allowed to access this MSR. > >+ */ > >+ if (msr->index == MSR_KVM_GUEST_SSP) { > >+ if (IS_ENABLED(CONFIG_X86_64) && is_smm(vcpu)) > >+ return true; > > On second thoughts, this is incorrect. We don't want guest in SMM > mode to read/write SSP via the synthesized MSR. Right? It's not a guest read though, KVM is doing the read while emulating SMI/RSM. > You can > 1. move set/get guest SSP into two helper functions, e.g., kvm_set/get_ssp() > 2. call kvm_set/get_ssp() for host-initiated MSR accesses and SMM transitions. We could, but that would largely defeat the purpose of kvm_x86_ops.{g,s}et_msr(), i.e. we already have hooks to get at MSR values that are buried in the VMCS/VMCB, the interface is just a bit kludgy. > 3. refuse guest accesses to the synthesized MSR. --- arch/x86/include/asm/kvm_host.h | 8 +++++++- arch/x86/kvm/cpuid.c | 2 +- arch/x86/kvm/smm.c | 10 ++++------ arch/x86/kvm/x86.c | 17 +++++++++++++---- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f883696723f4..fe8484bc8082 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1939,7 +1939,13 @@ void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu); void kvm_enable_efer_bits(u64); bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer); -int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, bool host_initiated); + +/* + * kvm_msr_{read,write}() are KVM-internal helpers, i.e. for when KVM needs to + * get/set an MSR value when emulating CPU behavior. + */ +int kvm_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data); +int kvm_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 *data); int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data); int kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data); int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 1a601be7b4fa..b595645b2af7 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1515,7 +1515,7 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, *edx = entry->edx; if (function == 7 && index == 0) { u64 data; - if (!__kvm_get_msr(vcpu, MSR_IA32_TSX_CTRL, &data, true) && + if (!kvm_msr_read(vcpu, MSR_IA32_TSX_CTRL, &data) && (data & TSX_CTRL_CPUID_CLEAR)) *ebx &= ~(F(RTM) | F(HLE)); } else if (function == 0x80000007) { diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c index e0b62d211306..8db12831877e 100644 --- a/arch/x86/kvm/smm.c +++ b/arch/x86/kvm/smm.c @@ -275,6 +275,10 @@ static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, enter_smm_save_seg_64(vcpu, &smram->gs, VCPU_SREG_GS); smram->int_shadow = static_call(kvm_x86_get_interrupt_shadow)(vcpu); + + if (guest_can_use(vcpu, X86_FEATURE_SHSTK) + KVM_BUG_ON(kvm_msr_read(vcpu, MSR_KVM_GUEST_SSP, + &smram.smram64.ssp), vcpu->kvm)); } #endif @@ -309,12 +313,6 @@ void enter_smm(struct kvm_vcpu *vcpu) kvm_smm_changed(vcpu, true); -#ifdef CONFIG_X86_64 - if (guest_can_use(vcpu, X86_FEATURE_SHSTK) && - kvm_get_msr(vcpu, MSR_KVM_GUEST_SSP, &smram.smram64.ssp)) - goto error; -#endif - if (kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, &smram, sizeof(smram))) goto error; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2e200a5d00e9..872767b7bf51 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1924,8 +1924,8 @@ static int kvm_set_msr_ignored_check(struct kvm_vcpu *vcpu, * Returns 0 on success, non-0 otherwise. * Assumes vcpu_load() was already called. */ -int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, - bool host_initiated) +static int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, + bool host_initiated) { struct msr_data msr; int ret; @@ -1951,6 +1951,16 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, return ret; } +int kvm_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 *data) +{ + return __kvm_get_msr(vcpu, index, data, true); +} + +int kvm_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data) +{ + return __kvm_get_msr(vcpu, index, data, true); +} + static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu, u32 index, u64 *data, bool host_initiated) { @@ -4433,8 +4443,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 1; if (msr == MSR_IA32_PL0_SSP || msr == MSR_IA32_PL1_SSP || msr == MSR_IA32_PL2_SSP) { - msr_info->data = - vcpu->arch.cet_s_ssp[msr - MSR_IA32_PL0_SSP]; + msr_info->data = vcpu->arch.cet_s_ssp[msr - MSR_IA32_PL0_SSP]; } else if (msr == MSR_IA32_U_CET || msr == MSR_IA32_PL3_SSP) { kvm_get_xsave_msr(msr_info); } base-commit: 82e95ab0094bf1b823a6f9c9a07238852b375a22 --