diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-05 22:59:12 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-05 22:59:12 +0000 |
commit | 5b19cb63d9dfda41b412373b8c9fe14641bcab60 (patch) | |
tree | 692eb654bd23ed45bcacc3f993d1d9fd29144f91 | |
parent | d0dddab40e472ba62b5f43f11cc7dba085dabe71 (diff) | |
parent | fb6916dd6ca8bb4b42d44baba9c67ecaf2279577 (diff) |
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210205' into staging
TCGCPUOps cleanups (claudio)
tcg/s390 compare fix (phil)
tcg/aarch64 rotli_vec fix
tcg/tci cleanups and fixes
# gpg: Signature made Fri 05 Feb 2021 22:55:10 GMT
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* remotes/rth-gitlab/tags/pull-tcg-20210205: (46 commits)
accel: introduce AccelCPUClass extending CPUClass
accel: replace struct CpusAccel with AccelOpsClass
accel: extend AccelState and AccelClass to user-mode
cpu: tcg_ops: move to tcg-cpu-ops.h, keep a pointer in CPUClass
cpu: move debug_check_watchpoint to tcg_ops
cpu: move adjust_watchpoint_address to tcg_ops
physmem: make watchpoint checking code TCG-only
cpu: move do_unaligned_access to tcg_ops
cpu: move cc->transaction_failed to tcg_ops
cpu: move cc->do_interrupt to tcg_ops
target/arm: do not use cc->do_interrupt for KVM directly
cpu: Move debug_excp_handler to tcg_ops
cpu: Move tlb_fill to tcg_ops
cpu: Move cpu_exec_* to tcg_ops
cpu: Move synchronize_from_tb() to tcg_ops
accel/tcg: split TCG-only code from cpu_exec_realizefn
target/riscv: remove CONFIG_TCG, as it is always TCG
cpu: Introduce TCGCpuOperations struct
tcg/tci: Remove TCG_CONST
tcg/tci: Fix TCG_REG_R4 misusage
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
108 files changed, 1564 insertions, 1064 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 00626941f1..8d8b0bf966 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 <aurelien@aurel32.net> @@ -437,8 +438,10 @@ Overall M: Richard Henderson <richard.henderson@linaro.org> R: Paolo Bonzini <pbonzini@redhat.com> S: Maintained -F: include/sysemu/accel.h -F: accel/accel.c +F: include/qemu/accel.h +F: include/sysemu/accel-ops.h +F: include/hw/core/accel-cpu.h +F: accel/accel-*.c F: accel/Makefile.objs F: accel/stubs/Makefile.objs diff --git a/accel/accel-common.c b/accel/accel-common.c new file mode 100644 index 0000000000..9901b0531c --- /dev/null +++ b/accel/accel-common.c @@ -0,0 +1,105 @@ +/* + * QEMU accel class, components common to system emulation and user mode + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/accel.h" + +#include "cpu.h" +#include "hw/core/accel-cpu.h" + +#ifndef CONFIG_USER_ONLY +#include "accel-softmmu.h" +#endif /* !CONFIG_USER_ONLY */ + +static const TypeInfo accel_type = { + .name = TYPE_ACCEL, + .parent = TYPE_OBJECT, + .class_size = sizeof(AccelClass), + .instance_size = sizeof(AccelState), +}; + +/* Lookup AccelClass from opt_name. Returns NULL if not found */ +AccelClass *accel_find(const char *opt_name) +{ + char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name); + AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name)); + g_free(class_name); + return ac; +} + +static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque) +{ + CPUClass *cc = CPU_CLASS(klass); + AccelCPUClass *accel_cpu = opaque; + + cc->accel_cpu = accel_cpu; + if (accel_cpu->cpu_class_init) { + accel_cpu->cpu_class_init(cc); + } +} + +/* initialize the arch-specific accel CpuClass interfaces */ +static void accel_init_cpu_interfaces(AccelClass *ac) +{ + const char *ac_name; /* AccelClass name */ + char *acc_name; /* AccelCPUClass name */ + ObjectClass *acc; /* AccelCPUClass */ + + ac_name = object_class_get_name(OBJECT_CLASS(ac)); + g_assert(ac_name != NULL); + + acc_name = g_strdup_printf("%s-%s", ac_name, CPU_RESOLVING_TYPE); + acc = object_class_by_name(acc_name); + g_free(acc_name); + + if (acc) { + object_class_foreach(accel_init_cpu_int_aux, + CPU_RESOLVING_TYPE, false, acc); + } +} + +void accel_init_interfaces(AccelClass *ac) +{ +#ifndef CONFIG_USER_ONLY + accel_init_ops_interfaces(ac); +#endif /* !CONFIG_USER_ONLY */ + + accel_init_cpu_interfaces(ac); +} + +static const TypeInfo accel_cpu_type = { + .name = TYPE_ACCEL_CPU, + .parent = TYPE_OBJECT, + .abstract = true, + .class_size = sizeof(AccelCPUClass), +}; + +static void register_accel_types(void) +{ + type_register_static(&accel_type); + type_register_static(&accel_cpu_type); +} + +type_init(register_accel_types); diff --git a/accel/accel.c b/accel/accel-softmmu.c index cb555e3b06..50fa5acaa4 100644 --- a/accel/accel.c +++ b/accel/accel-softmmu.c @@ -1,5 +1,5 @@ /* - * QEMU System Emulator, accelerator interfaces + * QEMU accel class, system emulation components * * Copyright (c) 2003-2008 Fabrice Bellard * Copyright (c) 2014 Red Hat Inc. @@ -24,27 +24,11 @@ */ #include "qemu/osdep.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "hw/boards.h" -#include "sysemu/arch_init.h" -#include "sysemu/sysemu.h" -#include "qom/object.h" +#include "sysemu/cpus.h" -static const TypeInfo accel_type = { - .name = TYPE_ACCEL, - .parent = TYPE_OBJECT, - .class_size = sizeof(AccelClass), - .instance_size = sizeof(AccelState), -}; - -/* Lookup AccelClass from opt_name. Returns NULL if not found */ -AccelClass *accel_find(const char *opt_name) -{ - char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name); - AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name)); - g_free(class_name); - return ac; -} +#include "accel-softmmu.h" int accel_init_machine(AccelState *accel, MachineState *ms) { @@ -77,9 +61,40 @@ void accel_setup_post(MachineState *ms) } } -static void register_accel_types(void) +/* initialize the arch-independent accel operation interfaces */ +void accel_init_ops_interfaces(AccelClass *ac) { - type_register_static(&accel_type); + const char *ac_name; + char *ops_name; + AccelOpsClass *ops; + + ac_name = object_class_get_name(OBJECT_CLASS(ac)); + g_assert(ac_name != NULL); + + ops_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name); + ops = ACCEL_OPS_CLASS(object_class_by_name(ops_name)); + g_free(ops_name); + + /* + * all accelerators need to define ops, providing at least a mandatory + * non-NULL create_vcpu_thread operation. + */ + g_assert(ops != NULL); + if (ops->ops_init) { + ops->ops_init(ops); + } + cpus_register_accel(ops); } -type_init(register_accel_types); +static const TypeInfo accel_ops_type_info = { + .name = TYPE_ACCEL_OPS, + .parent = TYPE_OBJECT, + .abstract = true, + .class_size = sizeof(AccelOpsClass), +}; + +static void accel_softmmu_register_types(void) +{ + type_register_static(&accel_ops_type_info); +} +type_init(accel_softmmu_register_types); diff --git a/accel/accel-softmmu.h b/accel/accel-softmmu.h new file mode 100644 index 0000000000..5e192f1882 --- /dev/null +++ b/accel/accel-softmmu.h @@ -0,0 +1,15 @@ +/* + * QEMU System Emulation accel internal functions + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef ACCEL_SOFTMMU_H +#define ACCEL_SOFTMMU_H + +void accel_init_ops_interfaces(AccelClass *ac); + +#endif /* ACCEL_SOFTMMU_H */ diff --git a/accel/accel-user.c b/accel/accel-user.c new file mode 100644 index 0000000000..22b6a1a1a8 --- /dev/null +++ b/accel/accel-user.c @@ -0,0 +1,24 @@ +/* + * QEMU accel class, user-mode components + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/accel.h" + +AccelState *current_accel(void) +{ + static AccelState *accel; + + if (!accel) { + AccelClass *ac = accel_find("tcg"); + + g_assert(ac != NULL); + accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac))); + } + return accel; +} diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-accel-ops.c index d809b1e74c..7516c67a3f 100644 --- a/accel/kvm/kvm-cpus.c +++ b/accel/kvm/kvm-accel-ops.c @@ -74,11 +74,27 @@ static void kvm_start_vcpu_thread(CPUState *cpu) cpu, QEMU_THREAD_JOINABLE); } -const CpusAccel kvm_cpus = { - .create_vcpu_thread = kvm_start_vcpu_thread, +static void kvm_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = kvm_start_vcpu_thread; + ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset; + ops->synchronize_post_init = kvm_cpu_synchronize_post_init; + ops->synchronize_state = kvm_cpu_synchronize_state; + ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; +} + +static const TypeInfo kvm_accel_ops_type = { + .name = ACCEL_OPS_NAME("kvm"), - .synchronize_post_reset = kvm_cpu_synchronize_post_reset, - .synchronize_post_init = kvm_cpu_synchronize_post_init, - .synchronize_state = kvm_cpu_synchronize_state, - .synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm, + .parent = TYPE_ACCEL_OPS, + .class_init = kvm_accel_ops_class_init, + .abstract = true, }; + +static void kvm_accel_ops_register_types(void) +{ + type_register_static(&kvm_accel_ops_type); +} +type_init(kvm_accel_ops_register_types); diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 3feb17d965..5164d838b9 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2256,8 +2256,6 @@ static int kvm_init(MachineState *ms) ret = ram_block_discard_disable(true); assert(!ret); } - - cpus_register_accel(&kvm_cpus); return 0; err: diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 3df732b816..bf0bd1bee4 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -12,8 +12,6 @@ #include "sysemu/cpus.h" -extern const CpusAccel kvm_cpus; - int kvm_init_vcpu(CPUState *cpu, Error **errp); int kvm_cpu_exec(CPUState *cpu); void kvm_destroy_vcpu(CPUState *cpu); diff --git a/accel/kvm/meson.build b/accel/kvm/meson.build index 7e9dafe24c..8d219bea50 100644 --- a/accel/kvm/meson.build +++ b/accel/kvm/meson.build @@ -1,7 +1,7 @@ kvm_ss = ss.source_set() kvm_ss.add(files( 'kvm-all.c', - 'kvm-cpus.c', + 'kvm-accel-ops.c', )) kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c')) diff --git a/accel/meson.build b/accel/meson.build index b26cca227a..b44ba30c86 100644 --- a/accel/meson.build +++ b/accel/meson.build @@ -1,4 +1,6 @@ -softmmu_ss.add(files('accel.c')) +specific_ss.add(files('accel-common.c')) +softmmu_ss.add(files('accel-softmmu.c')) +user_ss.add(files('accel-user.c')) subdir('qtest') subdir('kvm') diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c index b282cea5cf..edb29f6fa4 100644 --- a/accel/qtest/qtest.c +++ b/accel/qtest/qtest.c @@ -17,7 +17,7 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/config-file.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/qtest.h" #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" @@ -25,14 +25,8 @@ #include "qemu/main-loop.h" #include "hw/core/cpu.h" -const CpusAccel qtest_cpus = { - .create_vcpu_thread = dummy_start_vcpu_thread, - .get_virtual_clock = qtest_get_virtual_clock, -}; - static int qtest_init_accel(MachineState *ms) { - cpus_register_accel(&qtest_cpus); return 0; } @@ -52,9 +46,26 @@ static const TypeInfo qtest_accel_type = { .class_init = qtest_accel_class_init, }; +static void qtest_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = dummy_start_vcpu_thread; + ops->get_virtual_clock = qtest_get_virtual_clock; +}; + +static const TypeInfo qtest_accel_ops_type = { + .name = ACCEL_OPS_NAME("qtest"), + + .parent = TYPE_ACCEL_OPS, + .class_init = qtest_accel_ops_class_init, + .abstract = true, +}; + static void qtest_type_init(void) { type_register_static(&qtest_accel_type); + type_register_static(&qtest_accel_ops_type); } type_init(qtest_type_init); diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 6d017e46dd..d9ef69121c 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -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" @@ -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->synchronize_from_tb) { - cc->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); @@ -262,8 +263,8 @@ static void cpu_exec_enter(CPUState *cpu) { CPUClass *cc = CPU_GET_CLASS(cpu); - if (cc->cpu_exec_enter) { - cc->cpu_exec_enter(cpu); + if (cc->tcg_ops->cpu_exec_enter) { + cc->tcg_ops->cpu_exec_enter(cpu); } } @@ -271,8 +272,8 @@ static void cpu_exec_exit(CPUState *cpu) { CPUClass *cc = CPU_GET_CLASS(cpu); - if (cc->cpu_exec_exit) { - cc->cpu_exec_exit(cpu); + if (cc->tcg_ops->cpu_exec_exit) { + cc->tcg_ops->cpu_exec_exit(cpu); } } @@ -512,8 +513,8 @@ static inline void cpu_handle_debug_exception(CPUState *cpu) } } - if (cc->debug_excp_handler) { - cc->debug_excp_handler(cpu); + if (cc->tcg_ops->debug_excp_handler) { + cc->tcg_ops->debug_excp_handler(cpu); } } @@ -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->do_interrupt(cpu); + cc->tcg_ops->do_interrupt(cpu); #endif *ret = cpu->exception_index; cpu->exception_index = -1; @@ -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->do_interrupt(cpu); + cc->tcg_ops->do_interrupt(cpu); qemu_mutex_unlock_iothread(); cpu->exception_index = -1; @@ -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->cpu_exec_interrupt && - cc->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(); } @@ -828,6 +829,34 @@ int cpu_exec(CPUState *cpu) return ret; } +void tcg_exec_realizefn(CPUState *cpu, Error **errp) +{ + static bool tcg_target_initialized; + CPUClass *cc = CPU_GET_CLASS(cpu); + + if (!tcg_target_initialized) { + cc->tcg_ops->initialize(); + tcg_target_initialized = true; + } + tlb_init(cpu); + qemu_plugin_vcpu_init_hook(cpu); + +#ifndef CONFIG_USER_ONLY + tcg_iommu_init_notifier_list(cpu); +#endif /* !CONFIG_USER_ONLY */ +} + +/* undo the initializations in reverse order */ +void tcg_exec_unrealizefn(CPUState *cpu) +{ +#ifndef CONFIG_USER_ONLY + tcg_iommu_free_notifier_list(cpu); +#endif /* !CONFIG_USER_ONLY */ + + qemu_plugin_vcpu_exit_hook(cpu); + tlb_destroy(cpu); +} + #ifndef CONFIG_USER_ONLY void dump_drift_info(void) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 7a69726ba4..8a7b779270 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -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" @@ -1305,10 +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->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) @@ -1576,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->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; diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build index f39aab0a0c..1236ac7b91 100644 --- a/accel/tcg/meson.build +++ b/accel/tcg/meson.build @@ -1,5 +1,6 @@ tcg_ss = ss.source_set() tcg_ss.add(files( + 'tcg-all.c', 'cpu-exec-common.c', 'cpu-exec.c', 'tcg-runtime-gvec.c', @@ -13,10 +14,9 @@ tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl]) specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss) specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files( - 'tcg-all.c', 'cputlb.c', - 'tcg-cpus.c', - 'tcg-cpus-mttcg.c', - 'tcg-cpus-icount.c', - 'tcg-cpus-rr.c' + 'tcg-accel-ops.c', + 'tcg-accel-ops-mttcg.c', + 'tcg-accel-ops-icount.c', + 'tcg-accel-ops-rr.c' )) diff --git a/accel/tcg/tcg-cpus-icount.c b/accel/tcg/tcg-accel-ops-icount.c index 9f45432275..87762b469c 100644 --- a/accel/tcg/tcg-cpus-icount.c +++ b/accel/tcg/tcg-accel-ops-icount.c @@ -32,9 +32,9 @@ #include "exec/exec-all.h" #include "hw/boards.h" -#include "tcg-cpus.h" -#include "tcg-cpus-icount.h" -#include "tcg-cpus-rr.h" +#include "tcg-accel-ops.h" +#include "tcg-accel-ops-icount.h" +#include "tcg-accel-ops-rr.h" static int64_t icount_get_limit(void) { @@ -93,7 +93,7 @@ void icount_prepare_for_run(CPUState *cpu) /* * These should always be cleared by icount_process_data after * each vCPU execution. However u16.high can be raised - * asynchronously by cpu_exit/cpu_interrupt/tcg_cpus_handle_interrupt + * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt */ g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0); g_assert(cpu->icount_extra == 0); @@ -125,23 +125,14 @@ void icount_process_data(CPUState *cpu) replay_mutex_unlock(); } -static void icount_handle_interrupt(CPUState *cpu, int mask) +void icount_handle_interrupt(CPUState *cpu, int mask) { int old_mask = cpu->interrupt_request; - tcg_cpus_handle_interrupt(cpu, mask); + tcg_handle_interrupt(cpu, mask); if (qemu_cpu_is_self(cpu) && !cpu->can_do_io && (mask & ~old_mask) != 0) { cpu_abort(cpu, "Raised interrupt while not in I/O function"); } } - -const CpusAccel tcg_cpus_icount = { - .create_vcpu_thread = rr_start_vcpu_thread, - .kick_vcpu_thread = rr_kick_vcpu_thread, - - .handle_interrupt = icount_handle_interrupt, - .get_virtual_clock = icount_get, - .get_elapsed_ticks = icount_get, -}; diff --git a/accel/tcg/tcg-cpus-icount.h b/accel/tcg/tcg-accel-ops-icount.h index b695939dfa..d884aa2aaa 100644 --- a/accel/tcg/tcg-cpus-icount.h +++ b/accel/tcg/tcg-accel-ops-icount.h @@ -14,4 +14,6 @@ void icount_handle_deadline(void); void icount_prepare_for_run(CPUState *cpu); void icount_process_data(CPUState *cpu); +void icount_handle_interrupt(CPUState *cpu, int mask); + #endif /* TCG_CPUS_ICOUNT_H */ diff --git a/accel/tcg/tcg-cpus-mttcg.c b/accel/tcg/tcg-accel-ops-mttcg.c index 9c3767d260..42973fb062 100644 --- a/accel/tcg/tcg-cpus-mttcg.c +++ b/accel/tcg/tcg-accel-ops-mttcg.c @@ -32,7 +32,8 @@ #include "exec/exec-all.h" #include "hw/boards.h" -#include "tcg-cpus.h" +#include "tcg-accel-ops.h" +#include "tcg-accel-ops-mttcg.h" /* * In the multi-threaded case each vCPU has its own thread. The TLS @@ -103,12 +104,12 @@ static void *mttcg_cpu_thread_fn(void *arg) return NULL; } -static void mttcg_kick_vcpu_thread(CPUState *cpu) +void mttcg_kick_vcpu_thread(CPUState *cpu) { cpu_exit(cpu); } -static void mttcg_start_vcpu_thread(CPUState *cpu) +void mttcg_start_vcpu_thread(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -131,10 +132,3 @@ static void mttcg_start_vcpu_thread(CPUState *cpu) cpu->hThread = qemu_thread_get_handle(cpu->thread); #endif } - -const CpusAccel tcg_cpus_mttcg = { - .create_vcpu_thread = mttcg_start_vcpu_thread, - .kick_vcpu_thread = mttcg_kick_vcpu_thread, - - .handle_interrupt = tcg_cpus_handle_interrupt, -}; diff --git a/accel/tcg/tcg-accel-ops-mttcg.h b/accel/tcg/tcg-accel-ops-mttcg.h new file mode 100644 index 0000000000..9fdc5a2ab5 --- /dev/null +++ b/accel/tcg/tcg-accel-ops-mttcg.h @@ -0,0 +1,19 @@ +/* + * QEMU TCG Multi Threaded vCPUs implementation + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TCG_CPUS_MTTCG_H +#define TCG_CPUS_MTTCG_H + +/* kick MTTCG vCPU thread */ +void mttcg_kick_vcpu_thread(CPUState *cpu); + +/* start an mttcg vCPU thread */ +void mttcg_start_vcpu_thread(CPUState *cpu); + +#endif /* TCG_CPUS_MTTCG_H */ diff --git a/accel/tcg/tcg-cpus-rr.c b/accel/tcg/tcg-accel-ops-rr.c index 0181d2e4eb..4a66055e0d 100644 --- a/accel/tcg/tcg-cpus-rr.c +++ b/accel/tcg/tcg-accel-ops-rr.c @@ -32,9 +32,9 @@ #include "exec/exec-all.h" #include "hw/boards.h" -#include "tcg-cpus.h" -#include "tcg-cpus-rr.h" -#include "tcg-cpus-icount.h" +#include "tcg-accel-ops.h" +#include "tcg-accel-ops-rr.h" +#include "tcg-accel-ops-icount.h" /* Kick all RR vCPUs */ void rr_kick_vcpu_thread(CPUState *unused) @@ -296,10 +296,3 @@ void rr_start_vcpu_thread(CPUState *cpu) cpu->created = true; } } - -const CpusAccel tcg_cpus_rr = { - .create_vcpu_thread = rr_start_vcpu_thread, - .kick_vcpu_thread = rr_kick_vcpu_thread, - - .handle_interrupt = tcg_cpus_handle_interrupt, -}; diff --git a/accel/tcg/tcg-cpus-rr.h b/accel/tcg/tcg-accel-ops-rr.h index 54f6ae6e86..54f6ae6e86 100644 --- a/accel/tcg/tcg-cpus-rr.h +++ b/accel/tcg/tcg-accel-ops-rr.h diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-accel-ops.c index e335f9f155..6144d9df87 100644 --- a/accel/tcg/tcg-cpus.c +++ b/accel/tcg/tcg-accel-ops.c @@ -34,7 +34,10 @@ #include "exec/exec-all.h" #include "hw/boards.h" -#include "tcg-cpus.h" +#include "tcg-accel-ops.h" +#include "tcg-accel-ops-mttcg.h" +#include "tcg-accel-ops-rr.h" +#include "tcg-accel-ops-icount.h" /* common functionality among all TCG variants */ @@ -64,7 +67,7 @@ int tcg_cpus_exec(CPUState *cpu) } /* mask must never be zero, except for A20 change call */ -void tcg_cpus_handle_interrupt(CPUState *cpu, int mask) +void tcg_handle_interrupt(CPUState *cpu, int mask) { g_assert(qemu_mutex_iothread_locked()); @@ -80,3 +83,43 @@ void tcg_cpus_handle_interrupt(CPUState *cpu, int mask) qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); } } + +static void tcg_accel_ops_init(AccelOpsClass *ops) +{ + if (qemu_tcg_mttcg_enabled()) { + ops->create_vcpu_thread = mttcg_start_vcpu_thread; + ops->kick_vcpu_thread = mttcg_kick_vcpu_thread; + ops->handle_interrupt = tcg_handle_interrupt; + } else if (icount_enabled()) { + ops->create_vcpu_thread = rr_start_vcpu_thread; + ops->kick_vcpu_thread = rr_kick_vcpu_thread; + ops->handle_interrupt = icount_handle_interrupt; + ops->get_virtual_clock = icount_get; + ops->get_elapsed_ticks = icount_get; + } else { + ops->create_vcpu_thread = rr_start_vcpu_thread; + ops->kick_vcpu_thread = rr_kick_vcpu_thread; + ops->handle_interrupt = tcg_handle_interrupt; + } +} + +static void tcg_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->ops_init = tcg_accel_ops_init; +} + +static const TypeInfo tcg_accel_ops_type = { + .name = ACCEL_OPS_NAME("tcg"), + + .parent = TYPE_ACCEL_OPS, + .class_init = tcg_accel_ops_class_init, + .abstract = true, +}; + +static void tcg_accel_ops_register_types(void) +{ + type_register_static(&tcg_accel_ops_type); +} +type_init(tcg_accel_ops_register_types); diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-accel-ops.h index d6893a32f8..48130006de 100644 --- a/accel/tcg/tcg-cpus.h +++ b/accel/tcg/tcg-accel-ops.h @@ -14,12 +14,8 @@ #include "sysemu/cpus.h" -extern const CpusAccel tcg_cpus_mttcg; -extern const CpusAccel tcg_cpus_icount; -extern const CpusAccel tcg_cpus_rr; - void tcg_cpus_destroy(CPUState *cpu); int tcg_cpus_exec(CPUState *cpu); -void tcg_cpus_handle_interrupt(CPUState *cpu, int mask); +void tcg_handle_interrupt(CPUState *cpu, int mask); #endif /* TCG_CPUS_H */ diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index 2eea8c32ee..e378c2db73 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -30,9 +30,8 @@ #include "tcg/tcg.h" #include "qapi/error.h" #include "qemu/error-report.h" -#include "hw/boards.h" +#include "qemu/accel.h" #include "qapi/qapi-builtin-visit.h" -#include "tcg-cpus.h" struct TCGState { AccelState parent_obj; @@ -97,7 +96,7 @@ static void tcg_accel_instance_init(Object *obj) s->mttcg_enabled = default_mttcg_enabled(); /* If debugging enabled, default "auto on", otherwise off. */ -#ifdef CONFIG_DEBUG_TCG +#if defined(CONFIG_DEBUG_TCG) && !defined(CONFIG_USER_ONLY) s->splitwx_enabled = -1; #else s->splitwx_enabled = 0; @@ -114,17 +113,15 @@ static int tcg_init(MachineState *ms) mttcg_enabled = s->mttcg_enabled; /* - * Initialize TCG regions + * Initialize TCG regions only for softmmu. + * + * This needs to be done later for user mode, because the prologue + * generation needs to be delayed so that GUEST_BASE is already set. */ +#ifndef CONFIG_USER_ONLY tcg_region_init(); +#endif /* !CONFIG_USER_ONLY */ - if (mttcg_enabled) { - cpus_register_accel(&tcg_cpus_mttcg); - } else if (icount_enabled()) { - cpus_register_accel(&tcg_cpus_icount); - } else { - cpus_register_accel(&tcg_cpus_rr); - } return 0; } diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 1215b55ca0..0b6f56ca40 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -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" @@ -187,7 +188,8 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info, clear_helper_retaddr(); cc = CPU_GET_CLASS(cpu); - cc->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(); } @@ -217,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->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(); } } diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c index 878a4089d9..e9d2d6aaaa 100644 --- a/accel/xen/xen-all.c +++ b/accel/xen/xen-all.c @@ -15,7 +15,7 @@ #include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen_pt.h" #include "chardev/char.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/cpus.h" #include "sysemu/xen.h" #include "sysemu/runstate.h" @@ -154,10 +154,6 @@ static void xen_setup_post(MachineState *ms, AccelState *accel) } } -const CpusAccel xen_cpus = { - .create_vcpu_thread = dummy_start_vcpu_thread, -}; - static int xen_init(MachineState *ms) { MachineClass *mc = MACHINE_GET_CLASS(ms); @@ -185,9 +181,6 @@ static int xen_init(MachineState *ms) * opt out of system RAM being allocated by generic code */ mc->default_ram_id = NULL; - - cpus_register_accel(&xen_cpus); - return 0; } @@ -222,9 +215,24 @@ static const TypeInfo xen_accel_type = { .class_init = xen_accel_class_init, }; +static void xen_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = dummy_start_vcpu_thread; +} + +static const TypeInfo xen_accel_ops_type = { + .name = ACCEL_OPS_NAME("xen"), + + .parent = TYPE_ACCEL_OPS, + .class_init = xen_accel_ops_class_init, + .abstract = true, +}; + static void xen_type_init(void) { type_register_static(&xen_accel_type); + type_register_static(&xen_accel_ops_type); } - type_init(xen_type_init); diff --git a/bsd-user/main.c b/bsd-user/main.c index 65163e1396..7cc08024e3 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/units.h" +#include "qemu/accel.h" #include "sysemu/tcg.h" #include "qemu-version.h" #include <machine/trap.h> @@ -908,10 +909,14 @@ int main(int argc, char **argv) #endif } + cpu_type = parse_cpu_option(cpu_model); /* init tcg before creating CPUs and to get qemu_host_page_size */ - tcg_exec_init(0, false); + { + AccelClass *ac = ACCEL_GET_CLASS(current_accel()); - cpu_type = parse_cpu_option(cpu_model); + ac->init_machine(NULL); + accel_init_interfaces(ac); + } cpu = cpu_create(cpu_type); env = cpu->env_ptr; #if defined(TARGET_SPARC) || defined(TARGET_PPC) @@ -1110,9 +1110,9 @@ for opt do ;; --enable-whpx) whpx="enabled" ;; - --disable-tcg-interpreter) tcg_interpreter="true" + --disable-tcg-interpreter) tcg_interpreter="false" ;; - --enable-tcg-interpreter) tcg_interpreter="false" + --enable-tcg-interpreter) tcg_interpreter="true" ;; --disable-cap-ng) cap_ng="disabled" ;; @@ -6417,6 +6417,7 @@ NINJA=$ninja $meson setup \ -Dvhost_user_blk_server=$vhost_user_blk_server \ -Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi \ $(if test "$default_features" = no; then echo "-Dauto_features=disabled"; fi) \ + -Dtcg_interpreter=$tcg_interpreter \ $cross_arg \ "$PWD" "$source_path" @@ -124,12 +124,34 @@ const VMStateDescription vmstate_cpu_common = { }; #endif -void cpu_exec_unrealizefn(CPUState *cpu) +void cpu_exec_realizefn(CPUState *cpu, Error **errp) { CPUClass *cc = CPU_GET_CLASS(cpu); - tlb_destroy(cpu); - cpu_list_remove(cpu); + cpu_list_add(cpu); + +#ifdef CONFIG_TCG + /* NB: errp parameter is unused currently */ + if (tcg_enabled()) { + tcg_exec_realizefn(cpu, errp); + } +#endif /* CONFIG_TCG */ + +#ifdef CONFIG_USER_ONLY + assert(cc->vmsd == NULL); +#else + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { + vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); + } + if (cc->vmsd != NULL) { + vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); + } +#endif /* CONFIG_USER_ONLY */ +} + +void cpu_exec_unrealizefn(CPUState *cpu) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); #ifdef CONFIG_USER_ONLY assert(cc->vmsd == NULL); @@ -140,8 +162,15 @@ void cpu_exec_unrealizefn(CPUState *cpu) if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { vmstate_unregister(NULL, &vmstate_cpu_common, cpu); } - tcg_iommu_free_notifier_list(cpu); #endif +#ifdef CONFIG_TCG + /* NB: errp parameter is unused currently */ + if (tcg_enabled()) { + tcg_exec_unrealizefn(cpu); + } +#endif /* CONFIG_TCG */ + + cpu_list_remove(cpu); } void cpu_exec_initfn(CPUState *cpu) @@ -156,35 +185,6 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -void cpu_exec_realizefn(CPUState *cpu, Error **errp) -{ - CPUClass *cc = CPU_GET_CLASS(cpu); - static bool tcg_target_initialized; - - cpu_list_add(cpu); - - if (tcg_enabled() && !tcg_target_initialized) { - tcg_target_initialized = true; - cc->tcg_initialize(); - } - tlb_init(cpu); - - qemu_plugin_vcpu_init_hook(cpu); - -#ifdef CONFIG_USER_ONLY - assert(cc->vmsd == NULL); -#else /* !CONFIG_USER_ONLY */ - if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { - vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); - } - if (cc->vmsd != NULL) { - vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); - } - - tcg_iommu_init_notifier_list(cpu); -#endif -} - const char *parse_cpu_option(const char *cpu_option) { ObjectClass *oc; diff --git a/hw/core/cpu.c b/hw/core/cpu.c index 7553411653..00330ba07d 100644 --- a/hw/core/cpu.c +++ b/hw/core/cpu.c @@ -186,19 +186,15 @@ static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg) return 0; } -static bool cpu_common_debug_check_watchpoint(CPUState *cpu, CPUWatchpoint *wp) -{ - /* If no extra check is required, QEMU watchpoint match can be considered - * as an architectural match. - */ - return true; -} - static bool cpu_common_virtio_is_big_endian(CPUState *cpu) { return target_words_bigendian(); } +/* + * XXX the following #if is always true because this is a common_ss + * module, so target CONFIG_* is never defined. + */ #if !defined(CONFIG_USER_ONLY) GuestPanicInformation *cpu_get_crash_info(CPUState *cpu) { @@ -340,9 +336,9 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) static void cpu_common_unrealizefn(DeviceState *dev) { CPUState *cpu = CPU(dev); + /* NOTE: latest generic point before the cpu is fully unrealized */ trace_fini_vcpu(cpu); - qemu_plugin_vcpu_exit_hook(cpu); cpu_exec_unrealizefn(cpu); } @@ -379,11 +375,6 @@ static int64_t cpu_common_get_arch_id(CPUState *cpu) return cpu->cpu_index; } -static vaddr cpu_adjust_watchpoint_address(CPUState *cpu, vaddr addr, int len) -{ - return addr; -} - static Property cpu_common_props[] = { #ifndef CONFIG_USER_ONLY /* Create a memory property for softmmu CPU object, @@ -416,8 +407,6 @@ static void cpu_class_init(ObjectClass *klass, void *data) k->gdb_read_register = cpu_common_gdb_read_register; k->gdb_write_register = cpu_common_gdb_write_register; k->virtio_is_big_endian = cpu_common_virtio_is_big_endian; - k->debug_check_watchpoint = cpu_common_debug_check_watchpoint; - k->adjust_watchpoint_address = cpu_adjust_watchpoint_address; set_bit(DEVICE_CATEGORY_CPU, dc->categories); dc->realize = cpu_common_realizefn; dc->unrealize = cpu_common_unrealizefn; diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index f9442731dd..83c8086062 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -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, @@ -116,6 +119,8 @@ static const MemoryRegionOps dma_dummy_ops = { #define MAGNUM_BIOS_SIZE_MAX 0x7e000 #define MAGNUM_BIOS_SIZE \ (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX) + +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) static void (*real_do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, @@ -137,6 +142,7 @@ static void mips_jazz_do_transaction_failed(CPUState *cs, hwaddr physaddr, (*real_do_transaction_failed)(cs, physaddr, addr, size, access_type, mmu_idx, attrs, response, retaddr); } +#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ static void mips_jazz_init(MachineState *machine, enum jazz_model_e jazz_model) @@ -205,8 +211,10 @@ static void mips_jazz_init(MachineState *machine, * memory region that catches all memory accesses, as we do on Malta. */ cc = CPU_GET_CLASS(cpu); - real_do_transaction_failed = cc->do_transaction_failed; - cc->do_transaction_failed = mips_jazz_do_transaction_failed; +#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; +#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ /* allocate RAM */ memory_region_add_subregion(address_space, 0, machine->ram); diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 4b5408c341..cfb1d79331 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -410,19 +410,26 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) } #ifdef CONFIG_TCG +/* accel/tcg/cpu-exec.c */ void dump_drift_info(void); +/* accel/tcg/translate-all.c */ void dump_exec_info(void); void dump_opcount_info(void); #endif /* CONFIG_TCG */ #endif /* !CONFIG_USER_ONLY */ +#ifdef CONFIG_TCG +/* accel/tcg/cpu-exec.c */ +int cpu_exec(CPUState *cpu); +void tcg_exec_realizefn(CPUState *cpu, Error **errp); +void tcg_exec_unrealizefn(CPUState *cpu); +#endif /* CONFIG_TCG */ + /* Returns: 0 on success, -1 on error */ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, void *ptr, target_ulong len, bool is_write); -int cpu_exec(CPUState *cpu); - /** * cpu_set_cpustate_pointers(cpu) * @cpu: The cpu object diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index d1f5e3fc3d..ba3cd32a1e 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -25,9 +25,6 @@ #include "qemu/host-utils.h" #include "qemu/thread.h" -#ifdef CONFIG_TCG -#include "tcg-target.h" -#endif #ifndef CONFIG_USER_ONLY #include "exec/hwaddr.h" #endif diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 125000bcf7..f933c74c44 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -544,7 +544,7 @@ void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr); /* GETPC is the true target of the return instruction that we'll execute. */ #if defined(CONFIG_TCG_INTERPRETER) -extern uintptr_t tci_tb_ptr; +extern __thread uintptr_t tci_tb_ptr; # define GETPC() tci_tb_ptr #else # define GETPC() \ diff --git a/include/hw/boards.h b/include/hw/boards.h index 17b1f3f0b9..85af4faf76 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -6,7 +6,7 @@ #include "exec/memory.h" #include "sysemu/hostmem.h" #include "sysemu/blockdev.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "qapi/qapi-types-machine.h" #include "qemu/module.h" #include "qom/object.h" diff --git a/include/hw/core/accel-cpu.h b/include/hw/core/accel-cpu.h new file mode 100644 index 0000000000..24a6697412 --- /dev/null +++ b/include/hw/core/accel-cpu.h @@ -0,0 +1,38 @@ +/* + * Accelerator interface, specializes CPUClass + * This header is used only by target-specific code. + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef ACCEL_CPU_H +#define ACCEL_CPU_H + +/* + * This header is used to define new accelerator-specific target-specific + * accelerator cpu subclasses. + * It uses CPU_RESOLVING_TYPE, so this is clearly target-specific. + * + * Do not try to use for any other purpose than the implementation of new + * subclasses in target/, or the accel implementation itself in accel/ + */ + +#define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE +#define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU) +typedef struct AccelCPUClass AccelCPUClass; +DECLARE_CLASS_CHECKERS(AccelCPUClass, ACCEL_CPU, TYPE_ACCEL_CPU) + +typedef struct AccelCPUClass { + /*< private >*/ + ObjectClass parent_class; + /*< public >*/ + + void (*cpu_class_init)(CPUClass *cc); + void (*cpu_instance_init)(CPUState *cpu); + void (*cpu_realizefn)(CPUState *cpu, Error **errp); +} AccelCPUClass; + +#endif /* ACCEL_CPU_H */ diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 140fa32a5e..38d813c389 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -76,6 +76,12 @@ typedef struct CPUWatchpoint CPUWatchpoint; struct TranslationBlock; +/* see tcg-cpu-ops.h */ +struct TCGCPUOps; + +/* see accel-cpu.h */ +struct AccelCPUClass; + /** * CPUClass: * @class_by_name: Callback to map -cpu command line model name to an @@ -83,11 +89,6 @@ struct TranslationBlock; * @parse_features: Callback to parse command line arguments. * @reset_dump_flags: #CPUDumpFlags to use for reset logging. * @has_work: Callback for checking if there is work to do. - * @do_interrupt: Callback for interrupt handling. - * @do_unaligned_access: Callback for unaligned access handling, if - * the target defines #TARGET_ALIGNED_ONLY. - * @do_transaction_failed: Callback for handling failed memory transactions - * (ie bus faults or external aborts; not MMU faults) * @virtio_is_big_endian: Callback to return %true if a CPU which supports * runtime configurable endianness is currently big-endian. Non-configurable * CPUs can use the default implementation of this method. This method should @@ -106,19 +107,6 @@ struct TranslationBlock; * If the target behaviour here is anything other than "set * the PC register to the value passed in" then the target must * also implement the synchronize_from_tb hook. - * @synchronize_from_tb: Callback for synchronizing 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. - * This always includes at least the program counter; some targets - * will need to do more. If this hook is not implemented then the - * default is to call @set_pc(tb->pc). - * @tlb_fill: Callback for handling 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. * @get_phys_page_debug: Callback for obtaining a physical address. * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the * associated memory transaction attributes to use for the access. @@ -128,9 +116,6 @@ struct TranslationBlock; * a memory access with the specified memory transaction attributes. * @gdb_read_register: Callback for letting GDB read a register. * @gdb_write_register: Callback for letting GDB write a register. - * @debug_check_watchpoint: Callback: return true if the architectural - * watchpoint whose address has matched should really fire. - * @debug_excp_handler: Callback for handling debug exceptions. * @write_elf64_note: Callback for writing a CPU-specific ELF note to a * 64-bit VM coredump. * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF @@ -149,9 +134,6 @@ struct TranslationBlock; * @gdb_get_dynamic_xml: Callback to return dynamically generated XML for the * gdb stub. Returns a pointer to the XML contents for the specified XML file * or NULL if the CPU doesn't have a dynamically generated content for it. - * @cpu_exec_enter: Callback for cpu_exec preparation. - * @cpu_exec_exit: Callback for cpu_exec cleanup. - * @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec. * @disas_set_info: Setup architecture specific components of disassembly info * @adjust_watchpoint_address: Perform a target-specific adjustment to an * address before attempting to match it against watchpoints. @@ -170,14 +152,6 @@ struct CPUClass { int reset_dump_flags; bool (*has_work)(CPUState *cpu); - void (*do_interrupt)(CPUState *cpu); - void (*do_unaligned_access)(CPUState *cpu, vaddr addr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr); - 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); bool (*virtio_is_big_endian)(CPUState *cpu); int (*memory_rw_debug)(CPUState *cpu, vaddr addr, uint8_t *buf, int len, bool is_write); @@ -189,19 +163,12 @@ struct CPUClass { void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list, Error **errp); void (*set_pc)(CPUState *cpu, vaddr value); - void (*synchronize_from_tb)(CPUState *cpu, - const struct TranslationBlock *tb); - bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs); int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg); int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); - bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp); - void (*debug_excp_handler)(CPUState *cpu); int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu, int cpuid, void *opaque); @@ -216,18 +183,17 @@ struct CPUClass { const char *gdb_core_xml_file; gchar * (*gdb_arch_name)(CPUState *cpu); const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname); - void (*cpu_exec_enter)(CPUState *cpu); - void (*cpu_exec_exit)(CPUState *cpu); - bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request); void (*disas_set_info)(CPUState *cpu, disassemble_info *info); - vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len); - void (*tcg_initialize)(void); const char *deprecation_note; /* Keep non-pointer data at the end to minimize holes. */ int gdb_num_core_regs; bool gdb_stop_before_watchpoint; + struct AccelCPUClass *accel_cpu; + + /* when TCG is not available, this pointer is NULL */ + struct TCGCPUOps *tcg_ops; }; /* @@ -858,36 +824,6 @@ CPUState *cpu_by_arch_id(int64_t id); void cpu_interrupt(CPUState *cpu, int mask); -#ifdef NEED_CPU_H - -#ifdef CONFIG_SOFTMMU -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->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->do_transaction_failed) { - cc->do_transaction_failed(cpu, physaddr, addr, size, access_type, - mmu_idx, attrs, response, retaddr); - } -} -#endif - -#endif /* NEED_CPU_H */ - /** * cpu_set_pc: * @cpu: The CPU to set the program counter for. @@ -1112,6 +1048,8 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx); void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...) GCC_FMT_ATTR(2, 3); + +/* $(top_srcdir)/cpu.c */ void cpu_exec_initfn(CPUState *cpu); void cpu_exec_realizefn(CPUState *cpu, Error **errp); void cpu_exec_unrealizefn(CPUState *cpu); diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h new file mode 100644 index 0000000000..ccc97d1894 --- /dev/null +++ b/include/hw/core/tcg-cpu-ops.h @@ -0,0 +1,97 @@ +/* + * TCG CPU-specific operations + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TCG_CPU_OPS_H +#define TCG_CPU_OPS_H + +#include "hw/core/cpu.h" + +struct TCGCPUOps { + /** + * @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. + * + * note that this is in general SOFTMMU only, but it actually isn't + * because of an x86 hack (accel/tcg/cpu-exec.c), so we cannot put it + * in the SOFTMMU section in general. + */ + 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); + +#ifdef NEED_CPU_H +#ifdef CONFIG_SOFTMMU + /** + * @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); + +#endif /* CONFIG_SOFTMMU */ +#endif /* NEED_CPU_H */ + +}; + +#endif /* TCG_CPU_OPS_H */ diff --git a/include/sysemu/accel.h b/include/qemu/accel.h index e08b8ab8fa..b9d6d69eb8 100644 --- a/include/sysemu/accel.h +++ b/include/qemu/accel.h @@ -20,8 +20,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef HW_ACCEL_H -#define HW_ACCEL_H +#ifndef QEMU_ACCEL_H +#define QEMU_ACCEL_H #include "qom/object.h" #include "exec/hwaddr.h" @@ -37,8 +37,8 @@ typedef struct AccelClass { /*< public >*/ const char *name; -#ifndef CONFIG_USER_ONLY int (*init_machine)(MachineState *ms); +#ifndef CONFIG_USER_ONLY void (*setup_post)(MachineState *ms, AccelState *accel); bool (*has_memory)(MachineState *ms, AddressSpace *as, hwaddr start_addr, hwaddr size); @@ -67,11 +67,15 @@ typedef struct AccelClass { OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL) AccelClass *accel_find(const char *opt_name); +AccelState *current_accel(void); + +void accel_init_interfaces(AccelClass *ac); + +#ifndef CONFIG_USER_ONLY int accel_init_machine(AccelState *accel, MachineState *ms); /* Called just before os_setup_post (ie just before drop OS privs) */ void accel_setup_post(MachineState *ms); +#endif /* !CONFIG_USER_ONLY */ -AccelState *current_accel(void); - -#endif +#endif /* QEMU_ACCEL_H */ diff --git a/include/sysemu/accel-ops.h b/include/sysemu/accel-ops.h new file mode 100644 index 0000000000..032f6979d7 --- /dev/null +++ b/include/sysemu/accel-ops.h @@ -0,0 +1,45 @@ +/* + * Accelerator OPS, used for cpus.c module + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef ACCEL_OPS_H +#define ACCEL_OPS_H + +#include "qom/object.h" + +#define ACCEL_OPS_SUFFIX "-ops" +#define TYPE_ACCEL_OPS "accel" ACCEL_OPS_SUFFIX +#define ACCEL_OPS_NAME(name) (name "-" TYPE_ACCEL_OPS) + +typedef struct AccelOpsClass AccelOpsClass; +DECLARE_CLASS_CHECKERS(AccelOpsClass, ACCEL_OPS, TYPE_ACCEL_OPS) + +/* cpus.c operations interface */ +struct AccelOpsClass { + /*< private >*/ + ObjectClass parent_class; + /*< public >*/ + + /* initialization function called when accel is chosen */ + void (*ops_init)(AccelOpsClass *ops); + + void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */ + void (*kick_vcpu_thread)(CPUState *cpu); + + void (*synchronize_post_reset)(CPUState *cpu); + void (*synchronize_post_init)(CPUState *cpu); + void (*synchronize_state)(CPUState *cpu); + void (*synchronize_pre_loadvm)(CPUState *cpu); + + void (*handle_interrupt)(CPUState *cpu, int mask); + + int64_t (*get_virtual_clock)(void); + int64_t (*get_elapsed_ticks)(void); +}; + +#endif /* ACCEL_OPS_H */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index e8156728c6..2cd74392e0 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -2,30 +2,14 @@ #define QEMU_CPUS_H #include "qemu/timer.h" +#include "sysemu/accel-ops.h" -/* cpus.c */ +/* register accel-specific operations */ +void cpus_register_accel(const AccelOpsClass *i); -/* CPU execution threads */ +/* accel/dummy-cpus.c */ -typedef struct CpusAccel { - void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */ - void (*kick_vcpu_thread)(CPUState *cpu); - - void (*synchronize_post_reset)(CPUState *cpu); - void (*synchronize_post_init)(CPUState *cpu); - void (*synchronize_state)(CPUState *cpu); - void (*synchronize_pre_loadvm)(CPUState *cpu); - - void (*handle_interrupt)(CPUState *cpu, int mask); - - int64_t (*get_virtual_clock)(void); - int64_t (*get_elapsed_ticks)(void); -} CpusAccel; - -/* register accel-specific cpus interface implementation */ -void cpus_register_accel(const CpusAccel *i); - -/* Create a dummy vcpu for CpusAccel->create_vcpu_thread */ +/* Create a dummy vcpu for AccelOpsClass->create_vcpu_thread */ void dummy_start_vcpu_thread(CPUState *); /* interface available for cpus accelerator threads */ diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index f893768df9..c98636bc81 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -13,7 +13,7 @@ #ifndef HVF_H #define HVF_H -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "qom/object.h" #ifdef CONFIG_HVF diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index bb5d5cf497..739682f3c3 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -17,7 +17,7 @@ #include "qemu/queue.h" #include "hw/core/cpu.h" #include "exec/memattrs.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "qom/object.h" #ifdef NEED_CPU_H diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h index 65740806da..ccb8869f01 100644 --- a/include/sysemu/kvm_int.h +++ b/include/sysemu/kvm_int.h @@ -10,7 +10,7 @@ #define QEMU_KVM_INT_H #include "exec/memory.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/kvm.h" typedef struct KVMSlot diff --git a/linux-user/main.c b/linux-user/main.c index bb4e55e8fc..2e3c169878 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/units.h" +#include "qemu/accel.h" #include "sysemu/tcg.h" #include "qemu-version.h" #include <sys/syscall.h> @@ -701,8 +702,12 @@ int main(int argc, char **argv, char **envp) cpu_type = parse_cpu_option(cpu_model); /* init tcg before creating CPUs and to get qemu_host_page_size */ - tcg_exec_init(0, false); + { + AccelClass *ac = ACCEL_GET_CLASS(current_accel()); + ac->init_machine(NULL); + accel_init_interfaces(ac); + } cpu = cpu_create(cpu_type); env = cpu->env_ptr; cpu_reset(cpu); diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 1dc20b9dc3..112eba9d54 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -128,7 +128,7 @@ void hw_error(const char *fmt, ...) /* * The chosen accelerator is supposed to register this. */ -static const CpusAccel *cpus_accel; +static const AccelOpsClass *cpus_accel; void cpu_synchronize_all_states(void) { @@ -594,11 +594,11 @@ void cpu_remove_sync(CPUState *cpu) qemu_mutex_lock_iothread(); } -void cpus_register_accel(const CpusAccel *ca) +void cpus_register_accel(const AccelOpsClass *ops) { - assert(ca != NULL); - assert(ca->create_vcpu_thread != NULL); /* mandatory */ - cpus_accel = ca; + assert(ops != NULL); + assert(ops->create_vcpu_thread != NULL); /* mandatory */ + cpus_accel = ops; } void qemu_init_vcpu(CPUState *cpu) @@ -618,7 +618,7 @@ void qemu_init_vcpu(CPUState *cpu) cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory); } - /* accelerators all implement the CpusAccel interface */ + /* accelerators all implement the AccelOpsClass */ g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL); cpus_accel->create_vcpu_thread(cpu); diff --git a/softmmu/memory.c b/softmmu/memory.c index 676c298b60..c0c814fbb9 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -32,7 +32,7 @@ #include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "sysemu/tcg.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "hw/boards.h" #include "migration/vmstate.h" diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 60760a3bdc..243c3097d3 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -24,6 +24,11 @@ #include "qemu/cutils.h" #include "qemu/cacheflush.h" #include "cpu.h" + +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +#endif /* CONFIG_TCG */ + #include "exec/exec-all.h" #include "exec/target_page.h" #include "hw/qdev-core.h" @@ -840,6 +845,7 @@ void cpu_watchpoint_remove_all(CPUState *cpu, int mask) } } +#ifdef CONFIG_TCG /* Return true if this watchpoint address matches the specified * access (ie the address range covered by the watchpoint overlaps * partially or completely with the address range covered by the @@ -873,6 +879,80 @@ int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len) return ret; } +/* Generate a debug exception if a watchpoint has been hit. */ +void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, + MemTxAttrs attrs, int flags, uintptr_t ra) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + CPUWatchpoint *wp; + + assert(tcg_enabled()); + if (cpu->watchpoint_hit) { + /* + * We re-entered the check after replacing the TB. + * Now raise the debug interrupt so that it will + * trigger after the current instruction. + */ + qemu_mutex_lock_iothread(); + cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG); + qemu_mutex_unlock_iothread(); + return; + } + + if (cc->tcg_ops->adjust_watchpoint_address) { + /* this is currently used only by ARM BE32 */ + addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len); + } + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { + if (watchpoint_address_matches(wp, addr, len) + && (wp->flags & flags)) { + if (replay_running_debug()) { + /* + * Don't process the watchpoints when we are + * in a reverse debugging operation. + */ + replay_breakpoint(); + return; + } + if (flags == BP_MEM_READ) { + wp->flags |= BP_WATCHPOINT_HIT_READ; + } else { + wp->flags |= BP_WATCHPOINT_HIT_WRITE; + } + wp->hitaddr = MAX(addr, wp->vaddr); + wp->hitattrs = attrs; + if (!cpu->watchpoint_hit) { + if (wp->flags & BP_CPU && cc->tcg_ops->debug_check_watchpoint && + !cc->tcg_ops->debug_check_watchpoint(cpu, wp)) { + wp->flags &= ~BP_WATCHPOINT_HIT; + continue; + } + cpu->watchpoint_hit = wp; + + mmap_lock(); + tb_check_watchpoint(cpu, ra); + if (wp->flags & BP_STOP_BEFORE_ACCESS) { + cpu->exception_index = EXCP_DEBUG; + mmap_unlock(); + cpu_loop_exit_restore(cpu, ra); + } else { + /* Force execution of one insn next time. */ + cpu->cflags_next_tb = 1 | curr_cflags(); + mmap_unlock(); + if (ra) { + cpu_restore_state(cpu, ra, true); + } + cpu_loop_exit_noexc(cpu); + } + } + } else { + wp->flags &= ~BP_WATCHPOINT_HIT; + } + } +} + +#endif /* CONFIG_TCG */ + /* Called from RCU critical section */ static RAMBlock *qemu_get_ram_block(ram_addr_t addr) { @@ -2359,75 +2439,6 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr) return block->offset + offset; } -/* Generate a debug exception if a watchpoint has been hit. */ -void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, - MemTxAttrs attrs, int flags, uintptr_t ra) -{ - CPUClass *cc = CPU_GET_CLASS(cpu); - CPUWatchpoint *wp; - - assert(tcg_enabled()); - if (cpu->watchpoint_hit) { - /* - * We re-entered the check after replacing the TB. - * Now raise the debug interrupt so that it will - * trigger after the current instruction. - */ - qemu_mutex_lock_iothread(); - cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG); - qemu_mutex_unlock_iothread(); - return; - } - - addr = cc->adjust_watchpoint_address(cpu, addr, len); - QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - if (watchpoint_address_matches(wp, addr, len) - && (wp->flags & flags)) { - if (replay_running_debug()) { - /* - * Don't process the watchpoints when we are - * in a reverse debugging operation. - */ - replay_breakpoint(); - return; - } - if (flags == BP_MEM_READ) { - wp->flags |= BP_WATCHPOINT_HIT_READ; - } else { - wp->flags |= BP_WATCHPOINT_HIT_WRITE; - } - wp->hitaddr = MAX(addr, wp->vaddr); - wp->hitattrs = attrs; - if (!cpu->watchpoint_hit) { - if (wp->flags & BP_CPU && - !cc->debug_check_watchpoint(cpu, wp)) { - wp->flags &= ~BP_WATCHPOINT_HIT; - continue; - } - cpu->watchpoint_hit = wp; - - mmap_lock(); - tb_check_watchpoint(cpu, ra); - if (wp->flags & BP_STOP_BEFORE_ACCESS) { - cpu->exception_index = EXCP_DEBUG; - mmap_unlock(); - cpu_loop_exit_restore(cpu, ra); - } else { - /* Force execution of one insn next time. */ - cpu->cflags_next_tb = 1 | curr_cflags(); - mmap_unlock(); - if (ra) { - cpu_restore_state(cpu, ra, true); - } - cpu_loop_exit_noexc(cpu); - } - } - } else { - wp->flags &= ~BP_WATCHPOINT_HIT; - } - } -} - static MemTxResult flatview_read(FlatView *fv, hwaddr addr, MemTxAttrs attrs, void *buf, hwaddr len); static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs, diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 7965dc9a16..130c366615 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -20,7 +20,7 @@ #include "exec/ioport.h" #include "exec/memory.h" #include "hw/irq.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/cpu-timers.h" #include "qemu/config-file.h" #include "qemu/option.h" diff --git a/softmmu/vl.c b/softmmu/vl.c index bd55468669..2bf94ece9c 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -44,7 +44,7 @@ #include "qemu/error-report.h" #include "qemu/sockets.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "hw/usb.h" #include "hw/isa/isa.h" #include "hw/scsi/scsi.h" @@ -1726,7 +1726,8 @@ static bool object_create_early(const char *type, QemuOpts *opts) return false; } - /* Allocation of large amounts of memory may delay + /* + * Allocation of large amounts of memory may delay * chardev initialization for too long, and trigger timeouts * on software that waits for a monitor socket to be created * (e.g. libvirt). @@ -3497,7 +3498,7 @@ void qemu_init(int argc, char **argv, char **envp) * * Machine compat properties: object_set_machine_compat_props(). * Accelerator compat props: object_set_accelerator_compat_props(), - * called from configure_accelerator(). + * called from do_configure_accelerator(). */ machine_class = MACHINE_GET_CLASS(current_machine); @@ -3519,6 +3520,8 @@ void qemu_init(int argc, char **argv, char **envp) if (cpu_option) { current_machine->cpu_type = parse_cpu_option(cpu_option); } + /* NB: for machine none cpu_type could STILL be NULL here! */ + accel_init_interfaces(ACCEL_GET_CLASS(current_machine->accelerator)); qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c index b3fd6643e8..27192b62e2 100644 --- a/target/alpha/cpu.c +++ b/target/alpha/cpu.c @@ -206,6 +206,20 @@ static void alpha_cpu_initfn(Object *obj) #endif } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps alpha_tcg_ops = { + .initialize = alpha_translate_init, + .cpu_exec_interrupt = alpha_cpu_exec_interrupt, + .tlb_fill = alpha_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = alpha_cpu_do_interrupt, + .do_transaction_failed = alpha_cpu_do_transaction_failed, + .do_unaligned_access = alpha_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void alpha_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -217,22 +231,17 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = alpha_cpu_class_by_name; cc->has_work = alpha_cpu_has_work; - cc->do_interrupt = alpha_cpu_do_interrupt; - cc->cpu_exec_interrupt = alpha_cpu_exec_interrupt; cc->dump_state = alpha_cpu_dump_state; cc->set_pc = alpha_cpu_set_pc; cc->gdb_read_register = alpha_cpu_gdb_read_register; cc->gdb_write_register = alpha_cpu_gdb_write_register; - cc->tlb_fill = alpha_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY - cc->do_transaction_failed = alpha_cpu_do_transaction_failed; - cc->do_unaligned_access = alpha_cpu_do_unaligned_access; cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug; dc->vmsd = &vmstate_alpha_cpu; #endif cc->disas_set_info = alpha_cpu_disas_set_info; - cc->tcg_initialize = alpha_translate_init; + cc->tcg_ops = &alpha_tcg_ops; cc->gdb_num_core_regs = 67; } diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 40142ac141..8ddb2556f8 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -26,6 +26,9 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "cpu.h" +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +#endif /* CONFIG_TCG */ #include "internals.h" #include "exec/exec-all.h" #include "hw/qdev-properties.h" @@ -54,8 +57,9 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) } } -static void arm_cpu_synchronize_from_tb(CPUState *cs, - const TranslationBlock *tb) +#ifdef CONFIG_TCG +void arm_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb) { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -70,6 +74,7 @@ static void arm_cpu_synchronize_from_tb(CPUState *cs, env->regs[15] = tb->pc; } } +#endif /* CONFIG_TCG */ static bool arm_cpu_has_work(CPUState *cs) { @@ -588,7 +593,7 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) found: cs->exception_index = excp_idx; env->exception.target_el = target_el; - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); return true; } @@ -2240,6 +2245,24 @@ static gchar *arm_gdb_arch_name(CPUState *cs) return g_strdup("arm"); } +#ifdef CONFIG_TCG +static struct TCGCPUOps arm_tcg_ops = { + .initialize = arm_translate_init, + .synchronize_from_tb = arm_cpu_synchronize_from_tb, + .cpu_exec_interrupt = arm_cpu_exec_interrupt, + .tlb_fill = arm_cpu_tlb_fill, + .debug_excp_handler = arm_debug_excp_handler, + +#if !defined(CONFIG_USER_ONLY) + .do_interrupt = arm_cpu_do_interrupt, + .do_transaction_failed = arm_cpu_do_transaction_failed, + .do_unaligned_access = arm_cpu_do_unaligned_access, + .adjust_watchpoint_address = arm_adjust_watchpoint_address, + .debug_check_watchpoint = arm_debug_check_watchpoint, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void arm_cpu_class_init(ObjectClass *oc, void *data) { ARMCPUClass *acc = ARM_CPU_CLASS(oc); @@ -2254,14 +2277,11 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = arm_cpu_class_by_name; cc->has_work = arm_cpu_has_work; - cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; cc->dump_state = arm_cpu_dump_state; cc->set_pc = arm_cpu_set_pc; - cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; cc->gdb_read_register = arm_cpu_gdb_read_register; cc->gdb_write_register = arm_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY - cc->do_interrupt = arm_cpu_do_interrupt; cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug; cc->asidx_from_attrs = arm_asidx_from_attrs; cc->vmsd = &vmstate_arm_cpu; @@ -2275,17 +2295,10 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml; cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = arm_disas_set_info; + #ifdef CONFIG_TCG - cc->tcg_initialize = arm_translate_init; - cc->tlb_fill = arm_cpu_tlb_fill; - cc->debug_excp_handler = arm_debug_excp_handler; - cc->debug_check_watchpoint = arm_debug_check_watchpoint; - cc->do_unaligned_access = arm_cpu_do_unaligned_access; -#if !defined(CONFIG_USER_ONLY) - cc->do_transaction_failed = arm_cpu_do_transaction_failed; - cc->adjust_watchpoint_address = arm_adjust_watchpoint_address; -#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ -#endif + cc->tcg_ops = &arm_tcg_ops; +#endif /* CONFIG_TCG */ } #ifdef CONFIG_KVM diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 5e851028c5..10c5118176 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -21,6 +21,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "cpu.h" +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +#endif /* CONFIG_TCG */ #include "qemu/module.h" #if !defined(CONFIG_USER_ONLY) #include "hw/loader.h" @@ -805,7 +808,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) { CPUClass *cc = CPU_CLASS(oc); - cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; cc->gdb_read_register = aarch64_cpu_gdb_read_register; cc->gdb_write_register = aarch64_cpu_gdb_write_register; cc->gdb_num_core_regs = 34; diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 98544db2df..c29b434c60 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -10,11 +10,15 @@ #include "qemu/osdep.h" #include "cpu.h" +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +#endif /* CONFIG_TCG */ #include "internals.h" /* CPU models. These are not needed for the AArch64 linux-user build. */ #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) +#ifdef CONFIG_TCG static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { CPUClass *cc = CPU_GET_CLASS(cs); @@ -33,11 +37,12 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (interrupt_request & CPU_INTERRUPT_HARD && (armv7m_nvic_can_take_pending_exception(env->nvic))) { cs->exception_index = EXCP_IRQ; - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); ret = true; } return ret; } +#endif /* CONFIG_TCG */ static void arm926_initfn(Object *obj) { @@ -658,17 +663,34 @@ static void pxa270c5_initfn(Object *obj) cpu->reset_sctlr = 0x00000078; } +#ifdef CONFIG_TCG +static struct TCGCPUOps arm_v7m_tcg_ops = { + .initialize = arm_translate_init, + .synchronize_from_tb = arm_cpu_synchronize_from_tb, + .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt, + .tlb_fill = arm_cpu_tlb_fill, + .debug_excp_handler = arm_debug_excp_handler, + +#if !defined(CONFIG_USER_ONLY) + .do_interrupt = arm_v7m_cpu_do_interrupt, + .do_transaction_failed = arm_cpu_do_transaction_failed, + .do_unaligned_access = arm_cpu_do_unaligned_access, + .adjust_watchpoint_address = arm_adjust_watchpoint_address, + .debug_check_watchpoint = arm_debug_check_watchpoint, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void arm_v7m_class_init(ObjectClass *oc, void *data) { ARMCPUClass *acc = ARM_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); acc->info = data; -#ifndef CONFIG_USER_ONLY - cc->do_interrupt = arm_v7m_cpu_do_interrupt; -#endif +#ifdef CONFIG_TCG + cc->tcg_ops = &arm_v7m_tcg_ops; +#endif /* CONFIG_TCG */ - cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt; cc->gdb_core_xml_file = "arm-m-profile.xml"; } diff --git a/target/arm/helper.c b/target/arm/helper.c index 47e266d7e6..1a64bd748c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9969,6 +9969,10 @@ static void handle_semihosting(CPUState *cs) * Do any appropriate logging, handle PSCI calls, and then hand off * to the AArch64-entry or AArch32-entry function depending on the * target exception level's register width. + * + * Note: this is used for both TCG (as the do_interrupt tcg op), + * and KVM to re-inject guest debug exceptions, and to + * inject a Synchronous-External-Abort. */ void arm_cpu_do_interrupt(CPUState *cs) { diff --git a/target/arm/internals.h b/target/arm/internals.h index 853fa88fd6..448982dd2f 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -171,6 +171,12 @@ static inline int r14_bank_number(int mode) void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); +#ifdef CONFIG_TCG +void arm_cpu_synchronize_from_tb(CPUState *cs, + const struct TranslationBlock *tb); +#endif /* CONFIG_TCG */ + + enum arm_fprounding { FPROUNDING_TIEEVEN, FPROUNDING_POSINF, diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 3c37fc4fb6..dff85f6db9 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -946,7 +946,6 @@ static void kvm_inject_arm_sea(CPUState *c) { ARMCPU *cpu = ARM_CPU(c); CPUARMState *env = &cpu->env; - CPUClass *cc = CPU_GET_CLASS(c); uint32_t esr; bool same_el; @@ -962,7 +961,7 @@ static void kvm_inject_arm_sea(CPUState *c) env->exception.syndrome = esr; - cc->do_interrupt(c); + arm_cpu_do_interrupt(c); } #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ @@ -1493,7 +1492,6 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) { int hsr_ec = syn_get_ec(debug_exit->hsr); ARMCPU *cpu = ARM_CPU(cs); - CPUClass *cc = CPU_GET_CLASS(cs); CPUARMState *env = &cpu->env; /* Ensure PC is synchronised */ @@ -1547,7 +1545,7 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) env->exception.vaddress = debug_exit->far; env->exception.target_el = 1; qemu_mutex_lock_iothread(); - cc->do_interrupt(cs); + arm_cpu_do_interrupt(cs); qemu_mutex_unlock_iothread(); return false; diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 6f3d5a9e4a..fa0f8e0e80 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -184,6 +184,19 @@ static void avr_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, "\n"); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps avr_tcg_ops = { + .initialize = avr_cpu_tcg_init, + .synchronize_from_tb = avr_cpu_synchronize_from_tb, + .cpu_exec_interrupt = avr_cpu_exec_interrupt, + .tlb_fill = avr_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = avr_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void avr_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -198,21 +211,17 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = avr_cpu_class_by_name; cc->has_work = avr_cpu_has_work; - cc->do_interrupt = avr_cpu_do_interrupt; - cc->cpu_exec_interrupt = avr_cpu_exec_interrupt; cc->dump_state = avr_cpu_dump_state; cc->set_pc = avr_cpu_set_pc; cc->memory_rw_debug = avr_cpu_memory_rw_debug; cc->get_phys_page_debug = avr_cpu_get_phys_page_debug; - cc->tlb_fill = avr_cpu_tlb_fill; cc->vmsd = &vms_avr_cpu; cc->disas_set_info = avr_cpu_disas_set_info; - cc->tcg_initialize = avr_cpu_tcg_init; - cc->synchronize_from_tb = avr_cpu_synchronize_from_tb; cc->gdb_read_register = avr_cpu_gdb_read_register; cc->gdb_write_register = avr_cpu_gdb_write_register; cc->gdb_num_core_regs = 35; cc->gdb_core_xml_file = "avr-cpu.xml"; + cc->tcg_ops = &avr_tcg_ops; } /* diff --git a/target/avr/helper.c b/target/avr/helper.c index d96d14372b..65880b9928 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "hw/core/tcg-cpu-ops.h" #include "exec/exec-all.h" #include "exec/address-spaces.h" #include "exec/helper-proto.h" @@ -34,7 +35,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (interrupt_request & CPU_INTERRUPT_RESET) { if (cpu_interrupts_enabled(env)) { cs->exception_index = EXCP_RESET; - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); cs->interrupt_request &= ~CPU_INTERRUPT_RESET; @@ -45,7 +46,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (cpu_interrupts_enabled(env) && env->intsrc != 0) { int index = ctz32(env->intsrc); cs->exception_index = EXCP_INT(index); - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); env->intsrc &= env->intsrc - 1; /* clear the interrupt */ cs->interrupt_request &= ~CPU_INTERRUPT_HARD; diff --git a/target/cris/cpu.c b/target/cris/cpu.c index cff6b9eabf..ed983380fc 100644 --- a/target/cris/cpu.c +++ b/target/cris/cpu.c @@ -193,15 +193,36 @@ static void cris_cpu_initfn(Object *obj) #endif } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps crisv10_tcg_ops = { + .initialize = cris_initialize_crisv10_tcg, + .cpu_exec_interrupt = cris_cpu_exec_interrupt, + .tlb_fill = cris_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = crisv10_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + +static struct TCGCPUOps crisv32_tcg_ops = { + .initialize = cris_initialize_tcg, + .cpu_exec_interrupt = cris_cpu_exec_interrupt, + .tlb_fill = cris_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = cris_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void crisv8_cpu_class_init(ObjectClass *oc, void *data) { CPUClass *cc = CPU_CLASS(oc); CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 8; - cc->do_interrupt = crisv10_cpu_do_interrupt; cc->gdb_read_register = crisv10_cpu_gdb_read_register; - cc->tcg_initialize = cris_initialize_crisv10_tcg; + cc->tcg_ops = &crisv10_tcg_ops; } static void crisv9_cpu_class_init(ObjectClass *oc, void *data) @@ -210,9 +231,8 @@ static void crisv9_cpu_class_init(ObjectClass *oc, void *data) CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 9; - cc->do_interrupt = crisv10_cpu_do_interrupt; cc->gdb_read_register = crisv10_cpu_gdb_read_register; - cc->tcg_initialize = cris_initialize_crisv10_tcg; + cc->tcg_ops = &crisv10_tcg_ops; } static void crisv10_cpu_class_init(ObjectClass *oc, void *data) @@ -221,9 +241,8 @@ static void crisv10_cpu_class_init(ObjectClass *oc, void *data) CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 10; - cc->do_interrupt = crisv10_cpu_do_interrupt; cc->gdb_read_register = crisv10_cpu_gdb_read_register; - cc->tcg_initialize = cris_initialize_crisv10_tcg; + cc->tcg_ops = &crisv10_tcg_ops; } static void crisv11_cpu_class_init(ObjectClass *oc, void *data) @@ -232,9 +251,8 @@ static void crisv11_cpu_class_init(ObjectClass *oc, void *data) CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 11; - cc->do_interrupt = crisv10_cpu_do_interrupt; cc->gdb_read_register = crisv10_cpu_gdb_read_register; - cc->tcg_initialize = cris_initialize_crisv10_tcg; + cc->tcg_ops = &crisv10_tcg_ops; } static void crisv17_cpu_class_init(ObjectClass *oc, void *data) @@ -243,16 +261,17 @@ static void crisv17_cpu_class_init(ObjectClass *oc, void *data) CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 17; - cc->do_interrupt = crisv10_cpu_do_interrupt; cc->gdb_read_register = crisv10_cpu_gdb_read_register; - cc->tcg_initialize = cris_initialize_crisv10_tcg; + cc->tcg_ops = &crisv10_tcg_ops; } static void crisv32_cpu_class_init(ObjectClass *oc, void *data) { + CPUClass *cc = CPU_CLASS(oc); CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); ccc->vr = 32; + cc->tcg_ops = &crisv32_tcg_ops; } static void cris_cpu_class_init(ObjectClass *oc, void *data) @@ -268,13 +287,10 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = cris_cpu_class_by_name; cc->has_work = cris_cpu_has_work; - cc->do_interrupt = cris_cpu_do_interrupt; - cc->cpu_exec_interrupt = cris_cpu_exec_interrupt; cc->dump_state = cris_cpu_dump_state; cc->set_pc = cris_cpu_set_pc; cc->gdb_read_register = cris_cpu_gdb_read_register; cc->gdb_write_register = cris_cpu_gdb_write_register; - cc->tlb_fill = cris_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = cris_cpu_get_phys_page_debug; dc->vmsd = &vmstate_cris_cpu; @@ -284,7 +300,6 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = cris_disas_set_info; - cc->tcg_initialize = cris_initialize_tcg; } #define DEFINE_CRIS_CPU_TYPE(cpu_model, initfn) \ diff --git a/target/cris/helper.c b/target/cris/helper.c index ed45c3d9b7..7e3bb58fe1 100644 --- a/target/cris/helper.c +++ b/target/cris/helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "hw/core/tcg-cpu-ops.h" #include "mmu.h" #include "qemu/host-utils.h" #include "exec/exec-all.h" @@ -299,7 +300,7 @@ bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request) && (env->pregs[PR_CCS] & I_FLAG) && !env->locked_irq) { cs->exception_index = EXCP_IRQ; - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); ret = true; } if (interrupt_request & CPU_INTERRUPT_NMI) { @@ -311,7 +312,7 @@ bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request) } if ((env->pregs[PR_CCS] & m_flag_archval)) { cs->exception_index = EXCP_NMI; - cc->do_interrupt(cs); + cc->tcg_ops->do_interrupt(cs); ret = true; } } diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index e28f047d10..d8fad52d1f 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -71,6 +71,7 @@ static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) info->print_insn = print_insn_hppa; } +#ifndef CONFIG_USER_ONLY static void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) @@ -87,6 +88,7 @@ static void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, cpu_loop_exit_restore(cs, retaddr); } +#endif /* CONFIG_USER_ONLY */ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) { @@ -129,6 +131,20 @@ static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model) return object_class_by_name(TYPE_HPPA_CPU); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps hppa_tcg_ops = { + .initialize = hppa_translate_init, + .synchronize_from_tb = hppa_cpu_synchronize_from_tb, + .cpu_exec_interrupt = hppa_cpu_exec_interrupt, + .tlb_fill = hppa_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = hppa_cpu_do_interrupt, + .do_unaligned_access = hppa_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void hppa_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -140,23 +156,17 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = hppa_cpu_class_by_name; cc->has_work = hppa_cpu_has_work; - cc->do_interrupt = hppa_cpu_do_interrupt; - cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt; cc->dump_state = hppa_cpu_dump_state; cc->set_pc = hppa_cpu_set_pc; - cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb; cc->gdb_read_register = hppa_cpu_gdb_read_register; cc->gdb_write_register = hppa_cpu_gdb_write_register; - cc->tlb_fill = hppa_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; dc->vmsd = &vmstate_hppa_cpu; #endif - cc->do_unaligned_access = hppa_cpu_do_unaligned_access; cc->disas_set_info = hppa_cpu_disas_set_info; - cc->tcg_initialize = hppa_translate_init; - cc->gdb_num_core_regs = 128; + cc->tcg_ops = &hppa_tcg_ops; } static const TypeInfo hppa_cpu_type_info = { diff --git a/target/i386/hax/hax-cpus.c b/target/i386/hax/hax-accel-ops.c index f72c85bd49..136630e9b2 100644 --- a/target/i386/hax/hax-cpus.c +++ b/target/i386/hax/hax-accel-ops.c @@ -26,7 +26,7 @@ #include "sysemu/cpus.h" #include "qemu/guest-random.h" -#include "hax-cpus.h" +#include "hax-accel-ops.h" static void *hax_cpu_thread_fn(void *arg) { @@ -74,12 +74,29 @@ static void hax_start_vcpu_thread(CPUState *cpu) #endif } -const CpusAccel hax_cpus = { - .create_vcpu_thread = hax_start_vcpu_thread, - .kick_vcpu_thread = hax_kick_vcpu_thread, +static void hax_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = hax_start_vcpu_thread; + ops->kick_vcpu_thread = hax_kick_vcpu_thread; + + ops->synchronize_post_reset = hax_cpu_synchronize_post_reset; + ops->synchronize_post_init = hax_cpu_synchronize_post_init; + ops->synchronize_state = hax_cpu_synchronize_state; + ops->synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm; +} - .synchronize_post_reset = hax_cpu_synchronize_post_reset, - .synchronize_post_init = hax_cpu_synchronize_post_init, - .synchronize_state = hax_cpu_synchronize_state, - .synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm, +static const TypeInfo hax_accel_ops_type = { + .name = ACCEL_OPS_NAME("hax"), + + .parent = TYPE_ACCEL_OPS, + .class_init = hax_accel_ops_class_init, + .abstract = true, }; + +static void hax_accel_ops_register_types(void) +{ + type_register_static(&hax_accel_ops_type); +} +type_init(hax_accel_ops_register_types); diff --git a/target/i386/hax/hax-cpus.h b/target/i386/hax/hax-accel-ops.h index ee8ab7a631..c7698519cd 100644 --- a/target/i386/hax/hax-cpus.h +++ b/target/i386/hax/hax-accel-ops.h @@ -12,8 +12,6 @@ #include "sysemu/cpus.h" -extern const CpusAccel hax_cpus; - #include "hax-interface.h" #include "hax-i386.h" diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c index fecfe8cd6e..bf65ed6fa9 100644 --- a/target/i386/hax/hax-all.c +++ b/target/i386/hax/hax-all.c @@ -28,12 +28,12 @@ #include "exec/address-spaces.h" #include "qemu-common.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" #include "hw/boards.h" -#include "hax-cpus.h" +#include "hax-accel-ops.h" #define DEBUG_HAX 0 @@ -364,9 +364,6 @@ static int hax_accel_init(MachineState *ms) !ret ? "working" : "not working", !ret ? "fast virt" : "emulation"); } - if (ret == 0) { - cpus_register_accel(&hax_cpus); - } return ret; } diff --git a/target/i386/hax/hax-mem.c b/target/i386/hax/hax-mem.c index 71e637cf16..35495f5e82 100644 --- a/target/i386/hax/hax-mem.c +++ b/target/i386/hax/hax-mem.c @@ -13,7 +13,7 @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" -#include "hax-cpus.h" +#include "hax-accel-ops.h" #include "qemu/queue.h" #define DEBUG_HAX_MEM 0 diff --git a/target/i386/hax/hax-posix.c b/target/i386/hax/hax-posix.c index 735a749d4b..ac1a51096e 100644 --- a/target/i386/hax/hax-posix.c +++ b/target/i386/hax/hax-posix.c @@ -15,7 +15,7 @@ #include <sys/ioctl.h> #include "sysemu/cpus.h" -#include "hax-cpus.h" +#include "hax-accel-ops.h" hax_fd hax_mod_open(void) { diff --git a/target/i386/hax/hax-windows.c b/target/i386/hax/hax-windows.c index 6c82dfb54f..59afa213a6 100644 --- a/target/i386/hax/hax-windows.c +++ b/target/i386/hax/hax-windows.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "hax-cpus.h" +#include "hax-accel-ops.h" /* * return 0 when success, -1 when driver not loaded, diff --git a/target/i386/hax/hax-windows.h b/target/i386/hax/hax-windows.h index a5ce12d663..b1f5d4f32f 100644 --- a/target/i386/hax/hax-windows.h +++ b/target/i386/hax/hax-windows.h @@ -23,7 +23,7 @@ #include <winioctl.h> #include <windef.h> -#include "hax-cpus.h" +#include "hax-accel-ops.h" #define HAX_INVALID_FD INVALID_HANDLE_VALUE diff --git a/target/i386/hax/meson.build b/target/i386/hax/meson.build index 77ea431b30..d6c520fb6b 100644 --- a/target/i386/hax/meson.build +++ b/target/i386/hax/meson.build @@ -1,7 +1,7 @@ i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files( 'hax-all.c', 'hax-mem.c', - 'hax-cpus.c', + 'hax-accel-ops.c', )) i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c')) i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c')) diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-accel-ops.c index 817b3d7452..cbaad238e0 100644 --- a/target/i386/hvf/hvf-cpus.c +++ b/target/i386/hvf/hvf-accel-ops.c @@ -55,7 +55,7 @@ #include "target/i386/cpu.h" #include "qemu/guest-random.h" -#include "hvf-cpus.h" +#include "hvf-accel-ops.h" /* * The HVF-specific vCPU thread function. This one should only run when the host @@ -121,11 +121,26 @@ static void hvf_start_vcpu_thread(CPUState *cpu) cpu, QEMU_THREAD_JOINABLE); } -const CpusAccel hvf_cpus = { - .create_vcpu_thread = hvf_start_vcpu_thread, +static void hvf_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = hvf_start_vcpu_thread; + + ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset; + ops->synchronize_post_init = hvf_cpu_synchronize_post_init; + ops->synchronize_state = hvf_cpu_synchronize_state; + ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm; +}; +static const TypeInfo hvf_accel_ops_type = { + .name = ACCEL_OPS_NAME("hvf"), - .synchronize_post_reset = hvf_cpu_synchronize_post_reset, - .synchronize_post_init = hvf_cpu_synchronize_post_init, - .synchronize_state = hvf_cpu_synchronize_state, - .synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm, + .parent = TYPE_ACCEL_OPS, + .class_init = hvf_accel_ops_class_init, + .abstract = true, }; +static void hvf_accel_ops_register_types(void) +{ + type_register_static(&hvf_accel_ops_type); +} +type_init(hvf_accel_ops_register_types); diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-accel-ops.h index ced31b82c0..8f992da168 100644 --- a/target/i386/hvf/hvf-cpus.h +++ b/target/i386/hvf/hvf-accel-ops.h @@ -12,8 +12,6 @@ #include "sysemu/cpus.h" -extern const CpusAccel hvf_cpus; - int hvf_init_vcpu(CPUState *); int hvf_vcpu_exec(CPUState *); void hvf_cpu_synchronize_state(CPUState *); diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h index e0edffd077..50b914fd67 100644 --- a/target/i386/hvf/hvf-i386.h +++ b/target/i386/hvf/hvf-i386.h @@ -16,7 +16,7 @@ #ifndef HVF_I386_H #define HVF_I386_H -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/hvf.h" #include "cpu.h" #include "x86.h" diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index ed9356565c..5b90dcdf88 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -69,10 +69,10 @@ #include "exec/address-spaces.h" #include "hw/i386/apic_internal.h" #include "qemu/main-loop.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "target/i386/cpu.h" -#include "hvf-cpus.h" +#include "hvf-accel-ops.h" HVFState *hvf_state; @@ -887,7 +887,6 @@ static int hvf_accel_init(MachineState *ms) hvf_state = s; memory_listener_register(&hvf_memory_listener, &address_space_memory); - cpus_register_accel(&hvf_cpus); return 0; } diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build index 409c9a3f14..e9eb5a5da8 100644 --- a/target/i386/hvf/meson.build +++ b/target/i386/hvf/meson.build @@ -1,6 +1,6 @@ i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( 'hvf.c', - 'hvf-cpus.c', + 'hvf-accel-ops.c', 'x86.c', 'x86_cpuid.c', 'x86_decode.c', diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 6f04478b3a..d66dfd7669 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -28,7 +28,7 @@ #include "hw/i386/apic_internal.h" #include "qemu/main-loop.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "target/i386/cpu.h" // TODO: taskswitch handling diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index bbec412b6c..0d7533742e 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -32,7 +32,7 @@ #include <Hypervisor/hv.h> #include <Hypervisor/hv_vmx.h> -#include "hvf-cpus.h" +#include "hvf-accel-ops.h" void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr) diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 4fa013720e..1e125d2175 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -57,16 +57,22 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, cpu->env.eip = tb->pc - tb->cs_base; } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps x86_tcg_ops = { + .initialize = tcg_x86_init, + .synchronize_from_tb = x86_cpu_synchronize_from_tb, + .cpu_exec_enter = x86_cpu_exec_enter, + .cpu_exec_exit = x86_cpu_exec_exit, + .cpu_exec_interrupt = x86_cpu_exec_interrupt, + .do_interrupt = x86_cpu_do_interrupt, + .tlb_fill = x86_cpu_tlb_fill, +#ifndef CONFIG_USER_ONLY + .debug_excp_handler = breakpoint_handler, +#endif /* !CONFIG_USER_ONLY */ +}; + void tcg_cpu_common_class_init(CPUClass *cc) { - cc->do_interrupt = x86_cpu_do_interrupt; - cc->cpu_exec_interrupt = x86_cpu_exec_interrupt; - cc->synchronize_from_tb = x86_cpu_synchronize_from_tb; - cc->cpu_exec_enter = x86_cpu_exec_enter; - cc->cpu_exec_exit = x86_cpu_exec_exit; - cc->tcg_initialize = tcg_x86_init; - cc->tlb_fill = x86_cpu_tlb_fill; -#ifndef CONFIG_USER_ONLY - cc->debug_excp_handler = breakpoint_handler; -#endif + cc->tcg_ops = &x86_tcg_ops; } diff --git a/target/i386/whpx/meson.build b/target/i386/whpx/meson.build index d8aa683999..95fc31eb81 100644 --- a/target/i386/whpx/meson.build +++ b/target/i386/whpx/meson.build @@ -1,5 +1,5 @@ i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files( 'whpx-all.c', 'whpx-apic.c', - 'whpx-cpus.c', + 'whpx-accel-ops.c', )) diff --git a/target/i386/whpx/whpx-cpus.c b/target/i386/whpx/whpx-accel-ops.c index f7e69881a3..6bc47c5309 100644 --- a/target/i386/whpx/whpx-cpus.c +++ b/target/i386/whpx/whpx-accel-ops.c @@ -16,7 +16,7 @@ #include "sysemu/whpx.h" #include "whpx-internal.h" -#include "whpx-cpus.h" +#include "whpx-accel-ops.h" static void *whpx_cpu_thread_fn(void *arg) { @@ -83,12 +83,29 @@ static void whpx_kick_vcpu_thread(CPUState *cpu) } } -const CpusAccel whpx_cpus = { - .create_vcpu_thread = whpx_start_vcpu_thread, - .kick_vcpu_thread = whpx_kick_vcpu_thread, +static void whpx_accel_ops_class_init(ObjectClass *oc, void *data) +{ + AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + + ops->create_vcpu_thread = whpx_start_vcpu_thread; + ops->kick_vcpu_thread = whpx_kick_vcpu_thread; + + ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset; + ops->synchronize_post_init = whpx_cpu_synchronize_post_init; + ops->synchronize_state = whpx_cpu_synchronize_state; + ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm; +} - .synchronize_post_reset = whpx_cpu_synchronize_post_reset, - .synchronize_post_init = whpx_cpu_synchronize_post_init, - .synchronize_state = whpx_cpu_synchronize_state, - .synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm, +static const TypeInfo whpx_accel_ops_type = { + .name = ACCEL_OPS_NAME("whpx"), + + .parent = TYPE_ACCEL_OPS, + .class_init = whpx_accel_ops_class_init, + .abstract = true, }; + +static void whpx_accel_ops_register_types(void) +{ + type_register_static(&whpx_accel_ops_type); +} +type_init(whpx_accel_ops_register_types); diff --git a/target/i386/whpx/whpx-cpus.h b/target/i386/whpx/whpx-accel-ops.h index bdb367d1d0..2dee6d61ea 100644 --- a/target/i386/whpx/whpx-cpus.h +++ b/target/i386/whpx/whpx-accel-ops.h @@ -12,8 +12,6 @@ #include "sysemu/cpus.h" -extern const CpusAccel whpx_cpus; - int whpx_init_vcpu(CPUState *cpu); int whpx_vcpu_exec(CPUState *cpu); void whpx_destroy_vcpu(CPUState *cpu); diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index 985ceba8f8..f0a35df3bb 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -13,7 +13,7 @@ #include "exec/address-spaces.h" #include "exec/ioport.h" #include "qemu-common.h" -#include "sysemu/accel.h" +#include "qemu/accel.h" #include "sysemu/whpx.h" #include "sysemu/cpus.h" #include "sysemu/runstate.h" @@ -28,8 +28,11 @@ #include "migration/blocker.h" #include <winerror.h> -#include "whpx-cpus.h" #include "whpx-internal.h" +#include "whpx-accel-ops.h" + +#include <WinHvPlatform.h> +#include <WinHvEmulation.h> #define HYPERV_APIC_BUS_FREQUENCY (200000000ULL) @@ -1846,8 +1849,6 @@ static int whpx_accel_init(MachineState *ms) whpx_memory_init(); - cpus_register_accel(&whpx_cpus); - printf("Windows Hypervisor Platform accelerator is operational\n"); return 0; diff --git a/target/lm32/cpu.c b/target/lm32/cpu.c index c50ad5fa15..c23d72874c 100644 --- a/target/lm32/cpu.c +++ b/target/lm32/cpu.c @@ -210,6 +210,19 @@ static ObjectClass *lm32_cpu_class_by_name(const char *cpu_model) return oc; } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps lm32_tcg_ops = { + .initialize = lm32_translate_init, + .cpu_exec_interrupt = lm32_cpu_exec_interrupt, + .tlb_fill = lm32_cpu_tlb_fill, + .debug_excp_handler = lm32_debug_excp_handler, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = lm32_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void lm32_cpu_class_init(ObjectClass *oc, void *data) { LM32CPUClass *lcc = LM32_CPU_CLASS(oc); @@ -222,22 +235,18 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = lm32_cpu_class_by_name; cc->has_work = lm32_cpu_has_work; - cc->do_interrupt = lm32_cpu_do_interrupt; - cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt; cc->dump_state = lm32_cpu_dump_state; cc->set_pc = lm32_cpu_set_pc; cc->gdb_read_register = lm32_cpu_gdb_read_register; cc->gdb_write_register = lm32_cpu_gdb_write_register; - cc->tlb_fill = lm32_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug; cc->vmsd = &vmstate_lm32_cpu; #endif cc->gdb_num_core_regs = 32 + 7; cc->gdb_stop_before_watchpoint = true; - cc->debug_excp_handler = lm32_debug_excp_handler; cc->disas_set_info = lm32_cpu_disas_set_info; - cc->tcg_initialize = lm32_translate_init; + cc->tcg_ops = &lm32_tcg_ops; } #define DEFINE_LM32_CPU_TYPE(cpu_model, initfn) \ diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index b811a0bdde..c6fde8132b 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -453,6 +453,19 @@ static const VMStateDescription vmstate_m68k_cpu = { }; #endif +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps m68k_tcg_ops = { + .initialize = m68k_tcg_init, + .cpu_exec_interrupt = m68k_cpu_exec_interrupt, + .tlb_fill = m68k_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = m68k_cpu_do_interrupt, + .do_transaction_failed = m68k_cpu_transaction_failed, +#endif /* !CONFIG_USER_ONLY */ +}; + static void m68k_cpu_class_init(ObjectClass *c, void *data) { M68kCPUClass *mcc = M68K_CPU_CLASS(c); @@ -465,22 +478,18 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = m68k_cpu_class_by_name; cc->has_work = m68k_cpu_has_work; - cc->do_interrupt = m68k_cpu_do_interrupt; - cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt; cc->dump_state = m68k_cpu_dump_state; cc->set_pc = m68k_cpu_set_pc; cc->gdb_read_register = m68k_cpu_gdb_read_register; cc->gdb_write_register = m68k_cpu_gdb_write_register; - cc->tlb_fill = m68k_cpu_tlb_fill; #if defined(CONFIG_SOFTMMU) - cc->do_transaction_failed = m68k_cpu_transaction_failed; cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; dc->vmsd = &vmstate_m68k_cpu; #endif cc->disas_set_info = m68k_cpu_disas_set_info; - cc->tcg_initialize = m68k_tcg_init; cc->gdb_num_core_regs = 18; + cc->tcg_ops = &m68k_tcg_ops; } static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data) diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index d5e8bfe11f..433ba20203 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -352,6 +352,21 @@ static ObjectClass *mb_cpu_class_by_name(const char *cpu_model) return object_class_by_name(TYPE_MICROBLAZE_CPU); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps mb_tcg_ops = { + .initialize = mb_tcg_init, + .synchronize_from_tb = mb_cpu_synchronize_from_tb, + .cpu_exec_interrupt = mb_cpu_exec_interrupt, + .tlb_fill = mb_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = mb_cpu_do_interrupt, + .do_transaction_failed = mb_cpu_transaction_failed, + .do_unaligned_access = mb_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void mb_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -364,17 +379,13 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = mb_cpu_class_by_name; cc->has_work = mb_cpu_has_work; - cc->do_interrupt = mb_cpu_do_interrupt; - cc->do_unaligned_access = mb_cpu_do_unaligned_access; - cc->cpu_exec_interrupt = mb_cpu_exec_interrupt; + cc->dump_state = mb_cpu_dump_state; cc->set_pc = mb_cpu_set_pc; - cc->synchronize_from_tb = mb_cpu_synchronize_from_tb; cc->gdb_read_register = mb_cpu_gdb_read_register; cc->gdb_write_register = mb_cpu_gdb_write_register; - cc->tlb_fill = mb_cpu_tlb_fill; + #ifndef CONFIG_USER_ONLY - cc->do_transaction_failed = mb_cpu_transaction_failed; cc->get_phys_page_attrs_debug = mb_cpu_get_phys_page_attrs_debug; dc->vmsd = &vmstate_mb_cpu; #endif @@ -382,7 +393,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_num_core_regs = 32 + 27; cc->disas_set_info = mb_disas_set_info; - cc->tcg_initialize = mb_tcg_init; + cc->tcg_ops = &mb_tcg_ops; } static const TypeInfo mb_cpu_type_info = { diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 4c4548233c..ad163ead62 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -257,6 +257,7 @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value) } } +#ifdef CONFIG_TCG static void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -267,6 +268,7 @@ static void mips_cpu_synchronize_from_tb(CPUState *cs, env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags |= tb->flags & MIPS_HFLAG_BMASK; } +#endif /* CONFIG_TCG */ static bool mips_cpu_has_work(CPUState *cs) { @@ -661,6 +663,26 @@ static Property mips_cpu_properties[] = { DEFINE_PROP_END_OF_LIST() }; +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +/* + * NB: cannot be const, as some elements are changed for specific + * mips hardware (see hw/mips/jazz.c). + */ +static struct TCGCPUOps mips_tcg_ops = { + .initialize = mips_tcg_init, + .synchronize_from_tb = mips_cpu_synchronize_from_tb, + .cpu_exec_interrupt = mips_cpu_exec_interrupt, + .tlb_fill = mips_cpu_tlb_fill, + +#if !defined(CONFIG_USER_ONLY) + .do_interrupt = mips_cpu_do_interrupt, + .do_transaction_failed = mips_cpu_do_transaction_failed, + .do_unaligned_access = mips_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void mips_cpu_class_init(ObjectClass *c, void *data) { MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); @@ -674,27 +696,20 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = mips_cpu_class_by_name; cc->has_work = mips_cpu_has_work; - cc->do_interrupt = mips_cpu_do_interrupt; - cc->cpu_exec_interrupt = mips_cpu_exec_interrupt; cc->dump_state = mips_cpu_dump_state; cc->set_pc = mips_cpu_set_pc; - cc->synchronize_from_tb = mips_cpu_synchronize_from_tb; cc->gdb_read_register = mips_cpu_gdb_read_register; cc->gdb_write_register = mips_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY - cc->do_transaction_failed = mips_cpu_do_transaction_failed; - cc->do_unaligned_access = mips_cpu_do_unaligned_access; cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; cc->vmsd = &vmstate_mips_cpu; #endif cc->disas_set_info = mips_cpu_disas_set_info; -#ifdef CONFIG_TCG - cc->tcg_initialize = mips_tcg_init; - cc->tlb_fill = mips_cpu_tlb_fill; -#endif - cc->gdb_num_core_regs = 73; cc->gdb_stop_before_watchpoint = true; +#ifdef CONFIG_TCG + cc->tcg_ops = &mips_tcg_ops; +#endif /* CONFIG_TCG */ } static const TypeInfo mips_cpu_type_info = { diff --git a/target/moxie/cpu.c b/target/moxie/cpu.c index 6e0443ccb7..83bec34d36 100644 --- a/target/moxie/cpu.c +++ b/target/moxie/cpu.c @@ -94,6 +94,17 @@ static ObjectClass *moxie_cpu_class_by_name(const char *cpu_model) return oc; } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps moxie_tcg_ops = { + .initialize = moxie_translate_init, + .tlb_fill = moxie_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = moxie_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void moxie_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -107,16 +118,14 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = moxie_cpu_class_by_name; cc->has_work = moxie_cpu_has_work; - cc->do_interrupt = moxie_cpu_do_interrupt; cc->dump_state = moxie_cpu_dump_state; cc->set_pc = moxie_cpu_set_pc; - cc->tlb_fill = moxie_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug; cc->vmsd = &vmstate_moxie_cpu; #endif cc->disas_set_info = moxie_cpu_disas_set_info; - cc->tcg_initialize = moxie_translate_init; + cc->tcg_ops = &moxie_tcg_ops; } static void moxielite_initfn(Object *obj) diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index 58688e1623..e9c9fc3a38 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -207,6 +207,18 @@ static Property nios2_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps nios2_tcg_ops = { + .initialize = nios2_tcg_init, + .cpu_exec_interrupt = nios2_cpu_exec_interrupt, + .tlb_fill = nios2_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = nios2_cpu_do_interrupt, + .do_unaligned_access = nios2_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; static void nios2_cpu_class_init(ObjectClass *oc, void *data) { @@ -221,20 +233,16 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = nios2_cpu_class_by_name; cc->has_work = nios2_cpu_has_work; - cc->do_interrupt = nios2_cpu_do_interrupt; - cc->cpu_exec_interrupt = nios2_cpu_exec_interrupt; cc->dump_state = nios2_cpu_dump_state; cc->set_pc = nios2_cpu_set_pc; cc->disas_set_info = nios2_cpu_disas_set_info; - cc->tlb_fill = nios2_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY - cc->do_unaligned_access = nios2_cpu_do_unaligned_access; cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug; #endif cc->gdb_read_register = nios2_cpu_gdb_read_register; cc->gdb_write_register = nios2_cpu_gdb_write_register; cc->gdb_num_core_regs = 49; - cc->tcg_initialize = nios2_tcg_init; + cc->tcg_ops = &nios2_tcg_ops; } static const TypeInfo nios2_cpu_type_info = { diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index b0bdfbe4fe..2c64842f46 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -174,6 +174,18 @@ static void openrisc_any_initfn(Object *obj) | (IMMUCFGR_NTS & (ctz32(TLB_SIZE) << 2)); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps openrisc_tcg_ops = { + .initialize = openrisc_translate_init, + .cpu_exec_interrupt = openrisc_cpu_exec_interrupt, + .tlb_fill = openrisc_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = openrisc_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void openrisc_cpu_class_init(ObjectClass *oc, void *data) { OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc); @@ -186,20 +198,17 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = openrisc_cpu_class_by_name; cc->has_work = openrisc_cpu_has_work; - cc->do_interrupt = openrisc_cpu_do_interrupt; - cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt; cc->dump_state = openrisc_cpu_dump_state; cc->set_pc = openrisc_cpu_set_pc; cc->gdb_read_register = openrisc_cpu_gdb_read_register; cc->gdb_write_register = openrisc_cpu_gdb_write_register; - cc->tlb_fill = openrisc_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug; dc->vmsd = &vmstate_openrisc_cpu; #endif cc->gdb_num_core_regs = 32 + 3; - cc->tcg_initialize = openrisc_translate_init; cc->disas_set_info = openrisc_disas_set_info; + cc->tcg_ops = &openrisc_tcg_ops; } /* Sort alphabetically by type name, except for "any". */ diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc index 3c05a17343..9867d0a6e4 100644 --- a/target/ppc/translate_init.c.inc +++ b/target/ppc/translate_init.c.inc @@ -10700,6 +10700,7 @@ static void ppc_cpu_reset(DeviceState *dev) } #ifndef CONFIG_USER_ONLY + static bool ppc_cpu_is_big_endian(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -10710,6 +10711,7 @@ static bool ppc_cpu_is_big_endian(CPUState *cs) return !msr_le; } +#ifdef CONFIG_TCG static void ppc_cpu_exec_enter(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -10731,7 +10733,9 @@ static void ppc_cpu_exec_exit(CPUState *cs) vhc->cpu_exec_exit(cpu->vhyp, cpu); } } -#endif +#endif /* CONFIG_TCG */ + +#endif /* !CONFIG_USER_ONLY */ static void ppc_cpu_instance_init(Object *obj) { @@ -10823,6 +10827,23 @@ static Property ppc_cpu_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps ppc_tcg_ops = { + .initialize = ppc_translate_init, + .cpu_exec_interrupt = ppc_cpu_exec_interrupt, + .tlb_fill = ppc_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = ppc_cpu_do_interrupt, + .cpu_exec_enter = ppc_cpu_exec_enter, + .cpu_exec_exit = ppc_cpu_exec_exit, + .do_unaligned_access = ppc_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void ppc_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -10841,14 +10862,11 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = ppc_cpu_class_by_name; cc->has_work = ppc_cpu_has_work; - cc->do_interrupt = ppc_cpu_do_interrupt; - cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt; cc->dump_state = ppc_cpu_dump_state; cc->dump_statistics = ppc_cpu_dump_statistics; cc->set_pc = ppc_cpu_set_pc; cc->gdb_read_register = ppc_cpu_gdb_read_register; cc->gdb_write_register = ppc_cpu_gdb_write_register; - cc->do_unaligned_access = ppc_cpu_do_unaligned_access; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; cc->vmsd = &vmstate_ppc_cpu; @@ -10877,18 +10895,13 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) #ifndef CONFIG_USER_ONLY cc->virtio_is_big_endian = ppc_cpu_is_big_endian; #endif -#ifdef CONFIG_TCG - cc->tcg_initialize = ppc_translate_init; - cc->tlb_fill = ppc_cpu_tlb_fill; -#endif -#ifndef CONFIG_USER_ONLY - cc->cpu_exec_enter = ppc_cpu_exec_enter; - cc->cpu_exec_exit = ppc_cpu_exec_exit; -#endif - cc->disas_set_info = ppc_disas_set_info; dc->fw_name = "PowerPC,UNKNOWN"; + +#ifdef CONFIG_TCG + cc->tcg_ops = &ppc_tcg_ops; +#endif /* CONFIG_TCG */ } static const TypeInfo ppc_cpu_type_info = { diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 27788021eb..16f1a34238 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -580,6 +580,21 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) return NULL; } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps riscv_tcg_ops = { + .initialize = riscv_translate_init, + .synchronize_from_tb = riscv_cpu_synchronize_from_tb, + .cpu_exec_interrupt = riscv_cpu_exec_interrupt, + .tlb_fill = riscv_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = riscv_cpu_do_interrupt, + .do_transaction_failed = riscv_cpu_do_transaction_failed, + .do_unaligned_access = riscv_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void riscv_cpu_class_init(ObjectClass *c, void *data) { RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); @@ -593,11 +608,8 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = riscv_cpu_class_by_name; cc->has_work = riscv_cpu_has_work; - cc->do_interrupt = riscv_cpu_do_interrupt; - cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt; cc->dump_state = riscv_cpu_dump_state; cc->set_pc = riscv_cpu_set_pc; - cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb; cc->gdb_read_register = riscv_cpu_gdb_read_register; cc->gdb_write_register = riscv_cpu_gdb_write_register; cc->gdb_num_core_regs = 33; @@ -609,18 +621,14 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = riscv_cpu_disas_set_info; #ifndef CONFIG_USER_ONLY - cc->do_transaction_failed = riscv_cpu_do_transaction_failed; - cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; /* For now, mark unmigratable: */ cc->vmsd = &vmstate_riscv_cpu; #endif cc->gdb_arch_name = riscv_gdb_arch_name; cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml; -#ifdef CONFIG_TCG - cc->tcg_initialize = riscv_translate_init; - cc->tlb_fill = riscv_cpu_tlb_fill; -#endif + cc->tcg_ops = &riscv_tcg_ops; + device_class_set_props(dc, riscv_cpu_properties); } diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index f8350f5f78..2f43939fb6 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -671,7 +671,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, env->badaddr = addr; riscv_raise_exception(env, cs->exception_index, retaddr); } -#endif +#endif /* !CONFIG_USER_ONLY */ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, diff --git a/target/rx/cpu.c b/target/rx/cpu.c index 2bb14144a7..7ac6618b26 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -173,6 +173,19 @@ static void rx_cpu_init(Object *obj) qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps rx_tcg_ops = { + .initialize = rx_translate_init, + .synchronize_from_tb = rx_cpu_synchronize_from_tb, + .cpu_exec_interrupt = rx_cpu_exec_interrupt, + .tlb_fill = rx_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = rx_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void rx_cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -186,20 +199,17 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data) cc->class_by_name = rx_cpu_class_by_name; cc->has_work = rx_cpu_has_work; - cc->do_interrupt = rx_cpu_do_interrupt; - cc->cpu_exec_interrupt = rx_cpu_exec_interrupt; cc->dump_state = rx_cpu_dump_state; cc->set_pc = rx_cpu_set_pc; - cc->synchronize_from_tb = rx_cpu_synchronize_from_tb; + cc->gdb_read_register = rx_cpu_gdb_read_register; cc->gdb_write_register = rx_cpu_gdb_write_register; cc->get_phys_page_debug = rx_cpu_get_phys_page_debug; cc->disas_set_info = rx_cpu_disas_set_info; - cc->tcg_initialize = rx_translate_init; - cc->tlb_fill = rx_cpu_tlb_fill; cc->gdb_num_core_regs = 26; cc->gdb_core_xml_file = "rx-core.xml"; + cc->tcg_ops = &rx_tcg_ops; } static const TypeInfo rx_cpu_info = { diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 7da70afbf2..d35eb39a1b 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -477,6 +477,22 @@ static void s390_cpu_reset_full(DeviceState *dev) return s390_cpu_reset(s, S390_CPU_RESET_CLEAR); } +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps s390_tcg_ops = { + .initialize = s390x_translate_init, + .tlb_fill = s390_cpu_tlb_fill, + +#if !defined(CONFIG_USER_ONLY) + .cpu_exec_interrupt = s390_cpu_exec_interrupt, + .do_interrupt = s390_cpu_do_interrupt, + .debug_excp_handler = s390x_cpu_debug_excp_handler, + .do_unaligned_access = s390x_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void s390_cpu_class_init(ObjectClass *oc, void *data) { S390CPUClass *scc = S390_CPU_CLASS(oc); @@ -495,9 +511,6 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) scc->reset = s390_cpu_reset; cc->class_by_name = s390_cpu_class_by_name, cc->has_work = s390_cpu_has_work; -#ifdef CONFIG_TCG - cc->do_interrupt = s390_cpu_do_interrupt; -#endif cc->dump_state = s390_cpu_dump_state; cc->set_pc = s390_cpu_set_pc; cc->gdb_read_register = s390_cpu_gdb_read_register; @@ -507,23 +520,17 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->vmsd = &vmstate_s390_cpu; cc->get_crash_info = s390_cpu_get_crash_info; cc->write_elf64_note = s390_cpu_write_elf64_note; -#ifdef CONFIG_TCG - cc->cpu_exec_interrupt = s390_cpu_exec_interrupt; - cc->debug_excp_handler = s390x_cpu_debug_excp_handler; - cc->do_unaligned_access = s390x_cpu_do_unaligned_access; -#endif #endif cc->disas_set_info = s390_cpu_disas_set_info; -#ifdef CONFIG_TCG - cc->tcg_initialize = s390x_translate_init; - cc->tlb_fill = s390_cpu_tlb_fill; -#endif - cc->gdb_num_core_regs = S390_NUM_CORE_REGS; cc->gdb_core_xml_file = "s390x-core64.xml"; cc->gdb_arch_name = s390_gdb_arch_name; s390_cpu_model_class_register_props(oc); + +#ifdef CONFIG_TCG + cc->tcg_ops = &s390_tcg_ops; +#endif /* CONFIG_TCG */ } static const TypeInfo s390_cpu_type_info = { diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 9cf66d3690..ce16af394b 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -634,4 +634,4 @@ void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code, } } -#endif /* CONFIG_USER_ONLY */ +#endif /* !CONFIG_USER_ONLY */ diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 1e0f05a15b..a78d283bc8 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -206,6 +206,20 @@ static const VMStateDescription vmstate_sh_cpu = { .unmigratable = 1, }; +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps superh_tcg_ops = { + .initialize = sh4_translate_init, + .synchronize_from_tb = superh_cpu_synchronize_from_tb, + .cpu_exec_interrupt = superh_cpu_exec_interrupt, + .tlb_fill = superh_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = superh_cpu_do_interrupt, + .do_unaligned_access = superh_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void superh_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -219,24 +233,19 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = superh_cpu_class_by_name; cc->has_work = superh_cpu_has_work; - cc->do_interrupt = superh_cpu_do_interrupt; - cc->cpu_exec_interrupt = superh_cpu_exec_interrupt; cc->dump_state = superh_cpu_dump_state; cc->set_pc = superh_cpu_set_pc; - cc->synchronize_from_tb = superh_cpu_synchronize_from_tb; cc->gdb_read_register = superh_cpu_gdb_read_register; cc->gdb_write_register = superh_cpu_gdb_write_register; - cc->tlb_fill = superh_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY - cc->do_unaligned_access = superh_cpu_do_unaligned_access; cc->get_phys_page_debug = superh_cpu_get_phys_page_debug; #endif cc->disas_set_info = superh_cpu_disas_set_info; - cc->tcg_initialize = sh4_translate_init; cc->gdb_num_core_regs = 59; dc->vmsd = &vmstate_sh_cpu; + cc->tcg_ops = &superh_tcg_ops; } #define DEFINE_SUPERH_CPU_TYPE(type_name, cinit, initfn) \ diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 6f14e370ed..aece2c7dc8 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -848,6 +848,23 @@ static Property sparc_cpu_properties[] = { DEFINE_PROP_END_OF_LIST() }; +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps sparc_tcg_ops = { + .initialize = sparc_tcg_init, + .synchronize_from_tb = sparc_cpu_synchronize_from_tb, + .cpu_exec_interrupt = sparc_cpu_exec_interrupt, + .tlb_fill = sparc_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = sparc_cpu_do_interrupt, + .do_transaction_failed = sparc_cpu_do_transaction_failed, + .do_unaligned_access = sparc_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + static void sparc_cpu_class_init(ObjectClass *oc, void *data) { SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); @@ -863,31 +880,25 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = sparc_cpu_class_by_name; cc->parse_features = sparc_cpu_parse_features; cc->has_work = sparc_cpu_has_work; - cc->do_interrupt = sparc_cpu_do_interrupt; - cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt; cc->dump_state = sparc_cpu_dump_state; #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) cc->memory_rw_debug = sparc_cpu_memory_rw_debug; #endif cc->set_pc = sparc_cpu_set_pc; - cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; cc->gdb_read_register = sparc_cpu_gdb_read_register; cc->gdb_write_register = sparc_cpu_gdb_write_register; - cc->tlb_fill = sparc_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY - cc->do_transaction_failed = sparc_cpu_do_transaction_failed; - cc->do_unaligned_access = sparc_cpu_do_unaligned_access; cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug; cc->vmsd = &vmstate_sparc_cpu; #endif cc->disas_set_info = cpu_sparc_disas_set_info; - cc->tcg_initialize = sparc_tcg_init; #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) cc->gdb_num_core_regs = 86; #else cc->gdb_num_core_regs = 72; #endif + cc->tcg_ops = &sparc_tcg_ops; } static const TypeInfo sparc_cpu_type_info = { diff --git a/target/tilegx/cpu.c b/target/tilegx/cpu.c index 1fee87c094..d969c2f133 100644 --- a/target/tilegx/cpu.c +++ b/target/tilegx/cpu.c @@ -134,6 +134,18 @@ static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) return false; } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps tilegx_tcg_ops = { + .initialize = tilegx_tcg_init, + .cpu_exec_interrupt = tilegx_cpu_exec_interrupt, + .tlb_fill = tilegx_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = tilegx_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void tilegx_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -147,13 +159,10 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = tilegx_cpu_class_by_name; cc->has_work = tilegx_cpu_has_work; - cc->do_interrupt = tilegx_cpu_do_interrupt; - cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt; cc->dump_state = tilegx_cpu_dump_state; cc->set_pc = tilegx_cpu_set_pc; - cc->tlb_fill = tilegx_cpu_tlb_fill; cc->gdb_num_core_regs = 0; - cc->tcg_initialize = tilegx_tcg_init; + cc->tcg_ops = &tilegx_tcg_ops; } static const TypeInfo tilegx_cpu_type_info = { diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index 4bff1d4718..0b1e139bcb 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -142,6 +142,14 @@ static void tc27x_initfn(Object *obj) set_feature(&cpu->env, TRICORE_FEATURE_161); } +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps tricore_tcg_ops = { + .initialize = tricore_tcg_init, + .synchronize_from_tb = tricore_cpu_synchronize_from_tb, + .tlb_fill = tricore_cpu_tlb_fill, +}; + static void tricore_cpu_class_init(ObjectClass *c, void *data) { TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c); @@ -162,10 +170,8 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) cc->dump_state = tricore_cpu_dump_state; cc->set_pc = tricore_cpu_set_pc; - cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug; - cc->tcg_initialize = tricore_tcg_init; - cc->tlb_fill = tricore_cpu_tlb_fill; + cc->tcg_ops = &tricore_tcg_ops; } #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \ diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c index b27fb9689f..0258884f84 100644 --- a/target/unicore32/cpu.c +++ b/target/unicore32/cpu.c @@ -120,6 +120,18 @@ static const VMStateDescription vmstate_uc32_cpu = { .unmigratable = 1, }; +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps uc32_tcg_ops = { + .initialize = uc32_translate_init, + .cpu_exec_interrupt = uc32_cpu_exec_interrupt, + .tlb_fill = uc32_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = uc32_cpu_do_interrupt, +#endif /* !CONFIG_USER_ONLY */ +}; + static void uc32_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -131,14 +143,11 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = uc32_cpu_class_by_name; cc->has_work = uc32_cpu_has_work; - cc->do_interrupt = uc32_cpu_do_interrupt; - cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt; cc->dump_state = uc32_cpu_dump_state; cc->set_pc = uc32_cpu_set_pc; - cc->tlb_fill = uc32_cpu_tlb_fill; cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug; - cc->tcg_initialize = uc32_translate_init; dc->vmsd = &vmstate_uc32_cpu; + cc->tcg_ops = &uc32_tcg_ops; } #define DEFINE_UNICORE32_CPU_TYPE(cpu_model, initfn) \ diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 88a32268a1..e2b2c7a71c 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -181,6 +181,21 @@ static const VMStateDescription vmstate_xtensa_cpu = { .unmigratable = 1, }; +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps xtensa_tcg_ops = { + .initialize = xtensa_translate_init, + .cpu_exec_interrupt = xtensa_cpu_exec_interrupt, + .tlb_fill = xtensa_cpu_tlb_fill, + .debug_excp_handler = xtensa_breakpoint_handler, + +#ifndef CONFIG_USER_ONLY + .do_interrupt = xtensa_cpu_do_interrupt, + .do_transaction_failed = xtensa_cpu_do_transaction_failed, + .do_unaligned_access = xtensa_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; + static void xtensa_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -194,23 +209,17 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = xtensa_cpu_class_by_name; cc->has_work = xtensa_cpu_has_work; - cc->do_interrupt = xtensa_cpu_do_interrupt; - cc->cpu_exec_interrupt = xtensa_cpu_exec_interrupt; cc->dump_state = xtensa_cpu_dump_state; cc->set_pc = xtensa_cpu_set_pc; cc->gdb_read_register = xtensa_cpu_gdb_read_register; cc->gdb_write_register = xtensa_cpu_gdb_write_register; cc->gdb_stop_before_watchpoint = true; - cc->tlb_fill = xtensa_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY - cc->do_unaligned_access = xtensa_cpu_do_unaligned_access; cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; - cc->do_transaction_failed = xtensa_cpu_do_transaction_failed; #endif - cc->debug_excp_handler = xtensa_breakpoint_handler; cc->disas_set_info = xtensa_cpu_disas_set_info; - cc->tcg_initialize = xtensa_translate_init; dc->vmsd = &vmstate_xtensa_cpu; + cc->tcg_ops = &xtensa_tcg_ops; } static const TypeInfo xtensa_cpu_type_info = { diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 05e2b7f70a..eeffee297d 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -261,7 +261,7 @@ bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, cpu_loop_exit_restore(cs, retaddr); } -#else +#else /* !CONFIG_USER_ONLY */ void xtensa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, @@ -337,4 +337,4 @@ void xtensa_runstall(CPUXtensaState *env, bool runstall) qemu_cpu_kick(cpu); } } -#endif +#endif /* !CONFIG_USER_ONLY */ diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index 3c1ee39fd4..1376cdc404 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -2488,7 +2488,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, v0 = temp_tcgv_vec(arg_temp(a0)); v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg))); a2 = va_arg(va, TCGArg); - v2 = temp_tcgv_vec(arg_temp(a2)); + va_end(va); switch (opc) { case INDEX_op_rotli_vec: @@ -2502,6 +2502,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: /* Right shifts are negative left shifts for AArch64. */ + v2 = temp_tcgv_vec(arg_temp(a2)); t1 = tcg_temp_new_vec(type); tcg_gen_neg_vec(vece, t1, v2); opc = (opc == INDEX_op_shrv_vec @@ -2512,6 +2513,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, break; case INDEX_op_rotlv_vec: + v2 = temp_tcgv_vec(arg_temp(a2)); t1 = tcg_temp_new_vec(type); c1 = tcg_constant_vec(type, vece, 8 << vece); tcg_gen_sub_vec(vece, t1, v2, c1); @@ -2525,6 +2527,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, break; case INDEX_op_rotrv_vec: + v2 = temp_tcgv_vec(arg_temp(a2)); t1 = tcg_temp_new_vec(type); t2 = tcg_temp_new_vec(type); c1 = tcg_constant_vec(type, vece, 8 << vece); @@ -2543,8 +2546,6 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, default: g_assert_not_reached(); } - - va_end(va); } static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc index b67470137c..695d7ee652 100644 --- a/tcg/s390/tcg-target.c.inc +++ b/tcg/s390/tcg-target.c.inc @@ -1067,7 +1067,7 @@ static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, op = (is_unsigned ? RIL_CLFI : RIL_CFI); tcg_out_insn_RIL(s, op, r1, c2); goto exit; - } else if (c2 == (is_unsigned ? (uint32_t)c2 : (int32_t)c2)) { + } else if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) { op = (is_unsigned ? RIL_CLGFI : RIL_CGFI); tcg_out_insn_RIL(s, op, r1, c2); goto exit; diff --git a/tcg/tcg-common.c b/tcg/tcg-common.c index 7e1992e79e..aa0c4f60c9 100644 --- a/tcg/tcg-common.c +++ b/tcg/tcg-common.c @@ -25,10 +25,6 @@ #include "qemu/osdep.h" #include "tcg/tcg.h" -#if defined(CONFIG_TCG_INTERPRETER) -uintptr_t tci_tb_ptr; -#endif - TCGOpDef tcg_op_defs[] = { #define DEF(s, oargs, iargs, cargs, flags) \ { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, @@ -33,14 +33,6 @@ #include "tcg/tcg-op.h" #include "qemu/compiler.h" -/* Marker for missing code. */ -#define TODO() \ - do { \ - fprintf(stderr, "TODO %s:%u: %s()\n", \ - __FILE__, __LINE__, __func__); \ - tcg_abort(); \ - } while (0) - #if MAX_OPC_PARAM_IARGS != 6 # error Fix needed, number of supported input arguments changed! #endif @@ -57,6 +49,8 @@ typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong); #endif +__thread uintptr_t tci_tb_ptr; + static tcg_target_ulong tci_read_reg(const tcg_target_ulong *regs, TCGReg index) { tci_assert(index < TCG_TARGET_NB_REGS); @@ -115,33 +109,6 @@ tci_write_reg(tcg_target_ulong *regs, TCGReg index, tcg_target_ulong value) regs[index] = value; } -#if TCG_TARGET_REG_BITS == 64 -static void -tci_write_reg32s(tcg_target_ulong *regs, TCGReg index, int32_t value) -{ - tci_write_reg(regs, index, value); -} -#endif - -static void tci_write_reg8(tcg_target_ulong *regs, TCGReg index, uint8_t value) -{ - tci_write_reg(regs, index, value); -} - -#if TCG_TARGET_REG_BITS == 64 -static void -tci_write_reg16(tcg_target_ulong *regs, TCGReg index, uint16_t value) -{ - tci_write_reg(regs, index, value); -} -#endif - -static void -tci_write_reg32(tcg_target_ulong *regs, TCGReg index, uint32_t value) -{ - tci_write_reg(regs, index, value); -} - #if TCG_TARGET_REG_BITS == 32 static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index, uint32_t low_index, uint64_t value) @@ -149,12 +116,6 @@ static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index, tci_write_reg(regs, low_index, value); tci_write_reg(regs, high_index, value >> 32); } -#elif TCG_TARGET_REG_BITS == 64 -static void -tci_write_reg64(tcg_target_ulong *regs, TCGReg index, uint64_t value) -{ - tci_write_reg(regs, index, value); -} #endif #if TCG_TARGET_REG_BITS == 32 @@ -294,61 +255,6 @@ tci_read_ulong(const tcg_target_ulong *regs, const uint8_t **tb_ptr) return taddr; } -/* Read indexed register or constant (native size) from bytecode. */ -static tcg_target_ulong -tci_read_ri(const tcg_target_ulong *regs, const uint8_t **tb_ptr) -{ - tcg_target_ulong value; - TCGReg r = **tb_ptr; - *tb_ptr += 1; - if (r == TCG_CONST) { - value = tci_read_i(tb_ptr); - } else { - value = tci_read_reg(regs, r); - } - return value; -} - -/* Read indexed register or constant (32 bit) from bytecode. */ -static uint32_t tci_read_ri32(const tcg_target_ulong *regs, - const uint8_t **tb_ptr) -{ - uint32_t value; - TCGReg r = **tb_ptr; - *tb_ptr += 1; - if (r == TCG_CONST) { - value = tci_read_i32(tb_ptr); - } else { - value = tci_read_reg32(regs, r); - } - return value; -} - -#if TCG_TARGET_REG_BITS == 32 -/* Read two indexed registers or constants (2 * 32 bit) from bytecode. */ -static uint64_t tci_read_ri64(const tcg_target_ulong *regs, - const uint8_t **tb_ptr) -{ - uint32_t low = tci_read_ri32(regs, tb_ptr); - return tci_uint64(tci_read_ri32(regs, tb_ptr), low); -} -#elif TCG_TARGET_REG_BITS == 64 -/* Read indexed register or constant (64 bit) from bytecode. */ -static uint64_t tci_read_ri64(const tcg_target_ulong *regs, - const uint8_t **tb_ptr) -{ - uint64_t value; - TCGReg r = **tb_ptr; - *tb_ptr += 1; - if (r == TCG_CONST) { - value = tci_read_i64(tb_ptr); - } else { - value = tci_read_reg64(regs, r); - } - return value; -} -#endif - static tcg_target_ulong tci_read_label(const uint8_t **tb_ptr) { tcg_target_ulong label = tci_read_i(tb_ptr); @@ -393,7 +299,7 @@ static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition) result = (u0 > u1); break; default: - TODO(); + g_assert_not_reached(); } return result; } @@ -435,7 +341,7 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition) result = (u0 > u1); break; default: - TODO(); + g_assert_not_reached(); } return result; } @@ -486,6 +392,18 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition) # define qemu_st_beq(X) stq_be_p(g2h(taddr), X) #endif +#if TCG_TARGET_REG_BITS == 64 +# define CASE_32_64(x) \ + case glue(glue(INDEX_op_, x), _i64): \ + case glue(glue(INDEX_op_, x), _i32): +# define CASE_64(x) \ + case glue(glue(INDEX_op_, x), _i64): +#else +# define CASE_32_64(x) \ + case glue(glue(INDEX_op_, x), _i32): +# define CASE_64(x) +#endif + /* Interpret pseudo code in tb. */ /* * Disable CFI checks. @@ -526,29 +444,26 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, #endif TCGMemOpIdx oi; -#if defined(GETPC) - tci_tb_ptr = (uintptr_t)tb_ptr; -#endif - /* Skip opcode and size entry. */ tb_ptr += 2; switch (opc) { case INDEX_op_call: - t0 = tci_read_ri(regs, &tb_ptr); + t0 = tci_read_i(&tb_ptr); + tci_tb_ptr = (uintptr_t)tb_ptr; #if TCG_TARGET_REG_BITS == 32 tmp64 = ((helper_function)t0)(tci_read_reg(regs, TCG_REG_R0), tci_read_reg(regs, TCG_REG_R1), tci_read_reg(regs, TCG_REG_R2), tci_read_reg(regs, TCG_REG_R3), + tci_read_reg(regs, TCG_REG_R4), tci_read_reg(regs, TCG_REG_R5), tci_read_reg(regs, TCG_REG_R6), tci_read_reg(regs, TCG_REG_R7), tci_read_reg(regs, TCG_REG_R8), tci_read_reg(regs, TCG_REG_R9), tci_read_reg(regs, TCG_REG_R10), - tci_read_reg(regs, TCG_REG_R11), - tci_read_reg(regs, TCG_REG_R12)); + tci_read_reg(regs, TCG_REG_R11)); tci_write_reg(regs, TCG_REG_R0, tmp64); tci_write_reg(regs, TCG_REG_R1, tmp64 >> 32); #else @@ -556,8 +471,8 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tci_read_reg(regs, TCG_REG_R1), tci_read_reg(regs, TCG_REG_R2), tci_read_reg(regs, TCG_REG_R3), - tci_read_reg(regs, TCG_REG_R5), - tci_read_reg(regs, TCG_REG_R6)); + tci_read_reg(regs, TCG_REG_R4), + tci_read_reg(regs, TCG_REG_R5)); tci_write_reg(regs, TCG_REG_R0, tmp64); #endif break; @@ -569,78 +484,88 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_setcond_i32: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); condition = *tb_ptr++; - tci_write_reg32(regs, t0, tci_compare32(t1, t2, condition)); + tci_write_reg(regs, t0, tci_compare32(t1, t2, condition)); break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_setcond2_i32: t0 = *tb_ptr++; tmp64 = tci_read_r64(regs, &tb_ptr); - v64 = tci_read_ri64(regs, &tb_ptr); + v64 = tci_read_r64(regs, &tb_ptr); condition = *tb_ptr++; - tci_write_reg32(regs, t0, tci_compare64(tmp64, v64, condition)); + tci_write_reg(regs, t0, tci_compare64(tmp64, v64, condition)); break; #elif TCG_TARGET_REG_BITS == 64 case INDEX_op_setcond_i64: t0 = *tb_ptr++; t1 = tci_read_r64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); condition = *tb_ptr++; - tci_write_reg64(regs, t0, tci_compare64(t1, t2, condition)); + tci_write_reg(regs, t0, tci_compare64(t1, t2, condition)); break; #endif case INDEX_op_mov_i32: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; case INDEX_op_tci_movi_i32: t0 = *tb_ptr++; t1 = tci_read_i32(&tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; /* Load/store operations (32 bit). */ - case INDEX_op_ld8u_i32: + CASE_32_64(ld8u) t0 = *tb_ptr++; t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_write_reg8(regs, t0, *(uint8_t *)(t1 + t2)); + tci_write_reg(regs, t0, *(uint8_t *)(t1 + t2)); break; - case INDEX_op_ld8s_i32: - TODO(); + CASE_32_64(ld8s) + t0 = *tb_ptr++; + t1 = tci_read_r(regs, &tb_ptr); + t2 = tci_read_s32(&tb_ptr); + tci_write_reg(regs, t0, *(int8_t *)(t1 + t2)); break; - case INDEX_op_ld16u_i32: - TODO(); + CASE_32_64(ld16u) + t0 = *tb_ptr++; + t1 = tci_read_r(regs, &tb_ptr); + t2 = tci_read_s32(&tb_ptr); + tci_write_reg(regs, t0, *(uint16_t *)(t1 + t2)); break; - case INDEX_op_ld16s_i32: - TODO(); + CASE_32_64(ld16s) + t0 = *tb_ptr++; + t1 = tci_read_r(regs, &tb_ptr); + t2 = tci_read_s32(&tb_ptr); + tci_write_reg(regs, t0, *(int16_t *)(t1 + t2)); break; case INDEX_op_ld_i32: + CASE_64(ld32u) t0 = *tb_ptr++; t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_write_reg32(regs, t0, *(uint32_t *)(t1 + t2)); + tci_write_reg(regs, t0, *(uint32_t *)(t1 + t2)); break; - case INDEX_op_st8_i32: + CASE_32_64(st8) t0 = tci_read_r8(regs, &tb_ptr); t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint8_t *)(t1 + t2) = t0; break; - case INDEX_op_st16_i32: + CASE_32_64(st16) t0 = tci_read_r16(regs, &tb_ptr); t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint16_t *)(t1 + t2) = t0; break; case INDEX_op_st_i32: + CASE_64(st32) t0 = tci_read_r32(regs, &tb_ptr); t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_assert(t1 != sp_value || (int32_t)t2 < 0); *(uint32_t *)(t1 + t2) = t0; break; @@ -648,104 +573,97 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_add_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 + t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 + t2); break; case INDEX_op_sub_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 - t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 - t2); break; case INDEX_op_mul_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 * t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 * t2); break; -#if TCG_TARGET_HAS_div_i32 case INDEX_op_div_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, (int32_t)t1 / (int32_t)t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, (int32_t)t1 / (int32_t)t2); break; case INDEX_op_divu_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 / t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 / t2); break; case INDEX_op_rem_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, (int32_t)t1 % (int32_t)t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, (int32_t)t1 % (int32_t)t2); break; case INDEX_op_remu_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 % t2); - break; -#elif TCG_TARGET_HAS_div2_i32 - case INDEX_op_div2_i32: - case INDEX_op_divu2_i32: - TODO(); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 % t2); break; -#endif case INDEX_op_and_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 & t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 & t2); break; case INDEX_op_or_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 | t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 | t2); break; case INDEX_op_xor_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 ^ t2); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 ^ t2); break; /* Shift/rotate operations (32 bit). */ case INDEX_op_shl_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 << (t2 & 31)); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 << (t2 & 31)); break; case INDEX_op_shr_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1 >> (t2 & 31)); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 >> (t2 & 31)); break; case INDEX_op_sar_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, ((int32_t)t1 >> (t2 & 31))); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, ((int32_t)t1 >> (t2 & 31))); break; #if TCG_TARGET_HAS_rot_i32 case INDEX_op_rotl_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, rol32(t1, t2 & 31)); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, rol32(t1, t2 & 31)); break; case INDEX_op_rotr_i32: t0 = *tb_ptr++; - t1 = tci_read_ri32(regs, &tb_ptr); - t2 = tci_read_ri32(regs, &tb_ptr); - tci_write_reg32(regs, t0, ror32(t1, t2 & 31)); + t1 = tci_read_r32(regs, &tb_ptr); + t2 = tci_read_r32(regs, &tb_ptr); + tci_write_reg(regs, t0, ror32(t1, t2 & 31)); break; #endif #if TCG_TARGET_HAS_deposit_i32 @@ -756,12 +674,12 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp32 = (((1 << tmp8) - 1) << tmp16); - tci_write_reg32(regs, t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32)); + tci_write_reg(regs, t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32)); break; #endif case INDEX_op_brcond_i32: t0 = tci_read_r32(regs, &tb_ptr); - t1 = tci_read_ri32(regs, &tb_ptr); + t1 = tci_read_r32(regs, &tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare32(t0, t1, condition)) { @@ -787,7 +705,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, break; case INDEX_op_brcond2_i32: tmp64 = tci_read_r64(regs, &tb_ptr); - v64 = tci_read_ri64(regs, &tb_ptr); + v64 = tci_read_r64(regs, &tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(tmp64, v64, condition)) { @@ -808,131 +726,88 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_ext8s_i32: t0 = *tb_ptr++; t1 = tci_read_r8s(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i32 case INDEX_op_ext16s_i32: t0 = *tb_ptr++; t1 = tci_read_r16s(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext8u_i32 case INDEX_op_ext8u_i32: t0 = *tb_ptr++; t1 = tci_read_r8(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i32 case INDEX_op_ext16u_i32: t0 = *tb_ptr++; t1 = tci_read_r16(regs, &tb_ptr); - tci_write_reg32(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_bswap16_i32 case INDEX_op_bswap16_i32: t0 = *tb_ptr++; t1 = tci_read_r16(regs, &tb_ptr); - tci_write_reg32(regs, t0, bswap16(t1)); + tci_write_reg(regs, t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i32 case INDEX_op_bswap32_i32: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg32(regs, t0, bswap32(t1)); + tci_write_reg(regs, t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_not_i32 case INDEX_op_not_i32: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg32(regs, t0, ~t1); + tci_write_reg(regs, t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i32 case INDEX_op_neg_i32: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg32(regs, t0, -t1); + tci_write_reg(regs, t0, -t1); break; #endif #if TCG_TARGET_REG_BITS == 64 case INDEX_op_mov_i64: t0 = *tb_ptr++; t1 = tci_read_r64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; case INDEX_op_tci_movi_i64: t0 = *tb_ptr++; t1 = tci_read_i64(&tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; /* Load/store operations (64 bit). */ - case INDEX_op_ld8u_i64: - t0 = *tb_ptr++; - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - tci_write_reg8(regs, t0, *(uint8_t *)(t1 + t2)); - break; - case INDEX_op_ld8s_i64: - TODO(); - break; - case INDEX_op_ld16u_i64: - t0 = *tb_ptr++; - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - tci_write_reg16(regs, t0, *(uint16_t *)(t1 + t2)); - break; - case INDEX_op_ld16s_i64: - TODO(); - break; - case INDEX_op_ld32u_i64: - t0 = *tb_ptr++; - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - tci_write_reg32(regs, t0, *(uint32_t *)(t1 + t2)); - break; case INDEX_op_ld32s_i64: t0 = *tb_ptr++; t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_write_reg32s(regs, t0, *(int32_t *)(t1 + t2)); + tci_write_reg(regs, t0, *(int32_t *)(t1 + t2)); break; case INDEX_op_ld_i64: t0 = *tb_ptr++; t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_write_reg64(regs, t0, *(uint64_t *)(t1 + t2)); - break; - case INDEX_op_st8_i64: - t0 = tci_read_r8(regs, &tb_ptr); - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - *(uint8_t *)(t1 + t2) = t0; - break; - case INDEX_op_st16_i64: - t0 = tci_read_r16(regs, &tb_ptr); - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - *(uint16_t *)(t1 + t2) = t0; - break; - case INDEX_op_st32_i64: - t0 = tci_read_r32(regs, &tb_ptr); - t1 = tci_read_r(regs, &tb_ptr); - t2 = tci_read_s32(&tb_ptr); - *(uint32_t *)(t1 + t2) = t0; + tci_write_reg(regs, t0, *(uint64_t *)(t1 + t2)); break; case INDEX_op_st_i64: t0 = tci_read_r64(regs, &tb_ptr); t1 = tci_read_r(regs, &tb_ptr); t2 = tci_read_s32(&tb_ptr); - tci_assert(t1 != sp_value || (int32_t)t2 < 0); *(uint64_t *)(t1 + t2) = t0; break; @@ -940,86 +815,97 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_add_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 + t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 + t2); break; case INDEX_op_sub_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 - t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 - t2); break; case INDEX_op_mul_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 * t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 * t2); break; -#if TCG_TARGET_HAS_div_i64 case INDEX_op_div_i64: + t0 = *tb_ptr++; + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, (int64_t)t1 / (int64_t)t2); + break; case INDEX_op_divu_i64: + t0 = *tb_ptr++; + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, (uint64_t)t1 / (uint64_t)t2); + break; case INDEX_op_rem_i64: - case INDEX_op_remu_i64: - TODO(); + t0 = *tb_ptr++; + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, (int64_t)t1 % (int64_t)t2); break; -#elif TCG_TARGET_HAS_div2_i64 - case INDEX_op_div2_i64: - case INDEX_op_divu2_i64: - TODO(); + case INDEX_op_remu_i64: + t0 = *tb_ptr++; + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, (uint64_t)t1 % (uint64_t)t2); break; -#endif case INDEX_op_and_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 & t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 & t2); break; case INDEX_op_or_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 | t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 | t2); break; case INDEX_op_xor_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 ^ t2); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 ^ t2); break; /* Shift/rotate operations (64 bit). */ case INDEX_op_shl_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 << (t2 & 63)); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 << (t2 & 63)); break; case INDEX_op_shr_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1 >> (t2 & 63)); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, t1 >> (t2 & 63)); break; case INDEX_op_sar_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, ((int64_t)t1 >> (t2 & 63))); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, ((int64_t)t1 >> (t2 & 63))); break; #if TCG_TARGET_HAS_rot_i64 case INDEX_op_rotl_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, rol64(t1, t2 & 63)); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, rol64(t1, t2 & 63)); break; case INDEX_op_rotr_i64: t0 = *tb_ptr++; - t1 = tci_read_ri64(regs, &tb_ptr); - t2 = tci_read_ri64(regs, &tb_ptr); - tci_write_reg64(regs, t0, ror64(t1, t2 & 63)); + t1 = tci_read_r64(regs, &tb_ptr); + t2 = tci_read_r64(regs, &tb_ptr); + tci_write_reg(regs, t0, ror64(t1, t2 & 63)); break; #endif #if TCG_TARGET_HAS_deposit_i64 @@ -1030,12 +916,12 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp64 = (((1ULL << tmp8) - 1) << tmp16); - tci_write_reg64(regs, t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64)); + tci_write_reg(regs, t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64)); break; #endif case INDEX_op_brcond_i64: t0 = tci_read_r64(regs, &tb_ptr); - t1 = tci_read_ri64(regs, &tb_ptr); + t1 = tci_read_r64(regs, &tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(t0, t1, condition)) { @@ -1048,28 +934,28 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_ext8u_i64: t0 = *tb_ptr++; t1 = tci_read_r8(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext8s_i64 case INDEX_op_ext8s_i64: t0 = *tb_ptr++; t1 = tci_read_r8s(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i64 case INDEX_op_ext16s_i64: t0 = *tb_ptr++; t1 = tci_read_r16s(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i64 case INDEX_op_ext16u_i64: t0 = *tb_ptr++; t1 = tci_read_r16(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #endif #if TCG_TARGET_HAS_ext32s_i64 @@ -1078,7 +964,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_ext_i32_i64: t0 = *tb_ptr++; t1 = tci_read_r32s(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #if TCG_TARGET_HAS_ext32u_i64 case INDEX_op_ext32u_i64: @@ -1086,41 +972,41 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, case INDEX_op_extu_i32_i64: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg64(regs, t0, t1); + tci_write_reg(regs, t0, t1); break; #if TCG_TARGET_HAS_bswap16_i64 case INDEX_op_bswap16_i64: t0 = *tb_ptr++; t1 = tci_read_r16(regs, &tb_ptr); - tci_write_reg64(regs, t0, bswap16(t1)); + tci_write_reg(regs, t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i64 case INDEX_op_bswap32_i64: t0 = *tb_ptr++; t1 = tci_read_r32(regs, &tb_ptr); - tci_write_reg64(regs, t0, bswap32(t1)); + tci_write_reg(regs, t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_bswap64_i64 case INDEX_op_bswap64_i64: t0 = *tb_ptr++; t1 = tci_read_r64(regs, &tb_ptr); - tci_write_reg64(regs, t0, bswap64(t1)); + tci_write_reg(regs, t0, bswap64(t1)); break; #endif #if TCG_TARGET_HAS_not_i64 case INDEX_op_not_i64: t0 = *tb_ptr++; t1 = tci_read_r64(regs, &tb_ptr); - tci_write_reg64(regs, t0, ~t1); + tci_write_reg(regs, t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i64 case INDEX_op_neg_i64: t0 = *tb_ptr++; t1 = tci_read_r64(regs, &tb_ptr); - tci_write_reg64(regs, t0, -t1); + tci_write_reg(regs, t0, -t1); break; #endif #endif /* TCG_TARGET_REG_BITS == 64 */ @@ -1169,7 +1055,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tmp32 = qemu_ld_beul; break; default: - tcg_abort(); + g_assert_not_reached(); } tci_write_reg(regs, t0, tmp32); break; @@ -1218,7 +1104,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tmp64 = qemu_ld_beq; break; default: - tcg_abort(); + g_assert_not_reached(); } tci_write_reg(regs, t0, tmp64); if (TCG_TARGET_REG_BITS == 32) { @@ -1246,7 +1132,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, qemu_st_bel(t0); break; default: - tcg_abort(); + g_assert_not_reached(); } break; case INDEX_op_qemu_st_i64: @@ -1276,7 +1162,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, qemu_st_beq(tmp64); break; default: - tcg_abort(); + g_assert_not_reached(); } break; case INDEX_op_mb: @@ -1284,8 +1170,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, smp_mb(); break; default: - TODO(); - break; + g_assert_not_reached(); } tci_assert(tb_ptr == old_code_ptr + op_size); } diff --git a/tcg/tci/tcg-target-con-set.h b/tcg/tci/tcg-target-con-set.h index 38e82f7535..f51b7bcb13 100644 --- a/tcg/tci/tcg-target-con-set.h +++ b/tcg/tci/tcg-target-con-set.h @@ -10,16 +10,12 @@ * tcg-target-con-str.h; the constraint combination is inclusive or. */ C_O0_I2(r, r) -C_O0_I2(r, ri) C_O0_I3(r, r, r) -C_O0_I4(r, r, ri, ri) C_O0_I4(r, r, r, r) C_O1_I1(r, r) C_O1_I2(r, 0, r) -C_O1_I2(r, ri, ri) C_O1_I2(r, r, r) -C_O1_I2(r, r, ri) -C_O1_I4(r, r, r, ri, ri) +C_O1_I4(r, r, r, r, r) C_O2_I1(r, r, r) C_O2_I2(r, r, r, r) C_O2_I4(r, r, r, r, r, r) diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc index f0f6b13112..feac4659cc 100644 --- a/tcg/tci/tcg-target.c.inc +++ b/tcg/tci/tcg-target.c.inc @@ -92,8 +92,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_rem_i64: case INDEX_op_remu_i32: case INDEX_op_remu_i64: - return C_O1_I2(r, r, r); - case INDEX_op_add_i32: case INDEX_op_add_i64: case INDEX_op_sub_i32: @@ -126,8 +124,9 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_rotl_i64: case INDEX_op_rotr_i32: case INDEX_op_rotr_i64: - /* TODO: Does R, RI, RI result in faster code than R, R, RI? */ - return C_O1_I2(r, ri, ri); + case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: + return C_O1_I2(r, r, r); case INDEX_op_deposit_i32: case INDEX_op_deposit_i64: @@ -135,11 +134,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: - return C_O0_I2(r, ri); - - case INDEX_op_setcond_i32: - case INDEX_op_setcond_i64: - return C_O1_I2(r, r, ri); + return C_O0_I2(r, r); #if TCG_TARGET_REG_BITS == 32 /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */ @@ -147,11 +142,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_sub2_i32: return C_O2_I4(r, r, r, r, r, r); case INDEX_op_brcond2_i32: - return C_O0_I4(r, r, ri, ri); + return C_O0_I4(r, r, r, r); case INDEX_op_mulu2_i32: return C_O2_I2(r, r, r, r); case INDEX_op_setcond2_i32: - return C_O1_I4(r, r, r, ri, ri); + return C_O1_I4(r, r, r, r, r); #endif case INDEX_op_qemu_ld_i32: @@ -181,13 +176,10 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R1, TCG_REG_R2, TCG_REG_R3, -#if 0 /* used for TCG_REG_CALL_STACK */ TCG_REG_R4, -#endif TCG_REG_R5, TCG_REG_R6, TCG_REG_R7, -#if TCG_TARGET_NB_REGS >= 16 TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, @@ -196,7 +188,6 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R13, TCG_REG_R14, TCG_REG_R15, -#endif }; #if MAX_OPC_PARAM_IARGS != 6 @@ -208,23 +199,16 @@ static const int tcg_target_call_iarg_regs[] = { TCG_REG_R1, TCG_REG_R2, TCG_REG_R3, -#if 0 /* used for TCG_REG_CALL_STACK */ TCG_REG_R4, -#endif TCG_REG_R5, - TCG_REG_R6, #if TCG_TARGET_REG_BITS == 32 /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */ + TCG_REG_R6, TCG_REG_R7, -#if TCG_TARGET_NB_REGS >= 16 TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, TCG_REG_R11, - TCG_REG_R12, -#else -# error Too few input registers available -#endif #endif }; @@ -245,7 +229,6 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "r05", "r06", "r07", -#if TCG_TARGET_NB_REGS >= 16 "r08", "r09", "r10", @@ -254,25 +237,6 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "r13", "r14", "r15", -#if TCG_TARGET_NB_REGS >= 32 - "r16", - "r17", - "r18", - "r19", - "r20", - "r21", - "r22", - "r23", - "r24", - "r25", - "r26", - "r27", - "r28", - "r29", - "r30", - "r31" -#endif -#endif }; #endif @@ -325,44 +289,6 @@ static void tcg_out_r(TCGContext *s, TCGArg t0) tcg_out8(s, t0); } -/* Write register or constant (native size). */ -static void tcg_out_ri(TCGContext *s, int const_arg, TCGArg arg) -{ - if (const_arg) { - tcg_debug_assert(const_arg == 1); - tcg_out8(s, TCG_CONST); - tcg_out_i(s, arg); - } else { - tcg_out_r(s, arg); - } -} - -/* Write register or constant (32 bit). */ -static void tcg_out_ri32(TCGContext *s, int const_arg, TCGArg arg) -{ - if (const_arg) { - tcg_debug_assert(const_arg == 1); - tcg_out8(s, TCG_CONST); - tcg_out32(s, arg); - } else { - tcg_out_r(s, arg); - } -} - -#if TCG_TARGET_REG_BITS == 64 -/* Write register or constant (64 bit). */ -static void tcg_out_ri64(TCGContext *s, int const_arg, TCGArg arg) -{ - if (const_arg) { - tcg_debug_assert(const_arg == 1); - tcg_out8(s, TCG_CONST); - tcg_out64(s, arg); - } else { - tcg_out_r(s, arg); - } -} -#endif - /* Write label. */ static void tci_out_label(TCGContext *s, TCGLabel *label) { @@ -375,10 +301,20 @@ static void tci_out_label(TCGContext *s, TCGLabel *label) } } +static void stack_bounds_check(TCGReg base, target_long offset) +{ + if (base == TCG_REG_CALL_STACK) { + tcg_debug_assert(offset < 0); + tcg_debug_assert(offset >= -(CPU_TEMP_BUF_NLONGS * sizeof(long))); + } +} + static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, intptr_t arg2) { uint8_t *old_code_ptr = s->code_ptr; + + stack_bounds_check(arg1, arg2); if (type == TCG_TYPE_I32) { tcg_out_op_t(s, INDEX_op_ld_i32); tcg_out_r(s, ret); @@ -440,7 +376,7 @@ static inline void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) { uint8_t *old_code_ptr = s->code_ptr; tcg_out_op_t(s, INDEX_op_call); - tcg_out_ri(s, 1, (uintptr_t)arg); + tcg_out_i(s, (uintptr_t)arg); old_code_ptr[1] = s->code_ptr - old_code_ptr; } @@ -474,7 +410,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_setcond_i32: tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); - tcg_out_ri32(s, const_args[2], args[2]); + tcg_out_r(s, args[2]); tcg_out8(s, args[3]); /* condition */ break; #if TCG_TARGET_REG_BITS == 32 @@ -483,15 +419,15 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); tcg_out_r(s, args[2]); - tcg_out_ri32(s, const_args[3], args[3]); - tcg_out_ri32(s, const_args[4], args[4]); + tcg_out_r(s, args[3]); + tcg_out_r(s, args[4]); tcg_out8(s, args[5]); /* condition */ break; #elif TCG_TARGET_REG_BITS == 64 case INDEX_op_setcond_i64: tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); - tcg_out_ri64(s, const_args[2], args[2]); + tcg_out_r(s, args[2]); tcg_out8(s, args[3]); /* condition */ break; #endif @@ -514,6 +450,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_st16_i64: case INDEX_op_st32_i64: case INDEX_op_st_i64: + stack_bounds_check(args[1], args[2]); tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); tcg_debug_assert(args[2] == (int32_t)args[2]); @@ -536,8 +473,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_rotl_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */ case INDEX_op_rotr_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */ tcg_out_r(s, args[0]); - tcg_out_ri32(s, const_args[1], args[1]); - tcg_out_ri32(s, const_args[2], args[2]); + tcg_out_r(s, args[1]); + tcg_out_r(s, args[2]); break; case INDEX_op_deposit_i32: /* Optional (TCG_TARGET_HAS_deposit_i32). */ tcg_out_r(s, args[0]); @@ -566,9 +503,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_sar_i64: case INDEX_op_rotl_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ case INDEX_op_rotr_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ + case INDEX_op_div_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ + case INDEX_op_divu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ + case INDEX_op_rem_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ + case INDEX_op_remu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ tcg_out_r(s, args[0]); - tcg_out_ri64(s, const_args[1], args[1]); - tcg_out_ri64(s, const_args[2], args[2]); + tcg_out_r(s, args[1]); + tcg_out_r(s, args[2]); break; case INDEX_op_deposit_i64: /* Optional (TCG_TARGET_HAS_deposit_i64). */ tcg_out_r(s, args[0]); @@ -579,19 +520,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_debug_assert(args[4] <= UINT8_MAX); tcg_out8(s, args[4]); break; - case INDEX_op_div_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ - case INDEX_op_divu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ - case INDEX_op_rem_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ - case INDEX_op_remu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */ - TODO(); - break; - case INDEX_op_div2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */ - case INDEX_op_divu2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */ - TODO(); - break; case INDEX_op_brcond_i64: tcg_out_r(s, args[0]); - tcg_out_ri64(s, const_args[1], args[1]); + tcg_out_r(s, args[1]); tcg_out8(s, args[2]); /* condition */ tci_out_label(s, arg_label(args[3])); break; @@ -625,12 +556,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_rem_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ case INDEX_op_remu_i32: /* Optional (TCG_TARGET_HAS_div_i32). */ tcg_out_r(s, args[0]); - tcg_out_ri32(s, const_args[1], args[1]); - tcg_out_ri32(s, const_args[2], args[2]); - break; - case INDEX_op_div2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */ - case INDEX_op_divu2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */ - TODO(); + tcg_out_r(s, args[1]); + tcg_out_r(s, args[2]); break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_add2_i32: @@ -645,8 +572,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_brcond2_i32: tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); - tcg_out_ri32(s, const_args[2], args[2]); - tcg_out_ri32(s, const_args[3], args[3]); + tcg_out_r(s, args[2]); + tcg_out_r(s, args[3]); tcg_out8(s, args[4]); /* condition */ tci_out_label(s, arg_label(args[5])); break; @@ -659,7 +586,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, #endif case INDEX_op_brcond_i32: tcg_out_r(s, args[0]); - tcg_out_ri32(s, const_args[1], args[1]); + tcg_out_r(s, args[1]); tcg_out8(s, args[2]); /* condition */ tci_out_label(s, arg_label(args[3])); break; @@ -716,6 +643,8 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2) { uint8_t *old_code_ptr = s->code_ptr; + + stack_bounds_check(arg1, arg2); if (type == TCG_TYPE_I32) { tcg_out_op_t(s, INDEX_op_st_i32); tcg_out_r(s, arg); diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index bb784e018e..9c0021a26f 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -100,8 +100,8 @@ #define TCG_TARGET_HAS_extract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1 @@ -133,11 +133,8 @@ #define TCG_TARGET_HAS_mulu2_i32 1 #endif /* TCG_TARGET_REG_BITS == 64 */ -/* Number of registers available. - For 32 bit hosts, we need more than 8 registers (call arguments). */ -/* #define TCG_TARGET_NB_REGS 8 */ +/* Number of registers available. */ #define TCG_TARGET_NB_REGS 16 -/* #define TCG_TARGET_NB_REGS 32 */ /* List of registers which are used by TCG. */ typedef enum { @@ -149,7 +146,6 @@ typedef enum { TCG_REG_R5, TCG_REG_R6, TCG_REG_R7, -#if TCG_TARGET_NB_REGS >= 16 TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, @@ -158,33 +154,12 @@ typedef enum { TCG_REG_R13, TCG_REG_R14, TCG_REG_R15, -#if TCG_TARGET_NB_REGS >= 32 - TCG_REG_R16, - TCG_REG_R17, - TCG_REG_R18, - TCG_REG_R19, - TCG_REG_R20, - TCG_REG_R21, - TCG_REG_R22, - TCG_REG_R23, - TCG_REG_R24, - TCG_REG_R25, - TCG_REG_R26, - TCG_REG_R27, - TCG_REG_R28, - TCG_REG_R29, - TCG_REG_R30, - TCG_REG_R31, -#endif -#endif - /* Special value UINT8_MAX is used by TCI to encode constant values. */ - TCG_CONST = UINT8_MAX -} TCGReg; -#define TCG_AREG0 (TCG_TARGET_NB_REGS - 2) + TCG_AREG0 = TCG_REG_R14, + TCG_REG_CALL_STACK = TCG_REG_R15, +} TCGReg; /* Used for function call generation. */ -#define TCG_REG_CALL_STACK (TCG_TARGET_NB_REGS - 1) #define TCG_TARGET_CALL_STACK_OFFSET 0 #define TCG_TARGET_STACK_ALIGN 16 |