KVM: nVMX: Handle split-lock #AC exceptions that happen in L2
commit b33bb78a1fada6445c265c585ee0dd0fc6279102 upstream.
Mark #ACs that won't be reinjected to the guest as wanted by L0 so that
KVM handles split-lock #AC from L2 instead of forwarding the exception to
L1. Split-lock #AC isn't yet virtualized, i.e. L1 will treat it like a
regular #AC and do the wrong thing, e.g. reinject it into L2.
Fixes: e6f8b6c12f
("KVM: VMX: Extend VMXs #AC interceptor to handle split lock #AC in guest")
Cc: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210622172244.3561540-1-seanjc@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
7510c5cd0d
commit
39d0dfab6c
@@ -5787,6 +5787,9 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
|
|||||||
else if (is_breakpoint(intr_info) &&
|
else if (is_breakpoint(intr_info) &&
|
||||||
vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
|
vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
|
||||||
return true;
|
return true;
|
||||||
|
else if (is_alignment_check(intr_info) &&
|
||||||
|
!vmx_guest_inject_ac(vcpu))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
case EXIT_REASON_EXTERNAL_INTERRUPT:
|
case EXIT_REASON_EXTERNAL_INTERRUPT:
|
||||||
return true;
|
return true;
|
||||||
|
@@ -117,6 +117,11 @@ static inline bool is_gp_fault(u32 intr_info)
|
|||||||
return is_exception_n(intr_info, GP_VECTOR);
|
return is_exception_n(intr_info, GP_VECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_alignment_check(u32 intr_info)
|
||||||
|
{
|
||||||
|
return is_exception_n(intr_info, AC_VECTOR);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_machine_check(u32 intr_info)
|
static inline bool is_machine_check(u32 intr_info)
|
||||||
{
|
{
|
||||||
return is_exception_n(intr_info, MC_VECTOR);
|
return is_exception_n(intr_info, MC_VECTOR);
|
||||||
|
@@ -4755,7 +4755,7 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)
|
|||||||
* - Guest has #AC detection enabled in CR0
|
* - Guest has #AC detection enabled in CR0
|
||||||
* - Guest EFLAGS has AC bit set
|
* - Guest EFLAGS has AC bit set
|
||||||
*/
|
*/
|
||||||
static inline bool guest_inject_ac(struct kvm_vcpu *vcpu)
|
bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
|
if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
|
||||||
return true;
|
return true;
|
||||||
@@ -4864,7 +4864,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
|
|||||||
kvm_run->debug.arch.exception = ex_no;
|
kvm_run->debug.arch.exception = ex_no;
|
||||||
break;
|
break;
|
||||||
case AC_VECTOR:
|
case AC_VECTOR:
|
||||||
if (guest_inject_ac(vcpu)) {
|
if (vmx_guest_inject_ac(vcpu)) {
|
||||||
kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
|
kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -352,6 +352,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
|
|||||||
u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa,
|
u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa,
|
||||||
int root_level);
|
int root_level);
|
||||||
|
|
||||||
|
bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
|
||||||
void update_exception_bitmap(struct kvm_vcpu *vcpu);
|
void update_exception_bitmap(struct kvm_vcpu *vcpu);
|
||||||
void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
|
void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
|
||||||
bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
|
bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
|
||||||
|
Reference in New Issue
Block a user