|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |