From nobody Thu Oct 2 19:27:56 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65CB62D5A13 for ; Fri, 12 Sep 2025 23:23:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757719432; cv=none; b=kVBUmDcMbQK9r1gyc19l/YhbCS/tr7iWHpeggsRJnIWhRb26JGXoOvGU6ex5sskybo9g2kfA6EV78Sppn0IuyLcVAyTaRqtoDuiZyGPZaRRZg0AIzKFcR52IHsPs2WoDjwwgHpofzBBGFTrMRlExPe+CsSy/adA60KSyuxLh374= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757719432; c=relaxed/simple; bh=vQDdu1zHF4bPFrrDNQxsUDgUl3nDRRZ82FO95++Z81I=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=RENyvjbhLPZYXQ+9zt7tIa0fJXp3g8BoifEcXxRrbP+2ACMfHWafRMdvQ2YOKaT534wNFZlpd4sruagI47Islx+lHKrFd6sXGDN8lEdjYED1SATAG5HM1i8LZFJroz3fZrcuY0GQT9qRc/YhVCpXQNBaptB6+wWJjW7cBxe6WRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=NjE7J40C; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="NjE7J40C" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-32e0b00138cso179437a91.3 for ; Fri, 12 Sep 2025 16:23:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1757719430; x=1758324230; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=tsK8S7ainZOuiq7DM/VWeS+FQWWRgudnHijGojTqtSE=; b=NjE7J40CbkboexwUpkOVNsySS7jfEvBIcJ9SLkjIMvRAyC1C/QNC93TzI9QxHjMA4u 3r9GAMr7W+8SKm37PxZo+XfzmkekQn4+LlN5MfELwrS56UGuaJBmyuaViIENEziLtIup L+YdMJN2vDfJFHugcxNqr+I5rhwYnvp2M8anMknkJPsAbTLF2UJ1l1cNec1v8tVs/I2+ ed26fka81WYQQlRWSDWxThbZIWIAmwSQjtystieDgNdnzYnu5pcXaAdxd1oGg0PwyjeP DQRBvTTKVINWcRPhf4X+la3NV4hzlkMC0N3Z8HhWqw59syAY2dktdN1pQ+P4ZaH5w4J4 3bdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757719430; x=1758324230; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=tsK8S7ainZOuiq7DM/VWeS+FQWWRgudnHijGojTqtSE=; b=cn4qPrixtCvJB36S+GpMdkwKvcXsmquThhTy+kHN3CklCB2h+EOxQxoh2XOE0AAF7q veL1F+Vey1gff7XKHChIWMeSKlgn617AKqv1AprfmB+mpJz39rO4ovSCOsbC2taWE3PE 2cLQzLbR5/gVzou5bAk846omHW1S70jc8ma7uY/SrwNkCMLoHGh25nwX6ArUeLJYyIZK Cy8cvU3LN2XVjbA+KiaU7eCeiG9VmvUw5FIAEva9PAdcN24ZhkLdF2TjUUFQvpKlmWYo 4QotgbvQo0rNLt6wezlVAg+sS57i9jJYuVD7NVmHvR0ta62I1V6Kyi1H5yDygoZwfTB4 XCWw== X-Forwarded-Encrypted: i=1; AJvYcCW1Mczb3EHgaoftB3necpaDJTe949DeEub7nab+rIGB6rirl40eqSu7iljU0vfkhPF57/xeRsuS2un4nbw=@vger.kernel.org X-Gm-Message-State: AOJu0YybdrnBDy3a6dJ8d8d1UhI6irV6tn/XrX91juxeDyj5TtfdZEYT mVRwb1CpYeWCM063h0nHEdMa6fCHtreaBy24M5t9uYy4N6ytLtwm6fhbrFB4JoM4LfymkYm8l/O a0sIWcA== X-Google-Smtp-Source: AGHT+IFvmwPke7/pDRYXxhNym9lrKDGTafHhCXPfQmEL//L2GNevsjrfbq484QdlEwKFAEmqSAGwTvkqMxo= X-Received: from pjj16.prod.google.com ([2002:a17:90b:5550:b0:328:887d:69f0]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1dd1:b0:32d:dadf:b6ac with SMTP id 98e67ed59e1d1-32de4fb1099mr5747605a91.33.1757719429747; Fri, 12 Sep 2025 16:23:49 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 12 Sep 2025 16:22:52 -0700 In-Reply-To: <20250912232319.429659-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250912232319.429659-1-seanjc@google.com> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog Message-ID: <20250912232319.429659-15-seanjc@google.com> Subject: [PATCH v15 14/41] KVM: VMX: Emulate read and write to CET MSRs From: Sean Christopherson To: Paolo Bonzini , Sean Christopherson Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Tom Lendacky , Mathias Krause , John Allen , Rick Edgecombe , Chao Gao , Maxim Levitsky , Xiaoyao Li , Zhang Yi Z Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yang Weijiang Add emulation interface for CET MSR access. The emulation code is split into common part and vendor specific part. The former does common checks for MSRs, e.g., accessibility, data validity etc., then passes operation to either XSAVE-managed MSRs via the helpers or CET VMCS fields. SSP can only be read via RDSSP. Writing even requires destructive and potentially faulting operations such as SAVEPREVSSP/RSTORSSP or SETSSBSY/CLRSSBSY. Let the host use a pseudo-MSR that is just a wrapper for the GUEST_SSP field of the VMCS. Suggested-by: Sean Christopherson Signed-off-by: Yang Weijiang Tested-by: Mathias Krause Tested-by: John Allen Tested-by: Rick Edgecombe Signed-off-by: Chao Gao [sean: drop call to kvm_set_xstate_msr() for S_CET, consolidate code] Signed-off-by: Sean Christopherson Reviewed-by: Binbin Wu Reviewed-by: Xiaoyao Li --- arch/x86/kvm/vmx/vmx.c | 18 ++++++++++++ arch/x86/kvm/x86.c | 64 ++++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/x86.h | 23 +++++++++++++++ 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 227b45430ad8..4fc1dbba2eb0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2106,6 +2106,15 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_da= ta *msr_info) else msr_info->data =3D vmx->pt_desc.guest.addr_a[index / 2]; break; + case MSR_IA32_S_CET: + msr_info->data =3D vmcs_readl(GUEST_S_CET); + break; + case MSR_KVM_INTERNAL_GUEST_SSP: + msr_info->data =3D vmcs_readl(GUEST_SSP); + break; + case MSR_IA32_INT_SSP_TAB: + msr_info->data =3D vmcs_readl(GUEST_INTR_SSP_TABLE); + break; case MSR_IA32_DEBUGCTLMSR: msr_info->data =3D vmx_guest_debugctl_read(); break; @@ -2424,6 +2433,15 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_da= ta *msr_info) else vmx->pt_desc.guest.addr_a[index / 2] =3D data; break; + case MSR_IA32_S_CET: + vmcs_writel(GUEST_S_CET, data); + break; + case MSR_KVM_INTERNAL_GUEST_SSP: + vmcs_writel(GUEST_SSP, data); + break; + case MSR_IA32_INT_SSP_TAB: + vmcs_writel(GUEST_INTR_SSP_TABLE, data); + break; case MSR_IA32_PERF_CAPABILITIES: if (data & PMU_CAP_LBR_FMT) { if ((data & PMU_CAP_LBR_FMT) !=3D diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 460ceae11495..0b67b1b0e361 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1890,6 +1890,44 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 = index, u64 data, =20 data =3D (u32)data; break; + case MSR_IA32_U_CET: + case MSR_IA32_S_CET: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && + !guest_cpu_cap_has(vcpu, X86_FEATURE_IBT)) + return KVM_MSR_RET_UNSUPPORTED; + if (!kvm_is_valid_u_s_cet(vcpu, data)) + return 1; + break; + case MSR_KVM_INTERNAL_GUEST_SSP: + if (!host_initiated) + return 1; + fallthrough; + /* + * Note that the MSR emulation here is flawed when a vCPU + * doesn't support the Intel 64 architecture. The expected + * architectural behavior in this case is that the upper 32 + * bits do not exist and should always read '0'. However, + * because the actual hardware on which the virtual CPU is + * running does support Intel 64, XRSTORS/XSAVES in the + * guest could observe behavior that violates the + * architecture. Intercepting XRSTORS/XSAVES for this + * special case isn't deemed worthwhile. + */ + case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) + return KVM_MSR_RET_UNSUPPORTED; + /* + * MSR_IA32_INT_SSP_TAB is not present on processors that do + * not support Intel 64 architecture. + */ + if (index =3D=3D MSR_IA32_INT_SSP_TAB && !guest_cpu_cap_has(vcpu, X86_FE= ATURE_LM)) + return KVM_MSR_RET_UNSUPPORTED; + if (is_noncanonical_msr_address(data, vcpu)) + return 1; + /* All SSP MSRs except MSR_IA32_INT_SSP_TAB must be 4-byte aligned */ + if (index !=3D MSR_IA32_INT_SSP_TAB && !IS_ALIGNED(data, 4)) + return 1; + break; } =20 msr.data =3D data; @@ -1934,6 +1972,20 @@ static int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 = index, u64 *data, !guest_cpu_cap_has(vcpu, X86_FEATURE_RDPID)) return 1; break; + case MSR_IA32_U_CET: + case MSR_IA32_S_CET: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && + !guest_cpu_cap_has(vcpu, X86_FEATURE_IBT)) + return KVM_MSR_RET_UNSUPPORTED; + break; + case MSR_KVM_INTERNAL_GUEST_SSP: + if (!host_initiated) + return 1; + fallthrough; + case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB: + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) + return KVM_MSR_RET_UNSUPPORTED; + break; } =20 msr.index =3D index; @@ -3864,12 +3916,12 @@ static __always_inline void kvm_access_xstate_msr(s= truct kvm_vcpu *vcpu, kvm_fpu_put(); } =20 -static __maybe_unused void kvm_set_xstate_msr(struct kvm_vcpu *vcpu, struc= t msr_data *msr_info) +static void kvm_set_xstate_msr(struct kvm_vcpu *vcpu, struct msr_data *msr= _info) { kvm_access_xstate_msr(vcpu, msr_info, MSR_TYPE_W); } =20 -static __maybe_unused void kvm_get_xstate_msr(struct kvm_vcpu *vcpu, struc= t msr_data *msr_info) +static void kvm_get_xstate_msr(struct kvm_vcpu *vcpu, struct msr_data *msr= _info) { kvm_access_xstate_msr(vcpu, msr_info, MSR_TYPE_R); } @@ -4255,6 +4307,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct= msr_data *msr_info) vcpu->arch.guest_fpu.xfd_err =3D data; break; #endif + case MSR_IA32_U_CET: + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + kvm_set_xstate_msr(vcpu, msr_info); + break; default: if (kvm_pmu_is_valid_msr(vcpu, msr)) return kvm_pmu_set_msr(vcpu, msr_info); @@ -4604,6 +4660,10 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct= msr_data *msr_info) msr_info->data =3D vcpu->arch.guest_fpu.xfd_err; break; #endif + case MSR_IA32_U_CET: + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + kvm_get_xstate_msr(vcpu, msr_info); + break; default: if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) return kvm_pmu_get_msr(vcpu, msr_info); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index a7c9c72fca93..076eccba0f7e 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -710,4 +710,27 @@ int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu, i= nt cpl, =20 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu); =20 +#define CET_US_RESERVED_BITS GENMASK(9, 6) +#define CET_US_SHSTK_MASK_BITS GENMASK(1, 0) +#define CET_US_IBT_MASK_BITS (GENMASK_ULL(5, 2) | GENMASK_ULL(63, 10)) +#define CET_US_LEGACY_BITMAP_BASE(data) ((data) >> 12) + +static inline bool kvm_is_valid_u_s_cet(struct kvm_vcpu *vcpu, u64 data) +{ + if (data & CET_US_RESERVED_BITS) + return false; + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) && + (data & CET_US_SHSTK_MASK_BITS)) + return false; + if (!guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) && + (data & CET_US_IBT_MASK_BITS)) + return false; + if (!IS_ALIGNED(CET_US_LEGACY_BITMAP_BASE(data), 4)) + return false; + /* IBT can be suppressed iff the TRACKER isn't WAIT_ENDBR. */ + if ((data & CET_SUPPRESS) && (data & CET_WAIT_ENDBR)) + return false; + + return true; +} #endif --=20 2.51.0.384.g4c02a37b29-goog