|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v1.1 2/3] xen/sched: fix theoretical races accessing vcpu->dirty_cpu
On 30.04.2020 17:28, Juergen Gross wrote:
> The dirty_cpu field of struct vcpu denotes which cpu still holds data
> of a vcpu. All accesses to this field should be atomic in case the
> vcpu could just be running, as it is accessed without any lock held
> in most cases.
>
> There are some instances where accesses are not atomically done, and
> even worse where multiple accesses are done when a single one would
> be mandated.
>
> Correct that in order to avoid potential problems.
Beyond the changes you're making, what about the assignment in
startup_cpu_idle_loop()? And while less important, dump_domains()
also has a use that I think would better be converted for
completeness.
> @@ -1844,6 +1845,7 @@ void context_switch(struct vcpu *prev, struct vcpu
> *next)
> {
> /* Remote CPU calls __sync_local_execstate() from flush IPI handler.
> */
> flush_mask(cpumask_of(dirty_cpu), FLUSH_VCPU_STATE);
> + ASSERT(read_atomic(&next->dirty_cpu) == VCPU_CPU_CLEAN);
ASSERT(!is_vcpu_dirty_cpu(read_atomic(&next->dirty_cpu))) ?
> @@ -1956,13 +1958,17 @@ void sync_local_execstate(void)
>
> void sync_vcpu_execstate(struct vcpu *v)
> {
> - if ( v->dirty_cpu == smp_processor_id() )
> + unsigned int dirty_cpu = read_atomic(&v->dirty_cpu);
> +
> + if ( dirty_cpu == smp_processor_id() )
> sync_local_execstate();
> - else if ( vcpu_cpu_dirty(v) )
> + else if ( is_vcpu_dirty_cpu(dirty_cpu) )
> {
> /* Remote CPU calls __sync_local_execstate() from flush IPI handler.
> */
> - flush_mask(cpumask_of(v->dirty_cpu), FLUSH_VCPU_STATE);
> + flush_mask(cpumask_of(dirty_cpu), FLUSH_VCPU_STATE);
> }
> + ASSERT(read_atomic(&v->dirty_cpu) != dirty_cpu ||
> + dirty_cpu == VCPU_CPU_CLEAN);
!is_vcpu_dirty_cpu(dirty_cpu) again? Also perhaps flip both
sides of the || (to have the cheaper one first), and maybe
if ( is_vcpu_dirty_cpu(dirty_cpu) )
ASSERT(read_atomic(&v->dirty_cpu) != dirty_cpu);
as the longer assertion string literal isn't really of that
much extra value.
However, having stared at it for a while now - is this race
free? I can see this being fine in the (initial) case of
dirty_cpu == smp_processor_id(), but if this is for a foreign
CPU, can't the vCPU have gone back to that same CPU again in
the meantime?
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -844,7 +844,7 @@ static inline bool is_vcpu_dirty_cpu(unsigned int cpu)
>
> static inline bool vcpu_cpu_dirty(const struct vcpu *v)
> {
> - return is_vcpu_dirty_cpu(v->dirty_cpu);
> + return is_vcpu_dirty_cpu(read_atomic((unsigned int *)&v->dirty_cpu));
As per your communication with Julien I understand the cast
will go away again.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |