apicv: cancel event injection if vcpu is scheduled out
And re-inject the event after vcpu is scheduled in. Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
parent
c8d2cdccda
commit
189329e0de
|
@ -293,6 +293,18 @@ int acrn_do_intr_process(struct vcpu *vcpu)
|
||||||
if (bitmap_test_and_clear(ACRN_REQUEST_TMR_UPDATE, pending_intr_bits))
|
if (bitmap_test_and_clear(ACRN_REQUEST_TMR_UPDATE, pending_intr_bits))
|
||||||
vioapic_update_tmr(vcpu);
|
vioapic_update_tmr(vcpu);
|
||||||
|
|
||||||
|
/* handling cancelled event injection when vcpu is switched out */
|
||||||
|
if (vcpu->arch_vcpu.inject_event_pending) {
|
||||||
|
exec_vmwrite(VMX_ENTRY_EXCEPTION_EC,
|
||||||
|
vcpu->arch_vcpu.inject_info.error_code);
|
||||||
|
|
||||||
|
exec_vmwrite(VMX_ENTRY_INT_INFO_FIELD,
|
||||||
|
vcpu->arch_vcpu.inject_info.intr_info);
|
||||||
|
|
||||||
|
vcpu->arch_vcpu.inject_event_pending = false;
|
||||||
|
goto INTR_WIN;
|
||||||
|
}
|
||||||
|
|
||||||
/* handling pending vector injection:
|
/* handling pending vector injection:
|
||||||
* there are many reason inject failed, we need re-inject again
|
* there are many reason inject failed, we need re-inject again
|
||||||
*/
|
*/
|
||||||
|
@ -380,6 +392,30 @@ INTR_WIN:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cancel_event_injection(struct vcpu *vcpu)
|
||||||
|
{
|
||||||
|
uint32_t intinfo;
|
||||||
|
|
||||||
|
intinfo = exec_vmread(VMX_ENTRY_INT_INFO_FIELD);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If event is injected, we clear VMX_ENTRY_INT_INFO_FIELD,
|
||||||
|
* save injection info, and mark inject event pending.
|
||||||
|
* The event will be re-injected in next acrn_do_intr_process
|
||||||
|
* call.
|
||||||
|
*/
|
||||||
|
if (intinfo & VMX_INT_INFO_VALID) {
|
||||||
|
vcpu->arch_vcpu.inject_event_pending = true;
|
||||||
|
|
||||||
|
if (intinfo & (EXCEPTION_ERROR_CODE_VALID << 8))
|
||||||
|
vcpu->arch_vcpu.inject_info.error_code =
|
||||||
|
exec_vmread(VMX_ENTRY_EXCEPTION_EC);
|
||||||
|
|
||||||
|
vcpu->arch_vcpu.inject_info.intr_info = intinfo;
|
||||||
|
exec_vmwrite(VMX_ENTRY_INT_INFO_FIELD, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int exception_handler(struct vcpu *vcpu)
|
int exception_handler(struct vcpu *vcpu)
|
||||||
{
|
{
|
||||||
uint32_t intinfo, int_err_code;
|
uint32_t intinfo, int_err_code;
|
||||||
|
|
|
@ -147,6 +147,9 @@ static void context_switch_out(struct vcpu *vcpu)
|
||||||
if (vcpu == NULL)
|
if (vcpu == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* cancel event(int, gp, nmi and exception) injection */
|
||||||
|
cancel_event_injection(vcpu);
|
||||||
|
|
||||||
atomic_store_rel_32(&vcpu->running, 0);
|
atomic_store_rel_32(&vcpu->running, 0);
|
||||||
/* do prev vcpu context switch out */
|
/* do prev vcpu context switch out */
|
||||||
/* For now, we don't need to invalid ept.
|
/* For now, we don't need to invalid ept.
|
||||||
|
|
|
@ -185,6 +185,11 @@ struct run_context {
|
||||||
#define NORMAL_WORLD 0
|
#define NORMAL_WORLD 0
|
||||||
#define SECURE_WORLD 1
|
#define SECURE_WORLD 1
|
||||||
|
|
||||||
|
struct event_injection_info {
|
||||||
|
uint32_t intr_info;
|
||||||
|
uint32_t error_code;
|
||||||
|
};
|
||||||
|
|
||||||
struct vcpu_arch {
|
struct vcpu_arch {
|
||||||
int cur_context;
|
int cur_context;
|
||||||
struct run_context contexts[NR_WORLD];
|
struct run_context contexts[NR_WORLD];
|
||||||
|
@ -221,6 +226,8 @@ struct vcpu_arch {
|
||||||
|
|
||||||
/* interrupt injection information */
|
/* interrupt injection information */
|
||||||
uint64_t pending_intr;
|
uint64_t pending_intr;
|
||||||
|
bool inject_event_pending;
|
||||||
|
struct event_injection_info inject_info;
|
||||||
|
|
||||||
/* per vcpu lapic */
|
/* per vcpu lapic */
|
||||||
void *vlapic;
|
void *vlapic;
|
||||||
|
|
|
@ -161,4 +161,6 @@ int interrupt_win_exiting_handler(struct vcpu *vcpu);
|
||||||
int external_interrupt_handler(struct vcpu *vcpu);
|
int external_interrupt_handler(struct vcpu *vcpu);
|
||||||
int acrn_do_intr_process(struct vcpu *vcpu);
|
int acrn_do_intr_process(struct vcpu *vcpu);
|
||||||
int interrupt_init(uint32_t logical_id);
|
int interrupt_init(uint32_t logical_id);
|
||||||
|
|
||||||
|
void cancel_event_injection(struct vcpu *vcpu);
|
||||||
#endif /* IRQ_H */
|
#endif /* IRQ_H */
|
||||||
|
|
Loading…
Reference in New Issue