direct-io.hg

changeset 14594:faf0a055aa92

hvm: Clean up intr_assist() functions (both VMX and SVM,. but mainly
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 */