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

Re: [Xen-devel] [PATCH] x86: correct vCPU dirty CPU handling



Hello,
I still had to apply the patch below with 4.11rc4 for NetBSD.
Any chance to get it in the 4.11 branch before release ?

On Thu, Apr 26, 2018 at 03:41:20AM -0600, Jan Beulich wrote:
> Commit df8234fd2c ("replace vCPU's dirty CPU mask by numeric ID") was
> too lax in two respects: First of all it didn't consider the case of a
> vCPU not having a valid dirty CPU in the descriptor table TLB flush
> case. This is the issue Manual has run into with NetBSD.
> 
> Additionally reads of ->dirty_cpu for other than the current vCPU are at
> risk of racing with scheduler actions, i.e. single atomic reads need to
> be used there. Obviously the non-init write sites then better also use
> atomic writes.
> 
> Having to touch the descriptor table TLB flush code here anyway, take
> the opportunity and switch it to be at most one flush_tlb_mask()
> invocation.
> 
> Reported-by: Manuel Bouyer <bouyer@xxxxxxxxxxxxxxx>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> 
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1631,7 +1631,7 @@ static void __context_switch(void)
>       */
>      if ( pd != nd )
>          cpumask_set_cpu(cpu, nd->dirty_cpumask);
> -    n->dirty_cpu = cpu;
> +    write_atomic(&n->dirty_cpu, cpu);
>  
>      if ( !is_idle_domain(nd) )
>      {
> @@ -1687,7 +1687,7 @@ static void __context_switch(void)
>  
>      if ( pd != nd )
>          cpumask_clear_cpu(cpu, pd->dirty_cpumask);
> -    p->dirty_cpu = VCPU_CPU_CLEAN;
> +    write_atomic(&p->dirty_cpu, VCPU_CPU_CLEAN);
>  
>      per_cpu(curr_vcpu, cpu) = n;
>  }
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -1202,11 +1202,23 @@ void put_page_from_l1e(l1_pgentry_t l1e,
>               unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) &&
>               (l1e_owner == pg_owner) )
>          {
> +            cpumask_t *mask = this_cpu(scratch_cpumask);
> +
> +            cpumask_clear(mask);
> +
>              for_each_vcpu ( pg_owner, v )
>              {
> -                if ( pv_destroy_ldt(v) )
> -                    flush_tlb_mask(cpumask_of(v->dirty_cpu));
> +                unsigned int cpu;
> +
> +                if ( !pv_destroy_ldt(v) )
> +                    continue;
> +                cpu = read_atomic(&v->dirty_cpu);
> +                if ( is_vcpu_dirty_cpu(cpu) )
> +                    __cpumask_set_cpu(cpu, mask);
>              }
> +
> +            if ( !cpumask_empty(mask) )
> +                flush_tlb_mask(mask);
>          }
>          put_page(page);
>      }
> @@ -2979,13 +2991,18 @@ static inline int vcpumask_to_pcpumask(
>  
>          while ( vmask )
>          {
> +            unsigned int cpu;
> +
>              vcpu_id = find_first_set_bit(vmask);
>              vmask &= ~(1UL << vcpu_id);
>              vcpu_id += vcpu_bias;
>              if ( (vcpu_id >= d->max_vcpus) )
>                  return 0;
> -            if ( ((v = d->vcpu[vcpu_id]) != NULL) && vcpu_cpu_dirty(v) )
> -                __cpumask_set_cpu(v->dirty_cpu, pmask);
> +            if ( (v = d->vcpu[vcpu_id]) == NULL )
> +                continue;
> +            cpu = read_atomic(&v->dirty_cpu);
> +            if ( is_vcpu_dirty_cpu(cpu) )
> +                __cpumask_set_cpu(cpu, pmask);
>          }
>      }
>  }
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -795,10 +795,15 @@ static inline int vcpu_runnable(struct v
>               atomic_read(&v->domain->pause_count));
>  }
>  
> -static inline bool vcpu_cpu_dirty(const struct vcpu *v)
> +static inline bool is_vcpu_dirty_cpu(unsigned int cpu)
>  {
>      BUILD_BUG_ON(NR_CPUS >= VCPU_CPU_CLEAN);
> -    return v->dirty_cpu != VCPU_CPU_CLEAN;
> +    return cpu != VCPU_CPU_CLEAN;
> +}
> +
> +static inline bool vcpu_cpu_dirty(const struct vcpu *v)
> +{
> +    return is_vcpu_dirty_cpu(v->dirty_cpu);
>  }
>  
>  void vcpu_block(void);
> 
> 
> 
-- 
Manuel Bouyer <bouyer@xxxxxxxxxxxxxxx>
     NetBSD: 26 ans d'experience feront toujours la difference
--

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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