All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86: correct vCPU dirty CPU handling
@ 2018-04-26  9:41 Jan Beulich
  2018-04-26  9:51 ` Andrew Cooper
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Jan Beulich @ 2018-04-26  9:41 UTC (permalink / raw)
  To: xen-devel; +Cc: Juergen Gross, Andrew Cooper, Manuel Bouyer

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@antioche.eu.org>
Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- 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);




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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-04-26  9:41 [PATCH] x86: correct vCPU dirty CPU handling Jan Beulich
@ 2018-04-26  9:51 ` Andrew Cooper
  2018-04-26 10:52   ` Jan Beulich
  2018-04-26 12:39 ` Manuel Bouyer
  2018-05-22 11:02 ` Manuel Bouyer
  2 siblings, 1 reply; 9+ messages in thread
From: Andrew Cooper @ 2018-04-26  9:51 UTC (permalink / raw)
  To: Jan Beulich, xen-devel; +Cc: Juergen Gross, Manuel Bouyer

On 26/04/18 10:41, Jan Beulich wrote:
> --- 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);

Thinking about this, what is wrong with:

bool flush;

for_each_vcpu ( pg_owner, v )
    if ( pv_destroy_ldt(v) )
        flush = true;

if ( flush )
   flush_tlb_mask(pg_owner->dirty_cpumask);

This is far less complicated cpumask handling.  As the loop may be long,
it avoids flushing pcpus which have subsequently switched away from
pg_owner context.  It also avoids all playing with v->dirty_cpu.

~Andrew

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-04-26  9:51 ` Andrew Cooper
@ 2018-04-26 10:52   ` Jan Beulich
  2018-05-15  8:25     ` Ping: " Jan Beulich
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2018-04-26 10:52 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Juergen Gross, xen-devel, Manuel Bouyer

>>> On 26.04.18 at 11:51, <andrew.cooper3@citrix.com> wrote:
> On 26/04/18 10:41, Jan Beulich wrote:
>> --- 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);
> 
> Thinking about this, what is wrong with:
> 
> bool flush;
> 
> for_each_vcpu ( pg_owner, v )
>     if ( pv_destroy_ldt(v) )
>         flush = true;
> 
> if ( flush )
>    flush_tlb_mask(pg_owner->dirty_cpumask);
> 
> This is far less complicated cpumask handling.  As the loop may be long,
> it avoids flushing pcpus which have subsequently switched away from
> pg_owner context.  It also avoids all playing with v->dirty_cpu.

That would look to be correct, but I'm not sure it would be an improvement:
While it may avoid flushing some CPUs, it may then do extra flushes on
others (which another vCPU of the domain has been switched to). Plus it
would flush even those CPUs where pv_destroy_ldt() has returned false,
as long as the function returned true at least once.

If I was to go that route, I'd at least extend to latching
pg_owner->dirty_cpumask before the loop into scratch_cpumask, ANDing
in pg_owner->dirty_cpumask after the loop to restrict to those CPUs which
may have remained active over the entire time the loop takes. But even
then I would still be afraid of flushing far more CPUs than actually needed.

Jan



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-04-26  9:41 [PATCH] x86: correct vCPU dirty CPU handling Jan Beulich
  2018-04-26  9:51 ` Andrew Cooper
@ 2018-04-26 12:39 ` Manuel Bouyer
  2018-05-22 11:02 ` Manuel Bouyer
  2 siblings, 0 replies; 9+ messages in thread
From: Manuel Bouyer @ 2018-04-26 12:39 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Juergen Gross, xen-devel, Andrew Cooper

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.

Hello,
I tested this patch with NetBSD, it looks good.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Ping: Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-04-26 10:52   ` Jan Beulich
@ 2018-05-15  8:25     ` Jan Beulich
  2018-05-22 12:29       ` Andrew Cooper
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2018-05-15  8:25 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Juergen Gross, xen-devel, Manuel Bouyer

>>> On 26.04.18 at 12:52, <JBeulich@suse.com> wrote:
>>>> On 26.04.18 at 11:51, <andrew.cooper3@citrix.com> wrote:
>> On 26/04/18 10:41, Jan Beulich wrote:
>>> --- 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);
>> 
>> Thinking about this, what is wrong with:
>> 
>> bool flush;
>> 
>> for_each_vcpu ( pg_owner, v )
>>     if ( pv_destroy_ldt(v) )
>>         flush = true;
>> 
>> if ( flush )
>>    flush_tlb_mask(pg_owner->dirty_cpumask);
>> 
>> This is far less complicated cpumask handling.  As the loop may be long,
>> it avoids flushing pcpus which have subsequently switched away from
>> pg_owner context.  It also avoids all playing with v->dirty_cpu.
> 
> That would look to be correct, but I'm not sure it would be an improvement:
> While it may avoid flushing some CPUs, it may then do extra flushes on
> others (which another vCPU of the domain has been switched to). Plus it
> would flush even those CPUs where pv_destroy_ldt() has returned false,
> as long as the function returned true at least once.

Ping?

> If I was to go that route, I'd at least extend to latching
> pg_owner->dirty_cpumask before the loop into scratch_cpumask, ANDing
> in pg_owner->dirty_cpumask after the loop to restrict to those CPUs which
> may have remained active over the entire time the loop takes. But even
> then I would still be afraid of flushing far more CPUs than actually needed.

I don't think anymore that this would be correct, so please ignore this
part.

