Skip to content

Commit

Permalink
cpu: tcg_ops: move to tcg-cpu-ops.h, keep a pointer in CPUClass
Browse files Browse the repository at this point in the history
we cannot in principle make the TCG Operations field definitions
conditional on CONFIG_TCG in code that is included by both common_ss
and specific_ss modules.

Therefore, what we can do safely to restrict the TCG fields to TCG-only
builds, is to move all tcg cpu operations into a separate header file,
which is only included by TCG, target-specific code.

This leaves just a NULL pointer in the cpu.h for the non-TCG builds.

This also tidies up the code in all targets a bit, having all TCG cpu
operations neatly contained by a dedicated data struct.

Signed-off-by: Claudio Fontana <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
  • Loading branch information
Claudio Fontana authored and rth7680 committed Feb 5, 2021
1 parent c73bdb3 commit 7827168
Show file tree
Hide file tree
Showing 36 changed files with 582 additions and 306 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ F: include/exec/helper*.h
F: include/exec/tb-hash.h
F: include/sysemu/cpus.h
F: include/sysemu/tcg.h
F: include/hw/core/tcg-cpu-ops.h

FPU emulation
M: Aurelien Jarno <[email protected]>
Expand Down
27 changes: 14 additions & 13 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "qemu-common.h"
#include "qemu/qemu-print.h"
#include "cpu.h"
#include "hw/core/tcg-cpu-ops.h"
#include "trace.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
Expand Down Expand Up @@ -213,8 +214,8 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
TARGET_FMT_lx "] %s\n",
last_tb->tc.ptr, last_tb->pc,
lookup_symbol(last_tb->pc));
if (cc->tcg_ops.synchronize_from_tb) {
cc->tcg_ops.synchronize_from_tb(cpu, last_tb);
if (cc->tcg_ops->synchronize_from_tb) {
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
} else {
assert(cc->set_pc);
cc->set_pc(cpu, last_tb->pc);
Expand Down Expand Up @@ -262,17 +263,17 @@ static void cpu_exec_enter(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

if (cc->tcg_ops.cpu_exec_enter) {
cc->tcg_ops.cpu_exec_enter(cpu);
if (cc->tcg_ops->cpu_exec_enter) {
cc->tcg_ops->cpu_exec_enter(cpu);
}
}

static void cpu_exec_exit(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

if (cc->tcg_ops.cpu_exec_exit) {
cc->tcg_ops.cpu_exec_exit(cpu);
if (cc->tcg_ops->cpu_exec_exit) {
cc->tcg_ops->cpu_exec_exit(cpu);
}
}

Expand Down Expand Up @@ -512,8 +513,8 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)
}
}

if (cc->tcg_ops.debug_excp_handler) {
cc->tcg_ops.debug_excp_handler(cpu);
if (cc->tcg_ops->debug_excp_handler) {
cc->tcg_ops->debug_excp_handler(cpu);
}
}

Expand Down Expand Up @@ -547,7 +548,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
loop */
#if defined(TARGET_I386)
CPUClass *cc = CPU_GET_CLASS(cpu);
cc->tcg_ops.do_interrupt(cpu);
cc->tcg_ops->do_interrupt(cpu);
#endif
*ret = cpu->exception_index;
cpu->exception_index = -1;
Expand All @@ -556,7 +557,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
if (replay_exception()) {
CPUClass *cc = CPU_GET_CLASS(cpu);
qemu_mutex_lock_iothread();
cc->tcg_ops.do_interrupt(cpu);
cc->tcg_ops->do_interrupt(cpu);
qemu_mutex_unlock_iothread();
cpu->exception_index = -1;

Expand Down Expand Up @@ -655,8 +656,8 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
True when it is, and we should restart on a new TB,
and via longjmp via cpu_loop_exit. */
else {
if (cc->tcg_ops.cpu_exec_interrupt &&
cc->tcg_ops.cpu_exec_interrupt(cpu, interrupt_request)) {
if (cc->tcg_ops->cpu_exec_interrupt &&
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
if (need_replay_interrupt(interrupt_request)) {
replay_interrupt();
}
Expand Down Expand Up @@ -834,7 +835,7 @@ void tcg_exec_realizefn(CPUState *cpu, Error **errp)
CPUClass *cc = CPU_GET_CLASS(cpu);

if (!tcg_target_initialized) {
cc->tcg_ops.initialize();
cc->tcg_ops->initialize();
tcg_target_initialized = true;
}
tlb_init(cpu);
Expand Down
35 changes: 31 additions & 4 deletions accel/tcg/cputlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "hw/core/tcg-cpu-ops.h"
#include "exec/exec-all.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
Expand Down Expand Up @@ -1305,11 +1306,37 @@ static void tlb_fill(CPUState *cpu, target_ulong addr, int size,
* This is not a probe, so only valid return is success; failure
* should result in exception + longjmp to the cpu loop.
*/
ok = cc->tcg_ops.tlb_fill(cpu, addr, size,
access_type, mmu_idx, false, retaddr);
ok = cc->tcg_ops->tlb_fill(cpu, addr, size,
access_type, mmu_idx, false, retaddr);
assert(ok);
}

static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
}

static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response,
uintptr_t retaddr)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

if (!cpu->ignore_memory_transaction_failures &&
cc->tcg_ops->do_transaction_failed) {
cc->tcg_ops->do_transaction_failed(cpu, physaddr, addr, size,
access_type, mmu_idx, attrs,
response, retaddr);
}
}

static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
int mmu_idx, target_ulong addr, uintptr_t retaddr,
MMUAccessType access_type, MemOp op)
Expand Down Expand Up @@ -1577,8 +1604,8 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
CPUState *cs = env_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cs);

