|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v12 1/2] vmx: VT-d posted-interrupt core logic handling
>>> On 19.02.16 at 02:55, <feng.wu@xxxxxxxxx> wrote:
> +static void vmx_vcpu_block(struct vcpu *v)
> +{
> + unsigned long flags;
> + unsigned int dest;
> + spinlock_t *old_lock;
> + spinlock_t *pi_block_list_lock =
> + &per_cpu(pi_blocked_vcpu_lock, v->processor);
> + struct pi_desc *pi_desc = &v->arch.hvm_vmx.pi_desc;
> +
> + spin_lock_irqsave(pi_block_list_lock, flags);
> + old_lock = cmpxchg(&v->arch.hvm_vmx.pi_block_list_lock, NULL,
> + &per_cpu(pi_blocked_vcpu_lock, v->processor));
Why don't you use the local variable here?
> + /*
> + * 'v->arch.hvm_vmx.pi_block_list_lock' should be NULL before being
> assigned
> + * to a new value, since the vCPU is currently running and it cannot be
> on
> + * any blocking list.
> + */
> + ASSERT(old_lock == NULL);
> +
> + list_add_tail(&v->arch.hvm_vmx.pi_blocked_vcpu_list,
> + &per_cpu(pi_blocked_vcpu, v->processor));
> + spin_unlock_irqrestore(pi_block_list_lock, flags);
> +
> + ASSERT(!pi_test_sn(pi_desc));
> +
> + dest = cpu_physical_id(v->processor);
> +
> + ASSERT(pi_desc->ndst ==
> + (x2apic_enabled ? dest : MASK_INSR(dest, PI_xAPIC_NDST_MASK)));
May I ask for consistency between this and ...
> +static void vmx_pi_switch_to(struct vcpu *v)
> +{
> + struct pi_desc *pi_desc = &v->arch.hvm_vmx.pi_desc;
> +
> + write_atomic(&pi_desc->ndst, x2apic_enabled ?
> + cpu_physical_id(v->processor) :
> + MASK_INSR(cpu_physical_id(v->processor),
> PI_xAPIC_NDST_MASK));
... this? I.e. to either in both cases use a local variable "dest", or
in both cases to avoid doing so?
> +static void vmx_pi_do_resume(struct vcpu *v)
> +{
> + unsigned long flags;
> + spinlock_t *pi_block_list_lock;
> + struct pi_desc *pi_desc = &v->arch.hvm_vmx.pi_desc;
> +
> + ASSERT(!test_bit(_VPF_blocked, &v->pause_flags));
> +
> + /*
> + * Set 'NV' field back to posted_intr_vector, so the
> + * Posted-Interrupts can be delivered to the vCPU when
> + * it is running in non-root mode.
> + */
> + write_atomic(&pi_desc->nv, posted_intr_vector);
> +
> + /* The vCPU is not on any blocking list. */
> + pi_block_list_lock = v->arch.hvm_vmx.pi_block_list_lock;
> + if ( pi_block_list_lock == NULL )
> + return;
> +
> + /* Prevent the compiler from eliminating the local variable.*/
> + barrier();
As said before - this is too late: This way you still don't guarantee
pi_block_list_lock != NULL. The barrier needs to be after the read,
and _before_ the first use. Also I think the right barrier here
would be smp_rmb().
> + spin_lock_irqsave(pi_block_list_lock, flags);
> +
> + /*
> + * v->arch.hvm_vmx.pi_block_list_lock == NULL here means the vCPU was
> + * removed from the blocking list while we are acquiring the lock.
> + */
> + if ( v->arch.hvm_vmx.pi_block_list_lock != NULL )
> + {
ASSERT(v->arch.hvm_vmx.pi_block_list_lock == pi_block_list_lock)?
> +/* This function is called when pcidevs_lock is held */
> +void vmx_pi_hooks_assign(struct domain *target)
> +{
> + if ( !iommu_intpost )
> + return;
> +
> + if ( has_hvm_container_domain(target) &&
> + !target->arch.hvm_domain.vmx.vcpu_block )
> + {
> + target->arch.hvm_domain.vmx.vcpu_block = vmx_vcpu_block;
> + target->arch.hvm_domain.vmx.pi_switch_from = vmx_pi_switch_from;
> + target->arch.hvm_domain.vmx.pi_switch_to = vmx_pi_switch_to;
> + target->arch.hvm_domain.vmx.pi_do_resume = vmx_pi_do_resume;
> + }
> +}
> +
> +/* This function is called when pcidevs_lock is held */
> +void vmx_pi_hooks_deassign(struct domain *source)
> +{
> + if ( !iommu_intpost )
> + return;
> +
> + if ( has_hvm_container_domain(source) &&
> + source->arch.hvm_domain.vmx.vcpu_block && !has_arch_pdevs(source) )
> + {
I think it would be nice for the conditions in both functions to match
up. Since you can't add has_arch_pdevs(target) to the earlier, maybe
it should be the caller of the latter to check !has_arch_pdevs(source)?
And if you then made the caller(s) of vmx_pi_hooks_assign() do so
too, the checks on ->arch.hvm_domain.vmx.vcpu_block could
apparently become ASSERT()-s instead.
Also since neither function now takes two domain pointers anymore,
please name the function parameters just "d". And finally please, in
each function, combine the two if()-s.
> @@ -112,6 +251,10 @@ static int vmx_vcpu_initialise(struct vcpu *v)
>
> spin_lock_init(&v->arch.hvm_vmx.vmcs_lock);
>
> + INIT_LIST_HEAD(&v->arch.hvm_vmx.pi_blocked_vcpu_list);
> +
> + v->arch.hvm_vmx.pi_block_list_lock = NULL;
The latter is pointless, as struct vcpu starts out zero-initialized.
> @@ -740,6 +883,8 @@ static void vmx_ctxt_switch_from(struct vcpu *v)
> vmx_save_guest_msrs(v);
> vmx_restore_host_msrs();
> vmx_save_dr(v);
> + if (v->domain->arch.hvm_domain.vmx.pi_switch_from)
> + v->domain->arch.hvm_domain.vmx.pi_switch_from(v);
Coding style.
> @@ -752,6 +897,8 @@ static void vmx_ctxt_switch_to(struct vcpu *v)
>
> vmx_restore_guest_msrs(v);
> vmx_restore_dr(v);
> + if (v->domain->arch.hvm_domain.vmx.pi_switch_to)
> + v->domain->arch.hvm_domain.vmx.pi_switch_to(v);
Again. I'm pretty sure this has been pointed out before. And there
are more of these.
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -565,6 +565,11 @@ const char *hvm_efer_valid(const struct vcpu *v,
> uint64_t value,
> signed int cr0_pg);
> unsigned long hvm_cr4_guest_reserved_bits(const struct vcpu *v, bool_t
> restore);
>
> +#define arch_vcpu_block(v) ({ \
> + if ( (v)->domain->arch.hvm_domain.vmx.vcpu_block ) \
> + (v)->domain->arch.hvm_domain.vmx.vcpu_block((v)); \
> +})
I'd prefer if v got evaluated just once in this macro. Also note
the redundant parentheses in the function argument.
> @@ -160,6 +219,14 @@ struct arch_vmx_struct {
> struct page_info *vmwrite_bitmap;
>
> struct page_info *pml_pg;
> +
> + /*
> + * Before it is blocked, vCPU is added to the per-cpu list.
> + * VT-d engine can send wakeup notification event to the
> + * pCPU and wakeup the related vCPU.
> + */
> + struct list_head pi_blocked_vcpu_list;
> + spinlock_t *pi_block_list_lock;
> };
Didn't we settle on making this a struct with a "list" and a "lock"
member? And along those lines the local per-CPU variables added
to xen/arch/x86/hvm/vmx/vmx.c would also benefit from being
put in a struct, making more obvious their close relationship.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |