@@ -42,6 +42,8 @@
#include "qapi-event.h"
#include "hw/nmi.h"
+#include "exec/cputlb.h"
+
#ifndef _WIN32
#include "qemu/compatfd.h"
#endif
@@ -1379,6 +1381,21 @@ static void tcg_exec_all(CPUState *cpu)
}
}
+ switch (cpu->flush_request) {
+ case TLB_FLUSH:
+ tlb_flush(cpu, 0);
+ break;
+ case TLB_FLUSH_GLOBAL:
+ tlb_flush(cpu, 1);
+ break;
+ case TLB_FLUSH_PAGE:
+ tlb_flush_page(cpu, cpu->flush_addr);
+ break;
+ default:
+ break;
+ }
+
+ cpu->flush_request = 0;
cpu->exit_request = 0;
}
@@ -29,6 +29,7 @@
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
#include "tcg/tcg.h"
+#include "sysemu/cpus.h"
void qemu_mutex_lock_iothread(void);
void qemu_mutex_unlock_iothread(void);
@@ -39,6 +40,31 @@ void qemu_mutex_unlock_iothread(void);
/* statistics */
int tlb_flush_count;
+void tlb_request_flush(CPUState *cpu, int flush_global)
+{
+ if (cpu->thread_id == qemu_get_thread_id()) {
+ tlb_flush(cpu, flush_global);
+ }
+
+ if (!flush_global) {
+ cpu->flush_request = TLB_FLUSH;
+ } else {
+ cpu->flush_request = TLB_FLUSH_GLOBAL;
+ }
+ qemu_cpu_kick_thread(cpu);
+}
+
+void tlb_request_flush_page(CPUState *cpu, target_ulong addr)
+{
+ if (cpu->thread_id == qemu_get_thread_id()) {
+ tlb_flush_page(cpu, addr);
+ }
+
+ cpu->flush_request = TLB_FLUSH_PAGE;
+ cpu->flush_addr = addr;
+ qemu_cpu_kick_thread(cpu);
+}
+
/* NOTE:
* If flush_global is true (the usual case), flush all tlb entries.
* If flush_global is false, flush (at least) all tlb entries not
@@ -19,6 +19,14 @@
#ifndef CPUTLB_H
#define CPUTLB_H
+enum flush_req
+{
+ TLB_NO_REQUEST = 0,
+ TLB_FLUSH,
+ TLB_FLUSH_GLOBAL,
+ TLB_FLUSH_PAGE
+};
+
#if !defined(CONFIG_USER_ONLY)
/* cputlb.c */
void tlb_protect_code(ram_addr_t ram_addr);
@@ -95,6 +95,17 @@ void tb_invalidate_phys_page_range(tb_page_addr_t
start, tb_page_addr_t end,
int is_cpu_write_access);
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
+/**
+ * tlb_request_flush.
+ * Request a tlb_flush and exit the cpu.
+ */
+void tlb_request_flush(CPUState *cpu, int flush_global);
+/**
+ * tlb_request_flush_page.
+ * Request a tlb_flush_page and exit the cpu.
+ */
+void tlb_request_flush_page(CPUState *cpu, target_ulong addr);
+
#if !defined(CONFIG_USER_ONLY)
bool qemu_in_vcpu_thread(void);
void cpu_reload_memory_map(CPUState *cpu);
@@ -295,6 +295,10 @@ struct CPUState {
uint32_t can_do_io;
int32_t exception_index; /* used by m68k TCG */
+ /* Somebody asked to flush the tlb of this CPU. */
+ int flush_request;
+ uint64_t flush_addr;
+
/* Note that this is accessed at the start of every TB via a negative
offset from AREG0. Leave this field at the end so as to make the
(absolute value) offset as small as possible. This reduces code
This is the helper modification:
@@ -314,7 +314,7 @@ static void dacr_write(CPUARMState *env, const
ARMCPRegInfo *ri, uint64_t value)
ARMCPU *cpu = arm_env_get_cpu(env);
raw_write(env, ri, value);
- tlb_flush(CPU(cpu), 1); /* Flush TLB as domain not tracked in TLB */
+ tlb_request_flush(CPU(cpu), 1); /* Flush TLB as domain not tracked
in TLB */
}