if (!cc->tcg_ops.tlb_fill(cs, addr, fault_size, access_type,
mmu_idx, nonfault, retaddr)) {
if (!cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
mmu_idx, nonfault, retaddr)) {
/* Non-faulting page table read failed. */
*phost = NULL;
return TLB_INVALID_MASK;
Expand Down
9 changes: 5 additions & 4 deletions accel/tcg/user-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/core/tcg-cpu-ops.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
Expand Down Expand Up @@ -187,8 +188,8 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
clear_helper_retaddr();

cc = CPU_GET_CLASS(cpu);
cc->tcg_ops.tlb_fill(cpu, address, 0, access_type,
MMU_USER_IDX, false, pc);
cc->tcg_ops->tlb_fill(cpu, address, 0, access_type,
MMU_USER_IDX, false, pc);
g_assert_not_reached();
}

Expand Down Expand Up @@ -218,8 +219,8 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
} else {
CPUState *cpu = env_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
cc->tcg_ops.tlb_fill(cpu, addr, fault_size, access_type,
MMU_USER_IDX, false, ra);
cc->tcg_ops->tlb_fill(cpu, addr, fault_size, access_type,
MMU_USER_IDX, false, ra);
g_assert_not_reached();
}
}
Expand Down
7 changes: 5 additions & 2 deletions hw/mips/jazz.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/help_option.h"
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
#endif /* CONFIG_TCG */

enum jazz_model_e {
JAZZ_MAGNUM,
Expand Down Expand Up @@ -209,8 +212,8 @@ static void mips_jazz_init(MachineState *machine,
*/
cc = CPU_GET_CLASS(cpu);
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
real_do_transaction_failed = cc->tcg_ops.do_transaction_failed;
cc->tcg_ops.do_transaction_failed = mips_jazz_do_transaction_failed;
real_do_transaction_failed = cc->tcg_ops->do_transaction_failed;
cc->tcg_ops->do_transaction_failed = mips_jazz_do_transaction_failed;
#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */

/* allocate RAM */
Expand Down
103 changes: 4 additions & 99 deletions include/hw/core/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,78 +76,8 @@ typedef struct CPUWatchpoint CPUWatchpoint;

struct TranslationBlock;

/**
* struct TcgCpuOperations: TCG operations specific to a CPU class
*/
typedef struct TcgCpuOperations {
/**
* @initialize: Initalize TCG state
*
* Called when the first CPU is realized.
*/
void (*initialize)(void);
/**
* @synchronize_from_tb: Synchronize state from a TCG #TranslationBlock
*
* This is called when we abandon execution of a TB before starting it,
* and must set all parts of the CPU state which the previous TB in the
* chain may not have updated.
* By default, when this is NULL, a call is made to @set_pc(tb->pc).
*
* If more state needs to be restored, the target must implement a
* function to restore all the state, and register it here.
*/
void (*synchronize_from_tb)(CPUState *cpu,
const struct TranslationBlock *tb);
/** @cpu_exec_enter: Callback for cpu_exec preparation */
void (*cpu_exec_enter)(CPUState *cpu);
/** @cpu_exec_exit: Callback for cpu_exec cleanup */
void (*cpu_exec_exit)(CPUState *cpu);
/** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
/** @do_interrupt: Callback for interrupt handling. */
void (*do_interrupt)(CPUState *cpu);
/**
* @tlb_fill: Handle a softmmu tlb miss or user-only address fault
*
* For system mode, if the access is valid, call tlb_set_page
* and return true; if the access is invalid, and probe is
* true, return false; otherwise raise an exception and do
* not return. For user-only mode, always raise an exception
* and do not return.
*/
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
/** @debug_excp_handler: Callback for handling debug exceptions */
void (*debug_excp_handler)(CPUState *cpu);

/**
* @do_transaction_failed: Callback for handling failed memory transactions
* (ie bus faults or external aborts; not MMU faults)
*/
void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
unsigned size, MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr);
/**
* @do_unaligned_access: Callback for unaligned access handling
*/
void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
/**
* @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
*/
vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len);

/**
* @debug_check_watchpoint: return true if the architectural
* watchpoint whose address has matched should really fire, used by ARM
*/
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);

} TcgCpuOperations;
/* see tcg-cpu-ops.h */
struct TCGCPUOps;

/**
* CPUClass:
Expand Down Expand Up @@ -258,7 +188,8 @@ struct CPUClass {
int gdb_num_core_regs;
bool gdb_stop_before_watchpoint;

TcgCpuOperations tcg_ops;
/* when TCG is not available, this pointer is NULL */
struct TCGCPUOps *tcg_ops;
};

/*
Expand Down Expand Up @@ -889,32 +820,6 @@ CPUState *cpu_by_arch_id(int64_t id);

void cpu_interrupt(CPUState *cpu, int mask);

static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

cc->tcg_ops.do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
}

static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response,
uintptr_t retaddr)
{
CPUClass *cc = CPU_GET_CLASS(cpu);

if (!cpu->ignore_memory_transaction_failures &&
cc->tcg_ops.do_transaction_failed) {
cc->tcg_ops.do_transaction_failed(cpu, physaddr, addr, size,
access_type, mmu_idx, attrs,
response, retaddr);
}
}

/**
* cpu_set_pc:
* @cpu: The CPU to set the program counter for.
Expand Down
Loading

0 comments on commit 7827168

Please sign in to comment.