HV: fix the issue of ACRN_REQUEST_EXCP flag is not cleared.

the problem is : System will crash when run crashme.
The root cause of this problem is that when the ACRN_REQUEST_EXCP flag is set by calling
the vcpu_make_request function, the flag is not cleared.
Add the following statement to the vcpu_inject_exception function to fix the problem:
bitmap_test_and_clear_lock(ACRN_REQUEST_EXCP, &vcpu->arch.pending_req);
Tested that one night, there was no crash.

Tracked-On: #2527
Signed-off-by: bing.li<bingx.li@intel.com>
Acked-by:      Eddie Dong<eddie.dong@intel.com>
This commit is contained in:
li bing 2019-04-11 09:30:07 +00:00 committed by wenlingz
parent 28d50f1b96
commit 25741b62db

View File

@ -212,6 +212,7 @@ int32_t vcpu_queue_exception(struct acrn_vcpu *vcpu, uint32_t vector_arg, uint32
} else { } else {
arch->exception_info.error = 0U; arch->exception_info.error = 0U;
} }
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
} }
@ -220,25 +221,28 @@ int32_t vcpu_queue_exception(struct acrn_vcpu *vcpu, uint32_t vector_arg, uint32
static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector) static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector)
{ {
if ((exception_type[vector] & EXCEPTION_ERROR_CODE_VALID) != 0U) { if (bitmap_test_and_clear_lock(ACRN_REQUEST_EXCP, &vcpu->arch.pending_req)) {
exec_vmwrite32(VMX_ENTRY_EXCEPTION_ERROR_CODE,
vcpu->arch.exception_info.error); if ((exception_type[vector] & EXCEPTION_ERROR_CODE_VALID) != 0U) {
} exec_vmwrite32(VMX_ENTRY_EXCEPTION_ERROR_CODE,
vcpu->arch.exception_info.error);
}
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID |
(exception_type[vector] << 8U) | (vector & 0xFFU)); (exception_type[vector] << 8U) | (vector & 0xFFU));
vcpu->arch.exception_info.exception = VECTOR_INVALID; vcpu->arch.exception_info.exception = VECTOR_INVALID;
/* retain rip for exception injection */ /* retain rip for exception injection */
vcpu_retain_rip(vcpu); vcpu_retain_rip(vcpu);
/* SDM 17.3.1.1 For any fault-class exception except a debug exception generated in response to an /* SDM 17.3.1.1 For any fault-class exception except a debug exception generated in response to an
* instruction breakpoint, the value pushed for RF is 1. * instruction breakpoint, the value pushed for RF is 1.
* #DB is treated as Trap in get_exception_type, so RF will not be set for instruction breakpoint. * #DB is treated as Trap in get_exception_type, so RF will not be set for instruction breakpoint.
*/ */
if (get_exception_type(vector) == EXCEPTION_FAULT) { if (get_exception_type(vector) == EXCEPTION_FAULT) {
vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_RF); vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_RF);
}
} }
} }
@ -285,7 +289,6 @@ void vcpu_inject_nmi(struct acrn_vcpu *vcpu)
void vcpu_inject_gp(struct acrn_vcpu *vcpu, uint32_t err_code) void vcpu_inject_gp(struct acrn_vcpu *vcpu, uint32_t err_code)
{ {
(void)vcpu_queue_exception(vcpu, IDT_GP, err_code); (void)vcpu_queue_exception(vcpu, IDT_GP, err_code);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
/* Inject page fault exception(#PF) to guest */ /* Inject page fault exception(#PF) to guest */
@ -293,28 +296,24 @@ void vcpu_inject_pf(struct acrn_vcpu *vcpu, uint64_t addr, uint32_t err_code)
{ {
vcpu_set_cr2(vcpu, addr); vcpu_set_cr2(vcpu, addr);
(void)vcpu_queue_exception(vcpu, IDT_PF, err_code); (void)vcpu_queue_exception(vcpu, IDT_PF, err_code);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
/* Inject invalid opcode exception(#UD) to guest */ /* Inject invalid opcode exception(#UD) to guest */
void vcpu_inject_ud(struct acrn_vcpu *vcpu) void vcpu_inject_ud(struct acrn_vcpu *vcpu)
{ {
(void)vcpu_queue_exception(vcpu, IDT_UD, 0); (void)vcpu_queue_exception(vcpu, IDT_UD, 0);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
/* Inject alignment check exception(#AC) to guest */ /* Inject alignment check exception(#AC) to guest */
void vcpu_inject_ac(struct acrn_vcpu *vcpu) void vcpu_inject_ac(struct acrn_vcpu *vcpu)
{ {
(void)vcpu_queue_exception(vcpu, IDT_AC, 0); (void)vcpu_queue_exception(vcpu, IDT_AC, 0);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
/* Inject stack fault exception(#SS) to guest */ /* Inject stack fault exception(#SS) to guest */
void vcpu_inject_ss(struct acrn_vcpu *vcpu) void vcpu_inject_ss(struct acrn_vcpu *vcpu)
{ {
(void)vcpu_queue_exception(vcpu, IDT_SS, 0); (void)vcpu_queue_exception(vcpu, IDT_SS, 0);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
} }
int32_t interrupt_window_vmexit_handler(struct acrn_vcpu *vcpu) int32_t interrupt_window_vmexit_handler(struct acrn_vcpu *vcpu)