hv: virq: refine acrn_handle_pending_request() use goto instruction

The MISRA-C Standards suggests not to use 'goto' instruction.

Tracked-On: #861
Acked-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Tao Yuhong <yuhong.tao@intel.com>
This commit is contained in:
yuhong.tao@intel.com 2018-12-22 18:20:08 +00:00 committed by wenlingz
parent b4de4d1b0f
commit e692d4c721

View File

@ -379,6 +379,8 @@ int32_t external_interrupt_vmexit_handler(struct acrn_vcpu *vcpu)
return ret;
}
static inline int32_t acrn_inject_pending_vector(struct acrn_vcpu *vcpu, uint64_t *pending_req_bits);
int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
{
int32_t ret = 0;
@ -423,85 +425,40 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, intr_info);
arch->inject_event_pending = false;
goto INTR_WIN;
}
/*
* From SDM Vol3 26.3.2.5:
* Once the virtual interrupt is recognized, it will be delivered
* in VMX non-root operation immediately after VM entry(including
* any specified event injection) completes.
*
* So the hardware can handle vmcs event injection and
* evaluation/delivery of apicv virtual interrupts in one time
* vm-entry.
*
* Here to sync the pending interrupts to irr and update rvi if
* needed. And then try to handle vmcs event injection.
*/
if (is_apicv_intr_delivery_supported() &&
bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT, pending_req_bits)) {
vlapic = vcpu_vlapic(vcpu);
vlapic_apicv_inject_pir(vlapic);
}
/* SDM Vol 3 - table 6-2, inject high priority exception before
* maskable hardware interrupt */
if (vcpu_inject_hi_exception(vcpu) != 0) {
goto INTR_WIN;
}
/* inject NMI before maskable hardware interrupt */
if (bitmap_test_and_clear_lock(ACRN_REQUEST_NMI, pending_req_bits)) {
/* Inject NMI vector = 2 */
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
VMX_INT_INFO_VALID | (VMX_INT_TYPE_NMI << 8U) | IDT_NMI);
goto INTR_WIN;
}
/* handling pending vector injection:
* there are many reason inject failed, we need re-inject again
* here should take care
* - SW exception (not maskable by IF)
* - external interrupt, if IF clear, will keep in IDT_VEC_INFO_FIELD
* at next vm exit?
*/
if ((arch->idt_vectoring_info & VMX_INT_INFO_VALID) != 0U) {
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
arch->idt_vectoring_info);
goto INTR_WIN;
}
/* Guest interruptable or not */
if (is_guest_irq_enabled(vcpu)) {
/* Inject external interrupt first */
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EXTINT,
pending_req_bits)) {
/* has pending external interrupts */
ret = vcpu_do_pending_extint(vcpu);
goto INTR_WIN;
}
} else {
/*
* For "virtual-interrupt delivery" disabled case, if
* the virtual interrupt injection conditions are satified,
* then inject through vmcs.
* From SDM Vol3 26.3.2.5:
* Once the virtual interrupt is recognized, it will be delivered
* in VMX non-root operation immediately after VM entry(including
* any specified event injection) completes.
*
* So the hardware can handle vmcs event injection and
* evaluation/delivery of apicv virtual interrupts in one time
* vm-entry.
*
* Here to sync the pending interrupts to irr and update rvi if
* needed. And then try to handle vmcs event injection.
*/
if (!is_apicv_intr_delivery_supported() &&
bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT,
pending_req_bits)) {
ret = vcpu_inject_vlapic_int(vcpu);
goto INTR_WIN;
if (is_apicv_intr_delivery_supported() &&
bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT, pending_req_bits)) {
vlapic = vcpu_vlapic(vcpu);
vlapic_apicv_inject_pir(vlapic);
}
/* SDM Vol 3 - table 6-2, inject high priority exception before
* maskable hardware interrupt */
if (vcpu_inject_hi_exception(vcpu) == 0) {
/* inject NMI before maskable hardware interrupt */
if (bitmap_test_and_clear_lock(ACRN_REQUEST_NMI, pending_req_bits)) {
/* Inject NMI vector = 2 */
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
VMX_INT_INFO_VALID | (VMX_INT_TYPE_NMI << 8U) | IDT_NMI);
} else {
ret = acrn_inject_pending_vector(vcpu, pending_req_bits);
}
}
}
/* SDM Vol3 table 6-2, inject lowpri exception */
if (vcpu_inject_lo_exception(vcpu) != 0) {
goto INTR_WIN;
}
INTR_WIN:
/*
* If "virtual-interrupt delivered" is enabled, CPU will evaluate
* and automatic inject the virtual interrupts in appropriate time.
@ -534,6 +491,53 @@ INTR_WIN:
return ret;
}
static inline int32_t acrn_inject_pending_vector(struct acrn_vcpu *vcpu, uint64_t *pending_req_bits)
{
int32_t ret = 0;
struct acrn_vcpu_arch * arch = &vcpu->arch;
/* handling pending vector injection:
* there are many reason inject failed, we need re-inject again
* here should take care
* - SW exception (not maskable by IF)
* - external interrupt, if IF clear, will keep in IDT_VEC_INFO_FIELD
* at next vm exit?
*/
if ((arch->idt_vectoring_info & VMX_INT_INFO_VALID) != 0U) {
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
arch->idt_vectoring_info);
} else {
/* Guest interruptable or not */
if (is_guest_irq_enabled(vcpu)) {
/* Inject external interrupt first */
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EXTINT, pending_req_bits)) {
/* has pending external interrupts */
ret = vcpu_do_pending_extint(vcpu);
} else {
/*
* For "virtual-interrupt delivery" disabled case, if
* the virtual interrupt injection conditions are satified,
* then inject through vmcs.
*/
if ((!is_apicv_intr_delivery_supported()) &&
(bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT,
pending_req_bits))) {
ret = vcpu_inject_vlapic_int(vcpu);
}
}
} else {
/* SDM Vol3 table 6-2, inject lowpri exception */
ret = vcpu_inject_lo_exception(vcpu);
if (ret != 0) {
ret = 0;
}
}
}
return ret;
}
void cancel_event_injection(struct acrn_vcpu *vcpu)
{
uint32_t intinfo;