lkml.org 
[lkml]   [2024]   [Feb]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v19 113/130] KVM: TDX: Handle MSR MTRRCap and MTRRDefType access
    Date
    From: Isaku Yamahata <isaku.yamahata@intel.com>

    Handle MTRRCap RO MSR to return all features are unsupported and handle
    MTRRDefType MSR to accept only E=1,FE=0,type=writeback.
    enable MTRR, disable Fixed range MTRRs, default memory type=writeback

    TDX virtualizes that cpuid to report MTRR to guest TD and TDX enforces
    guest CR0.CD=0. If guest tries to set CR0.CD=1, it results in #GP. While
    updating MTRR requires to set CR0.CD=1 (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 <isaku.yamahata@intel.com>
    ---
    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 4c635bfcaf7a..2bddaef495d1 100644
    --- a/arch/x86/kvm/vmx/tdx.c
    +++ b/arch/x86/kvm/vmx/tdx.c
    @@ -611,18 +611,7 @@ u8 tdx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
    if (!kvm_arch_has_noncoherent_dma(vcpu->kvm))
    return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT;

    - /*
    - * TDX enforces CR0.CD = 0 and KVM MTRR emulation enforces writeback.
    - * TODO: implement MTRR MSR emulation so that
    - * MTRRCap: SMRR=0: SMRR interface unsupported
    - * WC=0: write combining unsupported
    - * FIX=0: Fixed range registers unsupported
    - * VCNT=0: number of variable range regitsers = 0
    - * MTRRDefType: E=1, FE=0, type=writeback only. Don't allow other value.
    - * E=1: enable MTRR
    - * FE=0: disable fixed range MTRRs
    - * type: default memory type=writeback
    - */
    + /* TDX enforces CR0.CD = 0 and KVM MTRR emulation enforces writeback. */
    return MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT;
    }

    @@ -1932,7 +1921,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:
    @@ -1974,16 +1965,47 @@ bool tdx_has_emulated_msr(u32 index, bool write)

    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 = 0, WC = 0, FIX = 0 VCNT = 0 to disable MTRR
    + * effectively.
    + */
    + msr->data = 0;
    + return 0;
    + default:
    + if (tdx_has_emulated_msr(msr->index, false))
    + return kvm_get_msr_common(vcpu, msr);
    + return 1;
    + }
    }

    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=0, enforce MTRRDefType.FE = 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) = (1, 1): enable MTRR and Fixed range MTRR
    + * (E, FE) = (1, 0): enable MTRR, disable Fixed range MTRR
    + * (E, FE) = (0, *): disable all MTRRs. all physical memory
    + * is UC
    + */
    + if (msr->data != ((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;
    + }
    }

    static int tdx_get_capabilities(struct kvm_tdx_cmd *cmd)
    @@ -2704,6 +2726,45 @@ static int tdx_td_vcpu_init(struct kvm_vcpu *vcpu, u64 vcpu_rcx)
    return ret;
    }

    +static int tdx_vcpu_init_mtrr(struct kvm_vcpu *vcpu)
    +{
    + struct msr_data msr;
    + int ret;
    + int i;
    +
    + /*
    + * To avoid confusion with reporting VNCT = 0, explicitly disable
    + * vaiale-range reisters.
    + */
    + for (i = 0; i < KVM_NR_VAR_MTRR; i++) {
    + /* phymask */
    + msr = (struct msr_data) {
    + .host_initiated = true,
    + .index = 0x200 + 2 * i + 1,
    + .data = 0, /* valid = 0 to disable. */
    + };
    + ret = kvm_set_msr_common(vcpu, &msr);
    + if (ret)
    + return -EINVAL;
    + }
    +
    + /* Set MTRR to use writeback on reset. */
    + msr = (struct msr_data) {
    + .host_initiated = true,
    + .index = MSR_MTRRdefType,
    + /*
    + * Set E(enable MTRR)=1, FE(enable fixed range MTRR)=0, default
    + * type=writeback on reset to avoid UC. Note E=0 means all
    + * memory is UC.
    + */
    + .data = (1 << 11) | MTRR_TYPE_WRBACK,
    + };
    + ret = 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;
    @@ -2741,6 +2802,10 @@ int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp)
    if (kvm_set_apic_base(vcpu, &apic_base_msr))
    return -EINVAL;

    + ret = tdx_vcpu_init_mtrr(vcpu);
    + if (ret)
    + return ret;
    +
    ret = tdx_td_vcpu_init(vcpu, (u64)cmd.data);
    if (ret)
    return ret;
    --
    2.25.1

    \
     
     \ /
      Last update: 2024-05-27 15:21    [W:8.771 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site