From nobody Mon Oct 6 08:12:24 2025 Received: from mail.zytor.com (terminus.zytor.com [198.137.202.136]) (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 3297324418D; Wed, 23 Jul 2025 17:54:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753293283; cv=none; b=LyyCXlINVwGemjraAP+XzOiDBRWdwUNkYj5JRQAlQnc9mB+hSOu4TK4FO2ujRGNEQ/aWjCv4bPo33iwmbo0F058lYrxJ8GT8rMrUpheff80f+BjhKiZEoIheQDkebi/OxBB8MU07WqTL99c2re/QFQUJx5JzVtSzoKeCginQ6JQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753293283; c=relaxed/simple; bh=O+qfavYKJv5iWUZTQ2uqTtRgKKTYjV8vuHOkwfS7QDc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X7mne9Dvi7xQCD2fmWRtVRlFa28OFV+MBRScB1Gkf6c5+1NVO7NjmyQ/wBPdX8pOSBtgRXn3csNStxv//j5KREqpCch/DbPFZ7+ispSTkVLvZ3tfTAMwgDzXqYvQKw4x7A0GsLYTedmQ3+PPTXjJpoxnQltSfGHbDfNycGKdY6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com; spf=pass smtp.mailfrom=zytor.com; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b=dpMTe6Mv; arc=none smtp.client-ip=198.137.202.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zytor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zytor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=zytor.com header.i=@zytor.com header.b="dpMTe6Mv" Received: from terminus.zytor.com (terminus.zytor.com [IPv6:2607:7c80:54:3:0:0:0:136]) (authenticated bits=0) by mail.zytor.com (8.18.1/8.17.1) with ESMTPSA id 56NHrf0B1284522 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 23 Jul 2025 10:54:05 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.zytor.com 56NHrf0B1284522 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2025072201; t=1753293245; bh=018Q97OXZzIS4qBkIRJzyl3XH/UjDMLrNTbYlNvCC0E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dpMTe6MvRoHSq4lYGjIviafdwU5vqAL1Ohbbz3J4aNx+aikG3U5ZeBGqruScrxuFK V/fNCjQV7MAF8SQHZ79FLeL8U4S5ytXrz+pht31i0RKFhW70eP6jzd6llIT2NIJMvO qtdf9bTDqUZXa2iIIbJT9vItlYcUb0FJu44hQNCwtZMOWhnipNaiJ38UwESAaJ3nUg 35zJtfP+kAhQrtk0v90df/5/Np+P+5K68bADhFJFLmzVNEIvYCKBOpm7qnalH6vNH7 h5WKj4AMi+So/DZ4oasM3yNpK1z/4NkKhtCM0JS0sSrNzw1vbt0PQh512F8dQWemZn Z9zoMVkigQH9Q== From: "Xin Li (Intel)" To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, corbet@lwn.net, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, xin@zytor.com, luto@kernel.org, peterz@infradead.org, andrew.cooper3@citrix.com, chao.gao@intel.com, hch@infradead.org Subject: [PATCH v5 21/23] KVM: nVMX: Add FRED-related VMCS field checks Date: Wed, 23 Jul 2025 10:53:39 -0700 Message-ID: <20250723175341.1284463-22-xin@zytor.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250723175341.1284463-1-xin@zytor.com> References: <20250723175341.1284463-1-xin@zytor.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: Xin Li As with real hardware, nested VMX validates various VMCS fields, including control and guest/host state fields. This patch adds checks for FRED-relat= ed VMCS fields to support nested FRED functionality. Signed-off-by: Xin Li Signed-off-by: Xin Li (Intel) Tested-by: Shan Kang Tested-by: Xuelian Guo --- Change in v5: * Add TB from Xuelian Guo. --- arch/x86/kvm/vmx/nested.c | 80 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 30d2de1243ef..d215e5ade5ef 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2966,6 +2966,8 @@ static int nested_check_vm_entry_controls(struct kvm_= vcpu *vcpu, struct vmcs12 *vmcs12) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); + bool fred_enabled =3D (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) && + (vmcs12->guest_cr4 & X86_CR4_FRED); =20 if (CC(!vmx_control_verify(vmcs12->vm_entry_controls, vmx->nested.msrs.entry_ctls_low, @@ -2984,6 +2986,7 @@ static int nested_check_vm_entry_controls(struct kvm_= vcpu *vcpu, u32 intr_type =3D intr_info & INTR_INFO_INTR_TYPE_MASK; bool has_error_code =3D intr_info & INTR_INFO_DELIVER_CODE_MASK; bool should_have_error_code; + bool has_nested_exception =3D vmx->nested.msrs.basic & VMX_BASIC_NESTED_= EXCEPTION; bool urg =3D nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST); bool prot_mode =3D !urg || vmcs12->guest_cr0 & X86_CR0_PE; @@ -2997,7 +3000,9 @@ static int nested_check_vm_entry_controls(struct kvm_= vcpu *vcpu, /* VM-entry interruption-info field: vector */ if (CC(intr_type =3D=3D INTR_TYPE_NMI_INTR && vector !=3D NMI_VECTOR) || CC(intr_type =3D=3D INTR_TYPE_HARD_EXCEPTION && vector > 31) || - CC(intr_type =3D=3D INTR_TYPE_OTHER_EVENT && vector !=3D 0)) + CC(intr_type =3D=3D INTR_TYPE_OTHER_EVENT && + ((!fred_enabled && vector > 0) || + (fred_enabled && vector > 2)))) return -EINVAL; =20 /* VM-entry interruption-info field: deliver error code */ @@ -3016,6 +3021,15 @@ static int nested_check_vm_entry_controls(struct kvm= _vcpu *vcpu, if (CC(intr_info & INTR_INFO_RESVD_BITS_MASK)) return -EINVAL; =20 + /* + * When the CPU enumerates VMX nested-exception support, bit 13 + * (set to indicate a nested exception) of the intr info field + * may have value 1. Otherwise bit 13 is reserved. + */ + if (CC(!has_nested_exception && + (intr_info & INTR_INFO_NESTED_EXCEPTION_MASK))) + return -EINVAL; + /* VM-entry instruction length */ switch (intr_type) { case INTR_TYPE_SOFT_EXCEPTION: @@ -3025,6 +3039,12 @@ static int nested_check_vm_entry_controls(struct kvm= _vcpu *vcpu, CC(vmcs12->vm_entry_instruction_len =3D=3D 0 && CC(!nested_cpu_has_zero_length_injection(vcpu)))) return -EINVAL; + break; + case INTR_TYPE_OTHER_EVENT: + if (fred_enabled && (vector =3D=3D 1 || vector =3D=3D 2)) + if (CC(vmcs12->vm_entry_instruction_len > 15)) + return -EINVAL; + break; } } =20 @@ -3098,9 +3118,30 @@ static int nested_vmx_check_host_state(struct kvm_vc= pu *vcpu, if (ia32e) { if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) return -EINVAL; + if (vmcs12->vm_exit_controls & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS && + vmcs12->secondary_vm_exit_controls & SECONDARY_VM_EXIT_LOAD_IA32_FRE= D) { + /* Bit 11, bits 5:4, and bit 2 of the IA32_FRED_CONFIG must be zero */ + if (CC(vmcs12->host_ia32_fred_config & + (BIT_ULL(11) | GENMASK_ULL(5, 4) | BIT_ULL(2))) || + CC(vmcs12->host_ia32_fred_rsp1 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_rsp2 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_rsp3 & GENMASK_ULL(5, 0)) || + CC(vmcs12->host_ia32_fred_ssp1 & GENMASK_ULL(2, 0)) || + CC(vmcs12->host_ia32_fred_ssp2 & GENMASK_ULL(2, 0)) || + CC(vmcs12->host_ia32_fred_ssp3 & GENMASK_ULL(2, 0)) || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_config & PAGE= _MASK, vcpu)) || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp1, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp2, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_rsp3, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp1, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp2, vcpu)) = || + CC(is_noncanonical_msr_address(vmcs12->host_ia32_fred_ssp3, vcpu))) + return -EINVAL; + } } else { if (CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || CC(vmcs12->host_cr4 & X86_CR4_PCIDE) || + CC(vmcs12->host_cr4 & X86_CR4_FRED) || CC((vmcs12->host_rip) >> 32)) return -EINVAL; } @@ -3245,6 +3286,43 @@ static int nested_vmx_check_guest_state(struct kvm_v= cpu *vcpu, CC((vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD)))) return -EINVAL; =20 + if (ia32e) { + if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_FRED) { + /* Bit 11, bits 5:4, and bit 2 of the IA32_FRED_CONFIG must be zero */ + if (CC(vmcs12->guest_ia32_fred_config & + (BIT_ULL(11) | GENMASK_ULL(5, 4) | BIT_ULL(2))) || + CC(vmcs12->guest_ia32_fred_rsp1 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_rsp2 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_rsp3 & GENMASK_ULL(5, 0)) || + CC(vmcs12->guest_ia32_fred_ssp1 & GENMASK_ULL(2, 0)) || + CC(vmcs12->guest_ia32_fred_ssp2 & GENMASK_ULL(2, 0)) || + CC(vmcs12->guest_ia32_fred_ssp3 & GENMASK_ULL(2, 0)) || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_config & PAG= E_MASK, vcpu)) || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp1, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp2, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_rsp3, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp1, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp2, vcpu))= || + CC(is_noncanonical_msr_address(vmcs12->guest_ia32_fred_ssp3, vcpu))) + return -EINVAL; + } + if (vmcs12->guest_cr4 & X86_CR4_FRED) { + unsigned int ss_dpl =3D VMX_AR_DPL(vmcs12->guest_ss_ar_bytes); + if (CC(ss_dpl =3D=3D 1 || ss_dpl =3D=3D 2)) + return -EINVAL; + if (ss_dpl =3D=3D 0 && + CC(!(vmcs12->guest_cs_ar_bytes & VMX_AR_L_MASK))) + return -EINVAL; + if (ss_dpl =3D=3D 3 && + (CC(vmcs12->guest_rflags & X86_EFLAGS_IOPL) || + CC(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_STI))) + return -EINVAL; + } + } else { + if (CC(vmcs12->guest_cr4 & X86_CR4_FRED)) + return -EINVAL; + } + if (nested_check_guest_non_reg_state(vmcs12)) return -EINVAL; =20 --=20 2.50.1