# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1175017867 -3600
# Node ID faf0a055aa92c5967e8ef2e3dc2bb04afe5d75ba
# Parent 2864754a398f3defeaad0494b8b6c23f82a1417d
hvm: Clean up intr_assist() functions (both VMX and SVM,. but mainly
the latter!).
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/svm/intr.c | 110 ++++++++++++++-----------------------
xen/arch/x86/hvm/svm/svm.c | 2
xen/arch/x86/hvm/vmx/intr.c | 35 +++--------
xen/include/asm-x86/hvm/svm/vmcb.h | 1
4 files changed, 51 insertions(+), 97 deletions(-)
diff -r 2864754a398f -r faf0a055aa92 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c Tue Mar 27 17:43:36 2007 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c Tue Mar 27 18:51:07 2007 +0100
@@ -64,87 +64,61 @@ asmlinkage void svm_intr_assist(void)
{
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- struct periodic_time *pt;
int intr_type = APIC_DM_EXTINT;
int intr_vector = -1;
- int re_injecting = 0;
- /* Check if an Injection is active */
- /* Previous Interrupt delivery caused this Intercept? */
+ /*
+ * Previous Interrupt delivery caused this intercept?
+ * This will happen if the injection is latched by the processor (hence
+ * clearing vintr.fields.irq) but then subsequently a fault occurs (e.g.,
+ * due to lack of shadow mapping of guest IDT or guest-kernel stack).
+ *
+ * NB. Exceptions that fault during delivery are lost. This needs to be
+ * fixed but we'll usually get away with it since faults are usually
+ * idempotent. But this isn't the case for e.g. software interrupts!
+ */
if ( vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0) )
{
- v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
+ intr_vector = vmcb->exitintinfo.fields.vector;
vmcb->exitintinfo.bytes = 0;
- re_injecting = 1;
+ HVMTRACE_1D(REINJ_VIRQ, v, intr_vector);
+ svm_inject_extint(v, intr_vector);
+ return;
}
- /* Previous interrupt still pending? */
+ /*
+ * Previous interrupt still pending? This occurs if we return from VMRUN
+ * very early in the entry-to-guest process. Usually this is because an
+ * external physical interrupt was pending when we executed VMRUN.
+ */
if ( vmcb->vintr.fields.irq )
+ return;
+
+ /* Crank the handle on interrupt state and check for new interrrupts. */
+ pt_update_irq(v);
+ hvm_set_callback_irq_level();
+ if ( !cpu_has_pending_irq(v) )
+ return;
+
+ /*
+ * 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 )
{
- intr_vector = vmcb->vintr.fields.vector;
- vmcb->vintr.bytes = 0;
- re_injecting = 1;
- }
- /* Pending IRQ saved at last VMExit? */
- else if ( v->arch.hvm_svm.saved_irq_vector >= 0 )
- {
- intr_vector = v->arch.hvm_svm.saved_irq_vector;
- v->arch.hvm_svm.saved_irq_vector = -1;
- re_injecting = 1;
- }
- /* Now let's check for newer interrrupts */
- else
- {
- pt_update_irq(v);
-
- 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;
- HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
- svm_inject_extint(v, 0x0); /* actual vector doesn't really
matter */
- return;
- }
- intr_vector = cpu_get_interrupt(v, &intr_type);
- }
+ vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+ HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
+ svm_inject_extint(v, 0x0); /* actual vector doesn't matter */
+ return;
}
- /* have we got an interrupt to inject? */
- if ( intr_vector < 0 )
- return;
+ /* Okay, we can deliver the interrupt: grab it and update PIC state. */
+ intr_vector = cpu_get_interrupt(v, &intr_type);
+ BUG_ON(intr_vector < 0);
- switch ( intr_type )
- {
- case APIC_DM_EXTINT:
- case APIC_DM_FIXED:
- case APIC_DM_LOWEST:
- /* Re-injecting a PIT interruptt? */
- if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) )
- ++pt->pending_intr_nr;
- /* let's inject this interrupt */
- if (re_injecting)
- HVMTRACE_1D(REINJ_VIRQ, v, intr_vector);
- else
- HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
- svm_inject_extint(v, intr_vector);
- break;
- case APIC_DM_SMI:
- case APIC_DM_NMI:
- case APIC_DM_INIT:
- case APIC_DM_STARTUP:
- default:
- printk("Unsupported interrupt type: %d\n", intr_type);
- BUG();
- break;
- }
+ HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
+ svm_inject_extint(v, intr_vector);
pt_intr_post(v, intr_vector, intr_type);
}
diff -r 2864754a398f -r faf0a055aa92 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Tue Mar 27 17:43:36 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c Tue Mar 27 18:51:07 2007 +0100
@@ -962,8 +962,6 @@ static int svm_vcpu_initialise(struct vc
v->arch.schedule_tail = arch_svm_do_resume;
v->arch.ctxt_switch_from = svm_ctxt_switch_from;
v->arch.ctxt_switch_to = svm_ctxt_switch_to;
-
- v->arch.hvm_svm.saved_irq_vector = -1;
v->arch.hvm_svm.launch_core = -1;
diff -r 2864754a398f -r faf0a055aa92 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c Tue Mar 27 17:43:36 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c Tue Mar 27 18:51:07 2007 +0100
@@ -89,7 +89,7 @@ asmlinkage void vmx_intr_assist(void)
asmlinkage void vmx_intr_assist(void)
{
int intr_type = 0;
- int highest_vector;
+ int intr_vector;
unsigned long eflags;
struct vcpu *v = current;
unsigned int idtv_info_field;
@@ -106,8 +106,9 @@ asmlinkage void vmx_intr_assist(void)
if ( unlikely(v->arch.hvm_vmx.vector_injected) )
{
- v->arch.hvm_vmx.vector_injected=0;
- if (unlikely(has_ext_irq)) enable_irq_window(v);
+ v->arch.hvm_vmx.vector_injected = 0;
+ if ( unlikely(has_ext_irq) )
+ enable_irq_window(v);
return;
}
@@ -132,7 +133,6 @@ asmlinkage void vmx_intr_assist(void)
enable_irq_window(v);
HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
-
return;
}
@@ -154,30 +154,13 @@ asmlinkage void vmx_intr_assist(void)
return;
}
- highest_vector = cpu_get_interrupt(v, &intr_type);
- if ( highest_vector < 0 )
- return;
+ intr_vector = cpu_get_interrupt(v, &intr_type);
+ BUG_ON(intr_vector < 0);
- switch ( intr_type )
- {
- case APIC_DM_EXTINT:
- case APIC_DM_FIXED:
- case APIC_DM_LOWEST:
- HVMTRACE_2D(INJ_VIRQ, v, highest_vector, /*fake=*/ 0);
- vmx_inject_extint(v, highest_vector, VMX_DELIVER_NO_ERROR_CODE);
- break;
+ HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
+ vmx_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
- case APIC_DM_SMI:
- case APIC_DM_NMI:
- case APIC_DM_INIT:
- case APIC_DM_STARTUP:
- default:
- printk("Unsupported interrupt type\n");
- BUG();
- break;
- }
-
- pt_intr_post(v, highest_vector, intr_type);
+ pt_intr_post(v, intr_vector, intr_type);
}
/*
diff -r 2864754a398f -r faf0a055aa92 xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 27 17:43:36 2007 +0100
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 27 18:51:07 2007 +0100
@@ -446,7 +446,6 @@ struct arch_svm_struct {
u64 vmcb_pa;
u32 *msrpm;
u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
- int saved_irq_vector;
int launch_core;
unsigned long flags; /* VMCB flags */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|