]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
x86: make CPU state flush requests explicit
authorJan Beulich <jbeulich@suse.com>
Tue, 23 Jan 2018 09:44:11 +0000 (10:44 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 23 Jan 2018 09:44:11 +0000 (10:44 +0100)
Having this be an implied side effect of a TLB flush is not very nice:
It could (at least in theory) lead to unintended state flushes (see e.g.
https://lists.xenproject.org/archives/html/xen-devel/2017-11/msg00187.html
for context). Introduce a flag to be used in the two places actually
wanting the state flushed, and conditionalize the
__sync_local_execstate() invocation in the IPI handler accordingly.

At the same time also conditionalize the flush_area_local() invocations,
to short-circuit the function ending up as a no-op anyway.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/domain.c
xen/arch/x86/smp.c
xen/include/asm-x86/flushtlb.h

index dbf4522e69fbd859b1b8e59f1091a9f2c92b38b0..643628c6513347e0c2f6fa2a0e084dc150ffad26 100644 (file)
@@ -1697,7 +1697,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
                   !cpumask_empty(&dirty_mask)) )
     {
         /* Other cpus call __sync_local_execstate from flush ipi handler. */
-        flush_tlb_mask(&dirty_mask);
+        flush_mask(&dirty_mask, FLUSH_TLB | FLUSH_VCPU_STATE);
     }
 
     if ( prev != next )
@@ -1806,7 +1806,7 @@ void sync_vcpu_execstate(struct vcpu *v)
         sync_local_execstate();
 
     /* Other cpus call __sync_local_execstate from flush ipi handler. */
-    flush_tlb_mask(v->vcpu_dirty_cpumask);
+    flush_mask(v->vcpu_dirty_cpumask, FLUSH_TLB | FLUSH_VCPU_STATE);
 }
 
 static int relinquish_memory(
index fd6d25481216350747b7891131903806469fc2e4..033dd059580b821661afd66c214a14b01371b626 100644 (file)
@@ -207,9 +207,10 @@ void invalidate_interrupt(struct cpu_user_regs *regs)
     unsigned int flags = flush_flags;
     ack_APIC_irq();
     perfc_incr(ipis);
-    if ( __sync_local_execstate() )
+    if ( (flags & FLUSH_VCPU_STATE) && __sync_local_execstate() )
         flags &= ~(FLUSH_TLB | FLUSH_TLB_GLOBAL);
-    flush_area_local(flush_va, flags);
+    if ( flags & ~(FLUSH_VCPU_STATE | FLUSH_ORDER_MASK) )
+        flush_area_local(flush_va, flags);
     cpumask_clear_cpu(smp_processor_id(), &flush_cpumask);
 }
 
@@ -219,7 +220,8 @@ void flush_area_mask(const cpumask_t *mask, const void *va, unsigned int flags)
 
     ASSERT(local_irq_is_enabled());
 
-    if ( cpumask_test_cpu(cpu, mask) )
+    if ( (flags & ~(FLUSH_VCPU_STATE | FLUSH_ORDER_MASK)) &&
+         cpumask_test_cpu(cpu, mask) )
         flags = flush_area_local(va, flags);
 
     if ( (flags & ~FLUSH_ORDER_MASK) &&
index 413db692e1f59a621128c74b4fe1588caae02e12..2cade9cbfbd6126503f59e724843d89763735e04 100644 (file)
@@ -101,6 +101,8 @@ void write_cr3(unsigned long cr3);
 #define FLUSH_CACHE      0x400
  /* VA for the flush has a valid mapping */
 #define FLUSH_VA_VALID   0x800
+ /* Flush CPU state */
+#define FLUSH_VCPU_STATE 0x1000
 
 /* Flush local TLBs/caches. */
 unsigned int flush_area_local(const void *va, unsigned int flags);