Skip to content

Commit 033cc16

Browse files
yang-weijiangsean-jc
authored andcommitted
KVM: nVMX: Virtualize NO_HW_ERROR_CODE_CC for L1 event injection to L2
Per SDM description(Vol.3D, Appendix A.1): "If bit 56 is read as 1, software can use VM entry to deliver a hardware exception with or without an error code, regardless of vector" Modify has_error_code check before inject events to nested guest. Only enforce the check when guest is in real mode, the exception is not hard exception and the platform doesn't enumerate bit56 in VMX_BASIC, in all other case ignore the check to make the logic consistent with SDM. Signed-off-by: Yang Weijiang <weijiang.yang@intel.com> Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Chao Gao <chao.gao@intel.com> Tested-by: Mathias Krause <minipli@grsecurity.net> Tested-by: John Allen <john.allen@amd.com> Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Signed-off-by: Chao Gao <chao.gao@intel.com> Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> Link: https://lore.kernel.org/r/20250919223258.1604852-31-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent f7336d4 commit 033cc16

2 files changed

Lines changed: 23 additions & 9 deletions

File tree

arch/x86/kvm/vmx/nested.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,9 +1272,10 @@ static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data)
12721272
{
12731273
const u64 feature_bits = VMX_BASIC_DUAL_MONITOR_TREATMENT |
12741274
VMX_BASIC_INOUT |
1275-
VMX_BASIC_TRUE_CTLS;
1275+
VMX_BASIC_TRUE_CTLS |
1276+
VMX_BASIC_NO_HW_ERROR_CODE_CC;
12761277

1277-
const u64 reserved_bits = GENMASK_ULL(63, 56) |
1278+
const u64 reserved_bits = GENMASK_ULL(63, 57) |
12781279
GENMASK_ULL(47, 45) |
12791280
BIT_ULL(31);
12801281

@@ -2949,7 +2950,6 @@ static int nested_check_vm_entry_controls(struct kvm_vcpu *vcpu,
29492950
u8 vector = intr_info & INTR_INFO_VECTOR_MASK;
29502951
u32 intr_type = intr_info & INTR_INFO_INTR_TYPE_MASK;
29512952
bool has_error_code = intr_info & INTR_INFO_DELIVER_CODE_MASK;
2952-
bool should_have_error_code;
29532953
bool urg = nested_cpu_has2(vmcs12,
29542954
SECONDARY_EXEC_UNRESTRICTED_GUEST);
29552955
bool prot_mode = !urg || vmcs12->guest_cr0 & X86_CR0_PE;
@@ -2966,12 +2966,19 @@ static int nested_check_vm_entry_controls(struct kvm_vcpu *vcpu,
29662966
CC(intr_type == INTR_TYPE_OTHER_EVENT && vector != 0))
29672967
return -EINVAL;
29682968

2969-
/* VM-entry interruption-info field: deliver error code */
2970-
should_have_error_code =
2971-
intr_type == INTR_TYPE_HARD_EXCEPTION && prot_mode &&
2972-
x86_exception_has_error_code(vector);
2973-
if (CC(has_error_code != should_have_error_code))
2974-
return -EINVAL;
2969+
/*
2970+
* Cannot deliver error code in real mode or if the interrupt
2971+
* type is not hardware exception. For other cases, do the
2972+
* consistency check only if the vCPU doesn't enumerate
2973+
* VMX_BASIC_NO_HW_ERROR_CODE_CC.
2974+
*/
2975+
if (!prot_mode || intr_type != INTR_TYPE_HARD_EXCEPTION) {
2976+
if (CC(has_error_code))
2977+
return -EINVAL;
2978+
} else if (!nested_cpu_has_no_hw_errcode_cc(vcpu)) {
2979+
if (CC(has_error_code != x86_exception_has_error_code(vector)))
2980+
return -EINVAL;
2981+
}
29752982

29762983
/* VM-entry exception error code */
29772984
if (CC(has_error_code &&
@@ -7217,6 +7224,8 @@ static void nested_vmx_setup_basic(struct nested_vmx_msrs *msrs)
72177224
msrs->basic |= VMX_BASIC_TRUE_CTLS;
72187225
if (cpu_has_vmx_basic_inout())
72197226
msrs->basic |= VMX_BASIC_INOUT;
7227+
if (cpu_has_vmx_basic_no_hw_errcode_cc())
7228+
msrs->basic |= VMX_BASIC_NO_HW_ERROR_CODE_CC;
72207229
}
72217230

72227231
static void nested_vmx_setup_cr_fixed(struct nested_vmx_msrs *msrs)

arch/x86/kvm/vmx/nested.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ static inline bool nested_cr4_valid(struct kvm_vcpu *vcpu, unsigned long val)
309309
__kvm_is_valid_cr4(vcpu, val);
310310
}
311311

312+
static inline bool nested_cpu_has_no_hw_errcode_cc(struct kvm_vcpu *vcpu)
313+
{
314+
return to_vmx(vcpu)->nested.msrs.basic & VMX_BASIC_NO_HW_ERROR_CODE_CC;
315+
}
316+
312317
/* No difference in the restrictions on guest and host CR4 in VMX operation. */
313318
#define nested_guest_cr4_valid nested_cr4_valid
314319
#define nested_host_cr4_valid nested_cr4_valid

0 commit comments

Comments
 (0)