[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 15/24] cputlb: introduce tlb_flush_* async work.
From: |
Alex Bennée |
Subject: |
[Qemu-devel] [PULL 15/24] cputlb: introduce tlb_flush_* async work. |
Date: |
Fri, 24 Feb 2017 11:21:00 +0000 |
From: KONRAD Frederic <address@hidden>
Some architectures allow to flush the tlb of other VCPUs. This is not a problem
when we have only one thread for all VCPUs but it definitely needs to be an
asynchronous work when we are in true multithreaded work.
We take the tb_lock() when doing this to avoid racing with other threads
which may be invalidating TB's at the same time. The alternative would
be to use proper atomic primitives to clear the tlb entries en-mass.
This patch doesn't do anything to protect other cputlb function being
called in MTTCG mode making cross vCPU changes.
Signed-off-by: KONRAD Frederic <address@hidden>
[AJB: remove need for g_malloc on defer, make check fixes, tb_lock]
Signed-off-by: Alex Bennée <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
cputlb.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++--
include/exec/exec-all.h | 1 +
include/qom/cpu.h | 6 +++++
3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/cputlb.c b/cputlb.c
index 94fa9977c5..5dfd3c3ba9 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -64,6 +64,10 @@
} \
} while (0)
+/* run_on_cpu_data.target_ptr should always be big enough for a
+ * target_ulong even on 32 bit builds */
+QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
+
/* statistics */
int tlb_flush_count;
@@ -72,13 +76,22 @@ int tlb_flush_count;
* flushing more entries than required is only an efficiency issue,
* not a correctness issue.
*/
-void tlb_flush(CPUState *cpu)
+static void tlb_flush_nocheck(CPUState *cpu)
{
CPUArchState *env = cpu->env_ptr;
+ /* The QOM tests will trigger tlb_flushes without setting up TCG
+ * so we bug out here in that case.
+ */
+ if (!tcg_enabled()) {
+ return;
+ }
+
assert_cpu_is_self(cpu);
tlb_debug("(count: %d)\n", tlb_flush_count++);
+ tb_lock();
+
memset(env->tlb_table, -1, sizeof(env->tlb_table));
memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
@@ -86,6 +99,27 @@ void tlb_flush(CPUState *cpu)
env->vtlb_index = 0;
env->tlb_flush_addr = -1;
env->tlb_flush_mask = 0;
+
+ tb_unlock();
+
+ atomic_mb_set(&cpu->pending_tlb_flush, false);
+}
+
+static void tlb_flush_global_async_work(CPUState *cpu, run_on_cpu_data data)
+{
+ tlb_flush_nocheck(cpu);
+}
+
+void tlb_flush(CPUState *cpu)
+{
+ if (cpu->created && !qemu_cpu_is_self(cpu)) {
+ if (atomic_cmpxchg(&cpu->pending_tlb_flush, false, true) == true) {
+ async_run_on_cpu(cpu, tlb_flush_global_async_work,
+ RUN_ON_CPU_NULL);
+ }
+ } else {
+ tlb_flush_nocheck(cpu);
+ }
}
static inline void v_tlb_flush_by_mmuidx(CPUState *cpu, va_list argp)
@@ -95,6 +129,8 @@ static inline void v_tlb_flush_by_mmuidx(CPUState *cpu,
va_list argp)
assert_cpu_is_self(cpu);
tlb_debug("start\n");
+ tb_lock();
+
for (;;) {
int mmu_idx = va_arg(argp, int);
@@ -109,6 +145,8 @@ static inline void v_tlb_flush_by_mmuidx(CPUState *cpu,
va_list argp)
}
memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
+
+ tb_unlock();
}
void tlb_flush_by_mmuidx(CPUState *cpu, ...)
@@ -131,13 +169,15 @@ static inline void tlb_flush_entry(CPUTLBEntry
*tlb_entry, target_ulong addr)
}
}
-void tlb_flush_page(CPUState *cpu, target_ulong addr)
+static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
{
CPUArchState *env = cpu->env_ptr;
+ target_ulong addr = (target_ulong) data.target_ptr;
int i;
int mmu_idx;
assert_cpu_is_self(cpu);
+
tlb_debug("page :" TARGET_FMT_lx "\n", addr);
/* Check if we need to flush due to large pages. */
@@ -167,6 +207,18 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
tb_flush_jmp_cache(cpu, addr);
}
+void tlb_flush_page(CPUState *cpu, target_ulong addr)
+{
+ tlb_debug("page :" TARGET_FMT_lx "\n", addr);
+
+ if (!qemu_cpu_is_self(cpu)) {
+ async_run_on_cpu(cpu, tlb_flush_page_async_work,
+ RUN_ON_CPU_TARGET_PTR(addr));
+ } else {
+ tlb_flush_page_async_work(cpu, RUN_ON_CPU_TARGET_PTR(addr));
+ }
+}
+
void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, ...)
{
CPUArchState *env = cpu->env_ptr;
@@ -213,6 +265,16 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong
addr, ...)
tb_flush_jmp_cache(cpu, addr);
}
+void tlb_flush_page_all(target_ulong addr)
+{
+ CPUState *cpu;
+
+ CPU_FOREACH(cpu) {
+ async_run_on_cpu(cpu, tlb_flush_page_async_work,
+ RUN_ON_CPU_TARGET_PTR(addr));
+ }
+}
+
/* update the TLBs so that writes to code in the virtual page 'addr'
can be detected */
void tlb_protect_code(ram_addr_t ram_addr)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 82f0e12327..c694e3482b 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -158,6 +158,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
void probe_write(CPUArchState *env, target_ulong addr, int mmu_idx,
uintptr_t retaddr);
+void tlb_flush_page_all(target_ulong addr);
#else
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
{
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 10db89b16a..e80bf7a64a 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -402,6 +402,12 @@ struct CPUState {
bool hax_vcpu_dirty;
struct hax_vcpu_state *hax_vcpu;
+
+ /* The pending_tlb_flush flag is set and cleared atomically to
+ * avoid potential races. The aim of the flag is to avoid
+ * unnecessary flushes.
+ */
+ bool pending_tlb_flush;
};
QTAILQ_HEAD(CPUTailQ, CPUState);
--
2.11.0
- [Qemu-devel] [PULL 01/24] docs: new design document multi-thread-tcg.txt, (continued)
- [Qemu-devel] [PULL 01/24] docs: new design document multi-thread-tcg.txt, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 05/24] tcg: add options for enabling MTTCG, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 07/24] tcg: rename tcg_current_cpu to tcg_current_rr_cpu, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 10/24] tcg: enable tb_lock() for SoftMMU, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 11/24] tcg: enable thread-per-vCPU, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 08/24] tcg: drop global lock during TCG code execution, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 09/24] tcg: remove global exit_request, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 12/24] tcg: handle EXCP_ATOMIC exception for system emulation, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 14/24] cputlb: tweak qemu_ram_addr_from_host_nofail reporting, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 13/24] cputlb: add assert_cpu_is_self checks, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 15/24] cputlb: introduce tlb_flush_* async work.,
Alex Bennée <=
- [Qemu-devel] [PULL 17/24] cputlb: add tlb_flush_by_mmuidx async routines, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 22/24] target-arm: ensure all cross vCPUs TLB flushes complete, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 18/24] cputlb: atomically update tlb fields used by tlb_reset_dirty, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 24/24] tcg: enable MTTCG by default for ARM on x86 hosts, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 23/24] hw/misc/imx6_src: defer clearing of SRC_SCR reset bits, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 20/24] target-arm/powerctl: defer cpu reset work to CPU context, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 16/24] cputlb and arm/sparc targets: convert mmuidx flushes from varg to bitmap, Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 19/24] cputlb: introduce tlb_flush_*_all_cpus[_synced], Alex Bennée, 2017/02/24
- [Qemu-devel] [PULL 21/24] target-arm: don't generate WFE/YIELD calls for MTTCG, Alex Bennée, 2017/02/24
- Re: [Qemu-devel] [PULL 00/24] MTTCG Base enabling patches with ARM enablement, Peter Maydell, 2017/02/25