debuggers.hg
changeset 14632:faf0a055aa92
hvm: Clean up intr_assist() functions (both VMX and SVM,. but mainly
the latter!).
Signed-off-by: Keir Fraser <keir@xensource.com>
the latter!).
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Tue Mar 27 18:51:07 2007 +0100 (2007-03-27) |
parents | 2864754a398f |
children | c489a25c9f9a |
files | xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/intr.c xen/include/asm-x86/hvm/svm/vmcb.h |
line diff
1.1 --- a/xen/arch/x86/hvm/svm/intr.c Tue Mar 27 17:43:36 2007 +0100 1.2 +++ b/xen/arch/x86/hvm/svm/intr.c Tue Mar 27 18:51:07 2007 +0100 1.3 @@ -64,87 +64,61 @@ asmlinkage void svm_intr_assist(void) 1.4 { 1.5 struct vcpu *v = current; 1.6 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; 1.7 - struct periodic_time *pt; 1.8 int intr_type = APIC_DM_EXTINT; 1.9 int intr_vector = -1; 1.10 - int re_injecting = 0; 1.11 1.12 - /* Check if an Injection is active */ 1.13 - /* Previous Interrupt delivery caused this Intercept? */ 1.14 + /* 1.15 + * Previous Interrupt delivery caused this intercept? 1.16 + * This will happen if the injection is latched by the processor (hence 1.17 + * clearing vintr.fields.irq) but then subsequently a fault occurs (e.g., 1.18 + * due to lack of shadow mapping of guest IDT or guest-kernel stack). 1.19 + * 1.20 + * NB. Exceptions that fault during delivery are lost. This needs to be 1.21 + * fixed but we'll usually get away with it since faults are usually 1.22 + * idempotent. But this isn't the case for e.g. software interrupts! 1.23 + */ 1.24 if ( vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0) ) 1.25 { 1.26 - v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector; 1.27 + intr_vector = vmcb->exitintinfo.fields.vector; 1.28 vmcb->exitintinfo.bytes = 0; 1.29 - re_injecting = 1; 1.30 + HVMTRACE_1D(REINJ_VIRQ, v, intr_vector); 1.31 + svm_inject_extint(v, intr_vector); 1.32 + return; 1.33 } 1.34 1.35 - /* Previous interrupt still pending? */ 1.36 + /* 1.37 + * Previous interrupt still pending? This occurs if we return from VMRUN 1.38 + * very early in the entry-to-guest process. Usually this is because an 1.39 + * external physical interrupt was pending when we executed VMRUN. 1.40 + */ 1.41 if ( vmcb->vintr.fields.irq ) 1.42 - { 1.43 - intr_vector = vmcb->vintr.fields.vector; 1.44 - vmcb->vintr.bytes = 0; 1.45 - re_injecting = 1; 1.46 - } 1.47 - /* Pending IRQ saved at last VMExit? */ 1.48 - else if ( v->arch.hvm_svm.saved_irq_vector >= 0 ) 1.49 - { 1.50 - intr_vector = v->arch.hvm_svm.saved_irq_vector; 1.51 - v->arch.hvm_svm.saved_irq_vector = -1; 1.52 - re_injecting = 1; 1.53 - } 1.54 - /* Now let's check for newer interrrupts */ 1.55 - else 1.56 - { 1.57 - pt_update_irq(v); 1.58 + return; 1.59 1.60 - hvm_set_callback_irq_level(); 1.61 + /* Crank the handle on interrupt state and check for new interrrupts. */ 1.62 + pt_update_irq(v); 1.63 + hvm_set_callback_irq_level(); 1.64 + if ( !cpu_has_pending_irq(v) ) 1.65 + return; 1.66 1.67 - if ( cpu_has_pending_irq(v) ) 1.68 - { 1.69 - /* 1.70 - * Create a 'fake' virtual interrupt on to intercept as soon 1.71 - * as the guest _can_ take interrupts. Do not obtain the next 1.72 - * interrupt from the vlapic/pic if unable to inject. 1.73 - */ 1.74 - if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow ) 1.75 - { 1.76 - vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; 1.77 - HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1); 1.78 - svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */ 1.79 - return; 1.80 - } 1.81 - intr_vector = cpu_get_interrupt(v, &intr_type); 1.82 - } 1.83 + /* 1.84 + * Create a 'fake' virtual interrupt on to intercept as soon as the 1.85 + * guest _can_ take interrupts. Do not obtain the next interrupt from 1.86 + * the vlapic/pic if unable to inject. 1.87 + */ 1.88 + if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow ) 1.89 + { 1.90 + vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; 1.91 + HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1); 1.92 + svm_inject_extint(v, 0x0); /* actual vector doesn't matter */ 1.93 + return; 1.94 } 1.95 1.96 - /* have we got an interrupt to inject? */ 1.97 - if ( intr_vector < 0 ) 1.98 - return; 1.99 + /* Okay, we can deliver the interrupt: grab it and update PIC state. */ 1.100 + intr_vector = cpu_get_interrupt(v, &intr_type); 1.101 + BUG_ON(intr_vector < 0); 1.102 1.103 - switch ( intr_type ) 1.104 - { 1.105 - case APIC_DM_EXTINT: 1.106 - case APIC_DM_FIXED: 1.107 - case APIC_DM_LOWEST: 1.108 - /* Re-injecting a PIT interruptt? */ 1.109 - if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) ) 1.110 - ++pt->pending_intr_nr; 1.111 - /* let's inject this interrupt */ 1.112 - if (re_injecting) 1.113 - HVMTRACE_1D(REINJ_VIRQ, v, intr_vector); 1.114 - else 1.115 - HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0); 1.116 - svm_inject_extint(v, intr_vector); 1.117 - break; 1.118 - case APIC_DM_SMI: 1.119 - case APIC_DM_NMI: 1.120 - case APIC_DM_INIT: 1.121 - case APIC_DM_STARTUP: 1.122 - default: 1.123 - printk("Unsupported interrupt type: %d\n", intr_type); 1.124 - BUG(); 1.125 - break; 1.126 - } 1.127 + HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0); 1.128 + svm_inject_extint(v, intr_vector); 1.129 1.130 pt_intr_post(v, intr_vector, intr_type); 1.131 }
2.1 --- a/xen/arch/x86/hvm/svm/svm.c Tue Mar 27 17:43:36 2007 +0100 2.2 +++ b/xen/arch/x86/hvm/svm/svm.c Tue Mar 27 18:51:07 2007 +0100 2.3 @@ -963,8 +963,6 @@ static int svm_vcpu_initialise(struct vc 2.4 v->arch.ctxt_switch_from = svm_ctxt_switch_from; 2.5 v->arch.ctxt_switch_to = svm_ctxt_switch_to; 2.6 2.7 - v->arch.hvm_svm.saved_irq_vector = -1; 2.8 - 2.9 v->arch.hvm_svm.launch_core = -1; 2.10 2.11 if ( (rc = svm_create_vmcb(v)) != 0 )
3.1 --- a/xen/arch/x86/hvm/vmx/intr.c Tue Mar 27 17:43:36 2007 +0100 3.2 +++ b/xen/arch/x86/hvm/vmx/intr.c Tue Mar 27 18:51:07 2007 +0100 3.3 @@ -89,7 +89,7 @@ static void update_tpr_threshold(struct 3.4 asmlinkage void vmx_intr_assist(void) 3.5 { 3.6 int intr_type = 0; 3.7 - int highest_vector; 3.8 + int intr_vector; 3.9 unsigned long eflags; 3.10 struct vcpu *v = current; 3.11 unsigned int idtv_info_field; 3.12 @@ -106,8 +106,9 @@ asmlinkage void vmx_intr_assist(void) 3.13 3.14 if ( unlikely(v->arch.hvm_vmx.vector_injected) ) 3.15 { 3.16 - v->arch.hvm_vmx.vector_injected=0; 3.17 - if (unlikely(has_ext_irq)) enable_irq_window(v); 3.18 + v->arch.hvm_vmx.vector_injected = 0; 3.19 + if ( unlikely(has_ext_irq) ) 3.20 + enable_irq_window(v); 3.21 return; 3.22 } 3.23 3.24 @@ -132,7 +133,6 @@ asmlinkage void vmx_intr_assist(void) 3.25 enable_irq_window(v); 3.26 3.27 HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field); 3.28 - 3.29 return; 3.30 } 3.31 3.32 @@ -154,30 +154,13 @@ asmlinkage void vmx_intr_assist(void) 3.33 return; 3.34 } 3.35 3.36 - highest_vector = cpu_get_interrupt(v, &intr_type); 3.37 - if ( highest_vector < 0 ) 3.38 - return; 3.39 + intr_vector = cpu_get_interrupt(v, &intr_type); 3.40 + BUG_ON(intr_vector < 0); 3.41 3.42 - switch ( intr_type ) 3.43 - { 3.44 - case APIC_DM_EXTINT: 3.45 - case APIC_DM_FIXED: 3.46 - case APIC_DM_LOWEST: 3.47 - HVMTRACE_2D(INJ_VIRQ, v, highest_vector, /*fake=*/ 0); 3.48 - vmx_inject_extint(v, highest_vector, VMX_DELIVER_NO_ERROR_CODE); 3.49 - break; 3.50 + HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0); 3.51 + vmx_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE); 3.52 3.53 - case APIC_DM_SMI: 3.54 - case APIC_DM_NMI: 3.55 - case APIC_DM_INIT: 3.56 - case APIC_DM_STARTUP: 3.57 - default: 3.58 - printk("Unsupported interrupt type\n"); 3.59 - BUG(); 3.60 - break; 3.61 - } 3.62 - 3.63 - pt_intr_post(v, highest_vector, intr_type); 3.64 + pt_intr_post(v, intr_vector, intr_type); 3.65 } 3.66 3.67 /*
4.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 27 17:43:36 2007 +0100 4.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 27 18:51:07 2007 +0100 4.3 @@ -446,7 +446,6 @@ struct arch_svm_struct { 4.4 u64 vmcb_pa; 4.5 u32 *msrpm; 4.6 u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */ 4.7 - int saved_irq_vector; 4.8 int launch_core; 4.9 4.10 unsigned long flags; /* VMCB flags */