From nobody Wed Dec 31 06:40:04 2025 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2FA36C4332F for ; Tue, 7 Nov 2023 15:11:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234789AbjKGPLU (ORCPT ); Tue, 7 Nov 2023 10:11:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234524AbjKGPLH (ORCPT ); Tue, 7 Nov 2023 10:11:07 -0500 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F3725FC2; Tue, 7 Nov 2023 07:01:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1699369319; x=1730905319; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uPFtvM2v1dDYMiCAKZicT6oJP7EaUdLLM8saT8zml+w=; b=EN3fmf1TvDUpyKQCcfN/6LaTSHF9OkfDKS2SN8ZiZx3dnhd9cz15RhIi lop62EeWLYh7Pcg0ttnzHkL0XYtz5n04lzRRw5odSsEPZ9436uLEwp6Cp OTAauZ3nZuQiL2OWlSfK73aLHWfuyfWa/lGKibPkmn4e3eo7KczuST0RL CtFqkoIdXjzWpfHPGBS8sCDyvKdwVkUhNOIqGbRnmEMluV5PK7l6sgyCQ z478jimu0YnL9T8NHCZvqdzhi5T0GzRHZ8CiGkuzAt2JFAGu2KExO9KCW SkmPaNYWPpoemzqpZyb5JzFdIfSmzPM6z2gBikIkY4I/WLd+DxVd4FpTr Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10887"; a="2462617" X-IronPort-AV: E=Sophos;i="6.03,284,1694761200"; d="scan'208";a="2462617" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Nov 2023 06:58:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.03,284,1694761200"; d="scan'208";a="10851602" Received: from ls.sc.intel.com (HELO localhost) ([172.25.112.31]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Nov 2023 06:58:26 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , erdemaktas@google.com, Sean Christopherson , Sagi Shahar , David Matlack , Kai Huang , Zhi Wang , chen.bo@intel.com, hang.yuan@intel.com, tina.zhang@intel.com Subject: [PATCH v17 097/116] KVM: TDX: Handle MSR MTRRCap and MTRRDefType access Date: Tue, 7 Nov 2023 06:57:03 -0800 Message-Id: <08515039b3a59f8ca2b95a28dfed5331d6651fb5.1699368322.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Isaku Yamahata Handle MTRRCap RO MSR to return all features are unsupported and handle MTRRDefType MSR to accept only E=3D1,FE=3D0,type=3Dwriteback. enable MTRR, disable Fixed range MTRRs, default memory type=3Dwriteback TDX virtualizes that cpuid to report MTRR to guest TD and TDX enforces guest CR0.CD=3D0. If guest tries to set CR0.CD=3D1, it results in #GP. Whi= le updating MTRR requires to set CR0.CD=3D1 (and other cache flushing operations). It means guest TD can't update MTRR. Virtualize MTRR as all features disabled and default memory type as writeback. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/tdx.c | 99 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index aa4b29863b66..01966d57c3d1 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -580,18 +580,7 @@ u8 tdx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, b= ool is_mmio) if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT; =20 - /* - * TDX enforces CR0.CD =3D 0 and KVM MTRR emulation enforces writeback. - * TODO: implement MTRR MSR emulation so that - * MTRRCap: SMRR=3D0: SMRR interface unsupported - * WC=3D0: write combining unsupported - * FIX=3D0: Fixed range registers unsupported - * VCNT=3D0: number of variable range regitsers =3D 0 - * MTRRDefType: E=3D1, FE=3D0, type=3Dwriteback only. Don't allow other v= alue. - * E=3D1: enable MTRR - * FE=3D0: disable fixed range MTRRs - * type: default memory type=3Dwriteback - */ + /* TDX enforces CR0.CD =3D 0 and KVM MTRR emulation enforces writeback. */ return MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT; } =20 @@ -1915,7 +1904,9 @@ bool tdx_has_emulated_msr(u32 index, bool write) case MSR_IA32_UCODE_REV: case MSR_IA32_ARCH_CAPABILITIES: case MSR_IA32_POWER_CTL: + case MSR_MTRRcap: case MSR_IA32_CR_PAT: + case MSR_MTRRdefType: case MSR_IA32_TSC_DEADLINE: case MSR_IA32_MISC_ENABLE: case MSR_PLATFORM_INFO: @@ -1957,16 +1948,47 @@ bool tdx_has_emulated_msr(u32 index, bool write) =20 int tdx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) { - if (tdx_has_emulated_msr(msr->index, false)) - return kvm_get_msr_common(vcpu, msr); - return 1; + switch (msr->index) { + case MSR_MTRRcap: + /* + * Override kvm_mtrr_get_msr() which hardcodes the value. + * Report SMRR =3D 0, WC =3D 0, FIX =3D 0 VCNT =3D 0 to disable MTRR + * effectively. + */ + msr->data =3D 0; + return 0; + default: + if (tdx_has_emulated_msr(msr->index, false)) + return kvm_get_msr_common(vcpu, msr); + return 1; + } } =20 int tdx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) { - if (tdx_has_emulated_msr(msr->index, true)) + switch (msr->index) { + case MSR_MTRRdefType: + /* + * Allow writeback only for all memory. + * Because it's reported that fixed range MTRR isn't supported + * and VCNT=3D0, enforce MTRRDefType.FE =3D 0 and don't care + * variable range MTRRs. Only default memory type matters. + * + * bit 11 E: MTRR enable/disable + * bit 12 FE: Fixed-range MTRRs enable/disable + * (E, FE) =3D (1, 1): enable MTRR and Fixed range MTRR + * (E, FE) =3D (1, 0): enable MTRR, disable Fixed range MTRR + * (E, FE) =3D (0, *): disable all MTRRs. all physical memory + * is UC + */ + if (msr->data !=3D ((1 << 11) | MTRR_TYPE_WRBACK)) + return 1; return kvm_set_msr_common(vcpu, msr); - return 1; + default: + if (tdx_has_emulated_msr(msr->index, true)) + return kvm_set_msr_common(vcpu, msr); + return 1; + } } =20 static int tdx_get_capabilities(struct kvm_tdx_cmd *cmd) @@ -2715,6 +2737,45 @@ static int tdx_td_vcpu_init(struct kvm_vcpu *vcpu, u= 64 vcpu_rcx) return ret; } =20 +static int tdx_vcpu_init_mtrr(struct kvm_vcpu *vcpu) +{ + struct msr_data msr; + int ret; + int i; + + /* + * To avoid confusion with reporting VNCT =3D 0, explicitly disable + * vaiale-range reisters. + */ + for (i =3D 0; i < KVM_NR_VAR_MTRR; i++) { + /* phymask */ + msr =3D (struct msr_data) { + .host_initiated =3D true, + .index =3D 0x200 + 2 * i + 1, + .data =3D 0, /* valid =3D 0 to disable. */ + }; + ret =3D kvm_set_msr_common(vcpu, &msr); + if (ret) + return -EINVAL; + } + + /* Set MTRR to use writeback on reset. */ + msr =3D (struct msr_data) { + .host_initiated =3D true, + .index =3D MSR_MTRRdefType, + /* + * Set E(enable MTRR)=3D1, FE(enable fixed range MTRR)=3D0, default + * type=3Dwriteback on reset to avoid UC. Note E=3D0 means all + * memory is UC. + */ + .data =3D (1 << 11) | MTRR_TYPE_WRBACK, + }; + ret =3D kvm_set_msr_common(vcpu, &msr); + if (ret) + return -EINVAL; + return 0; +} + int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp) { struct msr_data apic_base_msr; @@ -2752,6 +2813,10 @@ int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __use= r *argp) if (kvm_set_apic_base(vcpu, &apic_base_msr)) return -EINVAL; =20 + ret =3D tdx_vcpu_init_mtrr(vcpu); + if (ret) + return ret; + ret =3D tdx_td_vcpu_init(vcpu, (u64)cmd.data); if (ret) return ret; --=20 2.25.1