mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[HVM][SVM] Modify the interrupt/event injection logic.
Resolves performance issues concerning AMD-V virtual interrupt/event injection: - Remove extra VINTRs vmexits, and only setup fake interrupt if intr pending. - Allow both event injection and interrupt injection concurrently in vmcb. Signed-off-by: Tom Woller <thomas.woller@amd.com>
This commit is contained in:
1 parent
db6dca73cd
commit
625141e5d7
3 files changed
+14
-25
No files matched your search
+13
-20
@@ -78,26 +78,6 @@ asmlinkage void svm_intr_assist(void)
|
||||
re_injecting = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If event requires injecting then do not inject int.
|
||||
*/
|
||||
if ( unlikely(v->arch.hvm_svm.inject_event) )
|
||||
{
|
||||
v->arch.hvm_svm.inject_event = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a 'fake' virtual interrupt on to intercept as soon
|
||||
* as the guest _can_ take interrupts.
|
||||
*/
|
||||
if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )
|
||||
{
|
||||
vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
|
||||
svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Previous interrupt still pending? */
|
||||
if ( vmcb->vintr.fields.irq )
|
||||
{
|
||||
@@ -124,7 +104,20 @@ asmlinkage void svm_intr_assist(void)
|
||||
hvm_set_callback_irq_level();
|
||||
|
||||
if ( cpu_has_pending_irq(v) )
|
||||
{
|
||||
/*
|
||||
* Create a 'fake' virtual interrupt on to intercept as soon
|
||||
* as the guest _can_ take interrupts. Do not obtain the next
|
||||
* interrupt from the vlapic/pic if unable to inject.
|
||||
*/
|
||||
if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )
|
||||
{
|
||||
vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
|
||||
svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
|
||||
return;
|
||||
}
|
||||
intr_vector = cpu_get_interrupt(v, &intr_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* have we got an interrupt to inject? */
|
||||
|
||||
@@ -191,7 +191,6 @@ static inline void svm_inject_exception(struct vcpu *v, int trap,
|
||||
ASSERT(vmcb->eventinj.fields.v == 0);
|
||||
|
||||
vmcb->eventinj = event;
|
||||
v->arch.hvm_svm.inject_event=1;
|
||||
}
|
||||
|
||||
static void stop_svm(void)
|
||||
@@ -2564,8 +2563,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
|
||||
exit_reason = vmcb->exitcode;
|
||||
save_svm_cpu_user_regs(v, regs);
|
||||
|
||||
v->arch.hvm_svm.inject_event = 0;
|
||||
|
||||
if (exit_reason == VMEXIT_INVALID)
|
||||
{
|
||||
svm_dump_vmcb(__func__, vmcb);
|
||||
@@ -2933,7 +2930,7 @@ asmlinkage void svm_asid(void)
|
||||
clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -456,7 +456,6 @@ struct arch_svm_struct {
|
||||
u32 *msrpm;
|
||||
u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
|
||||
int saved_irq_vector;
|
||||
u32 inject_event;
|
||||
u32 launch_core;
|
||||
u32 asid_core;
|
||||
|
||||
|
||||