[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [v3 14/15] Update Posted-Interrupts Descriptor during vCPU scheduling



>>> On 24.06.15 at 07:18, <feng.wu@xxxxxxxxx> wrote:
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -6475,6 +6475,12 @@ enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v)
>      return hvm_funcs.nhvm_intr_blocked(v);
>  }
>  
> +void arch_pi_desc_update(struct vcpu *v, int old_state)
> +{
> +    if ( is_hvm_vcpu(v) && hvm_funcs.pi_desc_update )
> +        hvm_funcs.pi_desc_update(v, old_state);
> +}

Shouldn't this use has_hvm_container_vcpu()?

> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -168,6 +168,7 @@ static int vmx_vcpu_initialise(struct vcpu *v)
>  
>      INIT_LIST_HEAD(&v->arch.hvm_vmx.pi_blocked_vcpu_list);
>  
> +    v->arch.hvm_vmx.pi_block_cpu = -1;

The field should be of unsigned type, at which point it might be better
(but isn't required) to store NR_CPUS here (and below), and check
against that value further down.

> @@ -1778,6 +1779,124 @@ static void vmx_handle_eoi(u8 vector)
>      __vmwrite(GUEST_INTR_STATUS, status);
>  }
>  
> +static void vmx_pi_desc_update(struct vcpu *v, int old_state)
> +{
> +    struct pi_desc *pi_desc = &v->arch.hvm_vmx.pi_desc;
> +    struct pi_desc old, new;
> +    unsigned long flags;
> +
> +    ASSERT(iommu_intpost);
> +
> +    switch ( v->runstate.state )
> +    {
> +    case RUNSTATE_runnable:
> +    case RUNSTATE_offline:
> +        /*
> +         * We don't need to send notification event to a non-running
> +         * vcpu, the interrupt information will be delivered to it before
> +         * VM-ENTRY when the vcpu is scheduled to run next time.
> +         */
> +        pi_set_sn(pi_desc);
> +
> +        /*
> +         * If the state is transferred from RUNSTATE_blocked,
> +         * we should set 'NV' feild back to posted_intr_vector,
> +         * so the Posted-Interrupts can be delivered to the vCPU
> +         * by VT-d HW after it is scheduled to run.
> +         */
> +        if ( old_state == RUNSTATE_blocked )
> +        {
> +            write_atomic((uint8_t*)&new.nv, posted_intr_vector);
> +
> +            /*
> +             * Delete the vCPU from the related block list
> +             * if we are resuming from blocked state
> +             */
> +            ASSERT(v->arch.hvm_vmx.pi_block_cpu != -1);
> +            spin_lock_irqsave(&per_cpu(pi_blocked_vcpu_lock,
> +                              v->arch.hvm_vmx.pi_block_cpu), flags);
> +            list_del(&v->arch.hvm_vmx.pi_blocked_vcpu_list);
> +            spin_unlock_irqrestore(&per_cpu(pi_blocked_vcpu_lock,
> +                                   v->arch.hvm_vmx.pi_block_cpu), flags);
> +            v->arch.hvm_vmx.pi_block_cpu = -1;
> +        }
> +        break;
> +
> +    case RUNSTATE_blocked:
> +        ASSERT(v->arch.hvm_vmx.pi_block_cpu == -1);
> +
> +        /*
> +         * The vCPU is blocked on the block list. Add the blocked
> +         * vCPU on the list of the v->arch.hvm_vmx.pi_block_cpu,
> +         * which is the destination of the wake-up notification event.
> +         */
> +        v->arch.hvm_vmx.pi_block_cpu = v->processor;
> +        spin_lock_irqsave(&per_cpu(pi_blocked_vcpu_lock,
> +                          v->arch.hvm_vmx.pi_block_cpu), flags);
> +        list_add_tail(&v->arch.hvm_vmx.pi_blocked_vcpu_list,
> +                      &per_cpu(pi_blocked_vcpu, 
> v->arch.hvm_vmx.pi_block_cpu));
> +        spin_unlock_irqrestore(&per_cpu(pi_blocked_vcpu_lock,
> +                               v->arch.hvm_vmx.pi_block_cpu), flags);
> +
> +        do {
> +            old.control = new.control = pi_desc->control;
> +
> +            /*
> +             * We should not block the vCPU if
> +             * an interrupt was posted for it.
> +             */
> +
> +            if ( old.on )
> +            {
> +                /*
> +                 * The vCPU will be removed from the block list
> +                 * during its state transferring from RUNSTATE_blocked
> +                 * to RUNSTATE_runnable after the following tasklet
> +                 * is executed.
> +                 */
> +                tasklet_schedule(&v->arch.hvm_vmx.pi_vcpu_wakeup_tasklet);
> +                return;

"break" here has the same effect and looks better overall (single
function return point).

> +            }
> +
> +            /*
> +             * Change the 'NDST' field to v->arch.hvm_vmx.pi_block_cpu,
> +             * so when external interrupts from assigned deivces happen,
> +             * wakeup notifiction event will go to
> +             * v->arch.hvm_vmx.pi_block_cpu, then in pi_wakeup_interrupt()
> +             * we can find the vCPU in the right list to wake up.
> +             */
> +            if ( x2apic_enabled )
> +                new.ndst = cpu_physical_id(v->arch.hvm_vmx.pi_block_cpu);
> +            else
> +                new.ndst = MASK_INSR(cpu_physical_id(
> +                                     v->arch.hvm_vmx.pi_block_cpu),
> +                                     PI_xAPIC_NDST_MASK);

This isn't the first time I see this - please add a helper inline function.

> +            new.sn = 0;
> +            new.nv = pi_wakeup_vector;
> +        } while ( cmpxchg(&pi_desc->control, old.control, new.control)
> +                  != old.control );
> +        break;
> +
> +    case RUNSTATE_running:
> +        ASSERT( pi_desc->sn == 1 );

Stray blanks.

> +        if ( x2apic_enabled )
> +            write_atomic(&new.ndst, cpu_physical_id(v->processor));
> +        else
> +            write_atomic(&new.ndst,
> +                         MASK_INSR(cpu_physical_id(v->processor),
> +                         PI_xAPIC_NDST_MASK));

Ah, another use case for that helper...

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.