[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 21/35] core: virtualise CPU interfaces completely
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [PATCH v3 21/35] core: virtualise CPU interfaces completely |
Date: |
Sat, 18 Jul 2015 02:40:31 -0700 |
The core code interfaces to translate-all, cpu-tlb and cpu-exec are
virtualised. This prepare support for multi-arch where these modules
are multi-compiled for the different target backends and will need
to co-exist.
The names of functions are not changed. They still have their generic
names and can be linked to the final build as-is.
In multi-arch, the arch-obj components have all symbols localised which
includes all of the function defs for these hooks (despite them still
having generic names and global linkage). So it is up to the target
specific sub-class to install theses hooks. Multiple targets can do this
and then link together. The CPU base class will harmlessly set the
hooks to NULL but in multi-arch these must be overridden.
The hooks are only called in MULTI_ARCH case, which has the advantage
of preserving the devirtualised behaviour of these hooks. It also
guards against unconverted archs that do not set the QOM_HOOKS, i.e.
an unconverted arch will not attempt to call the virtualised hooks.
Signed-off-by: Peter Crosthwaite <address@hidden>
---
Changed since RFC v2:
* Major rewrite *
remove tcg_ctx ptr (RTH)
virtualise cpu_get_tb_cpu_state (Paolo)
Don't use virtualised hooks outside of multi-arch (Paolo)
Don't stub or install default hooks (woot!)
Don't move header definitions
Split API changes to separate patches
Compile out hooks when cpu.h is unavailable
Compile out hooks that dont exist in linux user mode
remove tb_invalidate_phys_page_range from hooks (linux-u only)
Add monitor hooks, dump_exec_info, dump_opcount_info
Add tcg_enabled() as a hook
---
cpus.c | 6 ++--
exec.c | 29 ++++++++---------
gdbstub.c | 2 +-
include/exec/cpu-common.h | 2 --
include/exec/exec-all.h | 5 +++
include/qom/cpu.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++
monitor.c | 4 +--
7 files changed, 105 insertions(+), 22 deletions(-)
diff --git a/cpus.c b/cpus.c
index cd25c8c..738b96f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1116,7 +1116,7 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
void qemu_cpu_kick(CPUState *cpu)
{
qemu_cond_broadcast(cpu->halt_cond);
- if (!tcg_enabled() && !cpu->thread_kicked) {
+ if (!CPU_HOOK(cpu, tcg_enabled)() && !cpu->thread_kicked) {
qemu_cpu_kick_thread(cpu);
cpu->thread_kicked = true;
}
@@ -1310,7 +1310,7 @@ void qemu_init_vcpu(CPUState *cpu)
cpu->stopped = true;
if (kvm_enabled()) {
qemu_kvm_start_vcpu(cpu);
- } else if (tcg_enabled()) {
+ } else if (CPU_HOOK(cpu, tcg_enabled)()) {
qemu_tcg_init_vcpu(cpu);
} else {
qemu_dummy_start_vcpu(cpu);
@@ -1393,7 +1393,7 @@ static int tcg_cpu_exec(CPUState *cpu)
cpu->icount_decr.u16.low = decr;
cpu->icount_extra = count;
}
- ret = cpu_exec(cpu);
+ ret = CPU_HOOK(cpu, cpu_exec)(cpu);
#ifdef CONFIG_PROFILER
tcg_time += profile_getclock() - ti;
#endif
diff --git a/exec.c b/exec.c
index c37475a..4a722ce 100644
--- a/exec.c
+++ b/exec.c
@@ -445,7 +445,7 @@ static int cpu_common_post_load(void *opaque, int
version_id)
/* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
version_id is increased. */
cpu->interrupt_request &= ~0x01;
- tlb_flush(cpu, 1);
+ CPU_HOOK(cpu, tlb_flush)(cpu, 1);
return 0;
}
@@ -463,7 +463,7 @@ static bool cpu_common_exception_index_needed(void *opaque)
{
CPUState *cpu = opaque;
- return tcg_enabled() && cpu->exception_index != -1;
+ return CPU_HOOK(cpu, tcg_enabled)() && cpu->exception_index != -1;
}
static const VMStateDescription vmstate_cpu_common_exception_index = {
@@ -621,8 +621,8 @@ static void breakpoint_invalidate(CPUState *cpu,
target_ulong pc)
{
hwaddr phys = cpu_get_phys_page_debug(cpu, pc);
if (phys != -1) {
- tb_invalidate_phys_addr(cpu->as,
- phys | (pc & ~TARGET_PAGE_MASK));
+ CPU_HOOK(cpu, tb_invalidate_phys_addr)(cpu->as,
+ phys | (pc &
~TARGET_PAGE_MASK));
}
}
#endif
@@ -674,7 +674,7 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr
len,
QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry);
}
- tlb_flush_page(cpu, addr);
+ CPU_HOOK(cpu, tlb_flush_page)(cpu, addr);
if (watchpoint)
*watchpoint = wp;
@@ -702,7 +702,7 @@ void cpu_watchpoint_remove_by_ref(CPUState *cpu,
CPUWatchpoint *watchpoint)
{
QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry);
- tlb_flush_page(cpu, watchpoint->vaddr);
+ CPU_HOOK(cpu, tlb_flush_page)(cpu, watchpoint->vaddr);
g_free(watchpoint);
}
@@ -814,7 +814,7 @@ void cpu_single_step(CPUState *cpu, int enabled)
} else {
/* must flush all the translated code to avoid inconsistencies */
/* XXX: only flush what is necessary */
- tb_flush(cpu);
+ CPU_HOOK(cpu,tb_flush)(cpu);
}
}
}
@@ -906,7 +906,7 @@ static void tlb_reset_dirty_range_all(ram_addr_t start,
ram_addr_t length)
assert(block == qemu_get_ram_block(end - 1));
start1 = (uintptr_t)ramblock_ptr(block, start - block->offset);
CPU_FOREACH(cpu) {
- tlb_reset_dirty(cpu, start1, length);
+ CPU_HOOK(cpu, tlb_reset_dirty)(cpu, start1, length);
}
rcu_read_unlock();
}
@@ -1876,7 +1876,7 @@ static void notdirty_mem_write(void *opaque, hwaddr
ram_addr,
uint64_t val, unsigned size)
{
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
- tb_invalidate_phys_page_fast(ram_addr, size);
+ CPU_HOOK(current_cpu, tb_invalidate_phys_page_fast)(ram_addr, size);
}
switch (size) {
case 1:
@@ -1899,7 +1899,8 @@ static void notdirty_mem_write(void *opaque, hwaddr
ram_addr,
/* we remove the notdirty callback only if the code has been
flushed */
if (!cpu_physical_memory_is_clean(ram_addr)) {
- tlb_set_dirty(current_cpu, current_cpu->mem_io_vaddr);
+ CPU_HOOK(current_cpu, tlb_set_dirty)(current_cpu,
+ current_cpu->mem_io_vaddr);
}
}
@@ -1945,13 +1946,13 @@ static void check_watchpoint(int offset, int len,
MemTxAttrs attrs, int flags)
wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) {
cpu->watchpoint_hit = wp;
- tb_check_watchpoint(cpu);
+ CPU_HOOK(cpu, tb_check_watchpoint)(cpu);
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
cpu->exception_index = EXCP_DEBUG;
cpu_loop_exit(cpu);
} else {
- cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
- tb_gen_code(cpu, pc, cs_base, cpu_flags, 1);
+ CPU_HOOK(cpu, cpu_get_tb_cpu_state)(env, &pc, &cs_base,
&cpu_flags);
+ CPU_HOOK(cpu, tb_gen_code)(cpu, pc, cs_base, cpu_flags, 1);
cpu_resume_from_signal(cpu, NULL);
}
}
@@ -2344,7 +2345,7 @@ static void invalidate_and_set_dirty(MemoryRegion *mr,
hwaddr addr,
cpu_physical_memory_range_includes_clean(addr, length,
dirty_log_mask);
}
if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
- tb_invalidate_phys_range(addr, addr + length);
+ CPU_HOOK(current_cpu, tb_invalidate_phys_range)(addr, addr + length);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
}
cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
diff --git a/gdbstub.c b/gdbstub.c
index 92b2f81..2f280e6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1257,7 +1257,7 @@ static void gdb_vm_state_change(void *opaque, int
running, RunState state)
cpu->watchpoint_hit = NULL;
goto send_packet;
}
- tb_flush(cpu);
+ CPU_HOOK(cpu, tb_flush)(cpu);
ret = GDB_SIGNAL_TRAP;
break;
case RUN_STATE_PAUSED:
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 47d416d..d35601e 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -53,9 +53,7 @@ typedef uintptr_t ram_addr_t;
# define RAM_ADDR_FMT "%" PRIxPTR
#endif
-#ifndef CONFIG_USER_ONLY
typedef ram_addr_t tb_page_addr_t;
-#endif
extern ram_addr_t ram_size;
ram_addr_t get_current_ram_size(void);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8fd0540..0c70c17 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -363,4 +363,9 @@ extern volatile sig_atomic_t exit_request;
#if !defined(CONFIG_USER_ONLY)
void migration_bitmap_extend(ram_addr_t old, ram_addr_t new);
#endif
+
+#ifdef NEED_CPU_H
+#include "translate-all.h"
+#endif
+
#endif
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index eb12d26..9fbae16 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -212,6 +212,8 @@ struct kvm_run;
#define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
+#define MAX_CPU_HOOKS 16
+
/**
* CPUState:
* @cpu_index: CPU index (informative).
@@ -320,8 +322,85 @@ struct CPUState {
(absolute value) offset as small as possible. This reduces code
size, especially for hosts without large memory offsets. */
volatile sig_atomic_t tcg_exit_req;
+
+ void (*cpu_get_tb_cpu_state)(void *env, void *pc, void *cs_base,
+ int *pflags);
+
+ union {
+ struct {
+#ifdef NEED_CPU_H
+ void (*tb_check_watchpoint)(CPUState *cpu);
+ void (*tb_flush)(CPUState *cpu);
+ struct TranslationBlock *(*tb_gen_code)(CPUState *cpu,
+ target_ulong pc,
+ target_ulong cs_base,
+ int flags, int cflags);
+#ifndef CONFIG_USER_ONLY
+ void (*tlb_flush)(CPUState *cpu, int flush_global);
+ void (*tlb_flush_page)(CPUState *cpu, target_ulong addr);
+ void (*tlb_set_dirty)(CPUState *cpu, target_ulong addr);
+ void (*tlb_reset_dirty)(CPUState *cpu, ram_addr_t start,
+ ram_addr_t length);
+
+ void (*tb_invalidate_phys_addr)(AddressSpace *as, hwaddr addr);
+ void (*tb_invalidate_phys_page_fast)(tb_page_addr_t start, int
len);
+ void (*tb_invalidate_phys_range)(tb_page_addr_t start,
tb_page_addr_t end);
+
+ void (*dump_exec_info)(FILE *f, fprintf_function cpu_fprintf);
+ void (*dump_opcount_info)(FILE *f, fprintf_function cpu_fprintf);
+#endif
+ int (*cpu_exec)(CPUState *cpu);
+
+ bool (*tcg_enabled)(void);
+#endif
+ void (*hooks_end_of_list)(void);
+ };
+ void (*hooks_dummy[MAX_CPU_HOOKS + 1])(void);
+ };
};
+QEMU_BUILD_BUG_ON(offsetof(CPUState, hooks_end_of_list) >
+ offsetof(CPUState, hooks_dummy[MAX_CPU_HOOKS + 1]))
+
+#ifndef CONFIG_USER_ONLY
+#define IFN_USER_ONLY(a) a
+#else
+#define IFN_USER_ONLY(a)
+#endif
+
+#define CPU_SET_QOM_HOOKS(cpu) do { \
+ cpu->cpu_get_tb_cpu_state = \
+ (void (*)(void *, void *, void *, int *))cpu_get_tb_cpu_state; \
+ \
+ cpu->tb_check_watchpoint = tb_check_watchpoint; \
+ cpu->tb_flush = tb_flush; \
+ cpu->tb_gen_code = tb_gen_code; \
+ \
+ IFN_USER_ONLY( \
+ cpu->tlb_flush = tlb_flush; \
+ cpu->tlb_flush_page = tlb_flush_page; \
+ cpu->tlb_set_dirty = tlb_set_dirty; \
+ cpu->tlb_reset_dirty = tlb_reset_dirty; \
+ \
+ cpu->tb_invalidate_phys_addr = tb_invalidate_phys_addr; \
+ cpu->tb_invalidate_phys_page_fast = tb_invalidate_phys_page_fast; \
+ cpu->tb_invalidate_phys_range = tb_invalidate_phys_range; \
+ \
+ cpu->dump_exec_info = dump_exec_info; \
+ cpu->dump_opcount_info = dump_opcount_info; \
+ ) \
+ \
+ cpu->cpu_exec = cpu_exec; \
+ \
+ cpu->tcg_enabled = tcg_enabled; \
+} while (0);
+
+#ifdef TARGET_MULTI
+#define CPU_HOOK(cpu, fn)(cpu->fn)
+#else
+#define CPU_HOOK(cpu, fn)(fn)
+#endif
+
QTAILQ_HEAD(CPUTailQ, CPUState);
extern struct CPUTailQ cpus;
#define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
diff --git a/monitor.c b/monitor.c
index f283035..cb66692 100644
--- a/monitor.c
+++ b/monitor.c
@@ -962,13 +962,13 @@ static void hmp_info_registers(Monitor *mon, const QDict
*qdict)
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
{
- dump_exec_info((FILE *)mon, monitor_fprintf);
+ CPU_HOOK(mon_get_cpu(), dump_exec_info)((FILE *)mon, monitor_fprintf);
dump_drift_info((FILE *)mon, monitor_fprintf);
}
static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
{
- dump_opcount_info((FILE *)mon, monitor_fprintf);
+ CPU_HOOK(mon_get_cpu(), dump_opcount_info)((FILE *)mon, monitor_fprintf);
}
static void hmp_info_history(Monitor *mon, const QDict *qdict)
--
1.9.1
- Re: [Qemu-devel] [PATCH v3 15/35] include/exec: Split target_long def to new header, (continued)
- [Qemu-devel] [PATCH v3 17/35] monitor: uninclude cpu_ldst, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 16/35] cpu-defs: Allow multiple inclusions, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 19/35] target-*: cpu.h: Undefine core code symbols, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 18/35] target-*: Don't redefine cpu_exec(), Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 20/35] Makefile.target: Introduce arch-obj, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 22/35] core: Introduce multi-arch build, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 21/35] core: virtualise CPU interfaces completely,
Peter Crosthwaite <=
- [Qemu-devel] [PATCH v3 23/35] arm: cpu: static inline cpu_arm_init(), Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 25/35] arm: register cpu_list() function, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 24/35] target-arm: Split cp helper API to new C file, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 27/35] hw: arm: Explicitly include cpu.h for consumers, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 28/35] arm: Remove ELF_MACHINE from cpu.h, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 29/35] hw: mb: Explicitly include cpu.h for consumers, Peter Crosthwaite, 2015/07/18