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:
Yin Fengwei 2018-02-28 19:33:13 +08:00 committed by Jack Ren
parent c8d2cdccda
commit 189329e0de
4 changed files with 48 additions and 0 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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 */