qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC 04/10] cputlb: Introduce tlb_flush_other()


From: Alvise Rigo
Subject: [Qemu-devel] [RFC 04/10] cputlb: Introduce tlb_flush_other()
Date: Thu, 26 May 2016 18:35:43 +0200

In some cases (like in softmmu_llsc_template.h) we know for certain that
we need to flush other VCPUs' TLB. tlb_flush_other() serves this
purpose, allowing the VCPU @cpu to query a global flush to @other.

In addition, use it also in softmmu_llsc_template.h and tlb_flush()
if possible.

Signed-off-by: Alvise Rigo <address@hidden>
---
 cputlb.c                | 28 +++++++++++++++++++++++-----
 softmmu_llsc_template.h |  2 +-
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 1586b64..55f7447 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -81,12 +81,24 @@ static void tlb_flush_nocheck(CPUState *cpu, int 
flush_global)
     env->tlb_flush_addr = -1;
     env->tlb_flush_mask = 0;
     tlb_flush_count++;
-    /* atomic_mb_set(&cpu->pending_tlb_flush, 0); */
 }
 
 static void tlb_flush_global_async_work(CPUState *cpu, void *opaque)
 {
     tlb_flush_nocheck(cpu, GPOINTER_TO_INT(opaque));
+    atomic_mb_set(&cpu->pending_tlb_flush, false);
+}
+
+static void tlb_flush_other(CPUState *cpu, CPUState *other, int flush_global)
+{
+    if (other->created) {
+        if (!atomic_xchg(&other->pending_tlb_flush, true)) {
+            async_wait_run_on_cpu(other, cpu, tlb_flush_global_async_work,
+                                  GINT_TO_POINTER(flush_global));
+        }
+    } else {
+        tlb_flush_nocheck(other, flush_global);
+    }
 }
 
 /* NOTE:
@@ -103,11 +115,17 @@ static void tlb_flush_global_async_work(CPUState *cpu, 
void *opaque)
  */
 void tlb_flush(CPUState *cpu, int flush_global)
 {
-    if (cpu->created) {
-        async_run_on_cpu(cpu, tlb_flush_global_async_work,
-                         GINT_TO_POINTER(flush_global));
-    } else {
+    /* if @cpu has not been created yet or it is the current_cpu, we do not
+     * need to query the flush. */
+    if (current_cpu == cpu || !cpu->created) {
         tlb_flush_nocheck(cpu, flush_global);
+    } else {
+        if (current_cpu) {
+            tlb_flush_other(current_cpu, cpu, flush_global);
+        } else {
+            async_run_on_cpu(cpu, tlb_flush_global_async_work,
+                             GINT_TO_POINTER(flush_global));
+        }
     }
 }
 
diff --git a/softmmu_llsc_template.h b/softmmu_llsc_template.h
index d3810c0..51ce58f 100644
--- a/softmmu_llsc_template.h
+++ b/softmmu_llsc_template.h
@@ -81,7 +81,7 @@ WORD_TYPE helper_ldlink_name(CPUArchState *env, target_ulong 
addr,
             excl_history_put_addr(hw_addr);
             CPU_FOREACH(cpu) {
                 if (this_cpu != cpu) {
-                    tlb_flush(cpu, 1);
+                    tlb_flush_other(this_cpu, cpu, 1);
                 }
             }
         }
-- 
2.8.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]