Thanks, Jan



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-04-26  9:41 [PATCH] x86: correct vCPU dirty CPU handling Jan Beulich
  2018-04-26  9:51 ` Andrew Cooper
  2018-04-26 12:39 ` Manuel Bouyer
@ 2018-05-22 11:02 ` Manuel Bouyer
  2018-05-22 11:08   ` Jan Beulich
  2 siblings, 1 reply; 9+ messages in thread
From: Manuel Bouyer @ 2018-05-22 11:02 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Juergen Gross, xen-devel, Andrew Cooper

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@antioche.eu.org>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> --- 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@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-05-22 11:02 ` Manuel Bouyer
@ 2018-05-22 11:08   ` Jan Beulich
  0 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2018-05-22 11:08 UTC (permalink / raw)
  To: Manuel Bouyer; +Cc: Juergen Gross, Andrew Cooper, xen-devel

>>> On 22.05.18 at 13:02, <bouyer@antioche.eu.org> wrote:
> 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 ?

See the thread "Pending patches for 4.11?" IOW - I very much hope so.

Jan



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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Ping: Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-05-15  8:25     ` Ping: " Jan Beulich
@ 2018-05-22 12:29       ` Andrew Cooper
  2018-05-22 12:38         ` Juergen Gross
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cooper @ 2018-05-22 12:29 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Juergen Gross, xen-devel, Manuel Bouyer

On 15/05/18 09:25, Jan Beulich wrote:
>>>> On 26.04.18 at 12:52, <JBeulich@suse.com> wrote:
>>>>> On 26.04.18 at 11:51, <andrew.cooper3@citrix.com> wrote:
>>> On 26/04/18 10:41, Jan Beulich wrote:
>>>> --- 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);
>>> Thinking about this, what is wrong with:
>>>
>>> bool flush;
>>>
>>> for_each_vcpu ( pg_owner, v )
>>>     if ( pv_destroy_ldt(v) )
>>>         flush = true;
>>>
>>> if ( flush )
>>>    flush_tlb_mask(pg_owner->dirty_cpumask);
>>>
>>> This is far less complicated cpumask handling.  As the loop may be long,
>>> it avoids flushing pcpus which have subsequently switched away from
>>> pg_owner context.  It also avoids all playing with v->dirty_cpu.
>> That would look to be correct, but I'm not sure it would be an improvement:
>> While it may avoid flushing some CPUs, it may then do extra flushes on
>> others (which another vCPU of the domain has been switched to). Plus it
>> would flush even those CPUs where pv_destroy_ldt() has returned false,
>> as long as the function returned true at least once.
> Ping?

I'm not sure it is worth trying to optimise this code.  I've got a patch
for 4.12 to leave it compiled out by default.

Therefore, Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> on the
original patch.

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Ping: Re: [PATCH] x86: correct vCPU dirty CPU handling
  2018-05-22 12:29       ` Andrew Cooper
@ 2018-05-22 12:38         ` Juergen Gross
  0 siblings, 0 replies; 9+ messages in thread
From: Juergen Gross @ 2018-05-22 12:38 UTC (permalink / raw)
  To: Andrew Cooper, Jan Beulich; +Cc: xen-devel, Manuel Bouyer

On 22/05/18 14:29, Andrew Cooper wrote:
> On 15/05/18 09:25, Jan Beulich wrote:
>>>>> On 26.04.18 at 12:52, <JBeulich@suse.com> wrote:
>>>>>> On 26.04.18 at 11:51, <andrew.cooper3@citrix.com> wrote:
>>>> On 26/04/18 10:41, Jan Beulich wrote:
>>>>> --- 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);
>>>> Thinking about this, what is wrong with:
>>>>
>>>> bool flush;
>>>>
>>>> for_each_vcpu ( pg_owner, v )
>>>>     if ( pv_destroy_ldt(v) )
>>>>         flush = true;
>>>>
>>>> if ( flush )
>>>>    flush_tlb_mask(pg_owner->dirty_cpumask);
>>>>
>>>> This is far less complicated cpumask handling.  As the loop may be long,
>>>> it avoids flushing pcpus which have subsequently switched away from
>>>> pg_owner context.  It also avoids all playing with v->dirty_cpu.
>>> That would look to be correct, but I'm not sure it would be an improvement:
>>> While it may avoid flushing some CPUs, it may then do extra flushes on
>>> others (which another vCPU of the domain has been switched to). Plus it
>>> would flush even those CPUs where pv_destroy_ldt() has returned false,
>>> as long as the function returned true at least once.
>> Ping?
> 
> I'm not sure it is worth trying to optimise this code.  I've got a patch
> for 4.12 to leave it compiled out by default.
> 
> Therefore, Acked-by: Andrew Cooper <andrew.cooper3@citrix.com> on the
> original patch.
> 

You can add my

Release-acked-by: Juergen Gross <jgross@suse.com>


Juergen

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-05-22 12:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-26  9:41 [PATCH] x86: correct vCPU dirty CPU handling Jan Beulich
2018-04-26  9:51 ` Andrew Cooper
2018-04-26 10:52   ` Jan Beulich
2018-05-15  8:25     ` Ping: " Jan Beulich
2018-05-22 12:29       ` Andrew Cooper
2018-05-22 12:38         ` Juergen Gross
2018-04-26 12:39 ` Manuel Bouyer
2018-05-22 11:02 ` Manuel Bouyer
2018-05-22 11:08   ` Jan Beulich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.