2020-12-12 18:55:14 +03:00
|
|
|
/*
|
|
|
|
* i386 TCG cpu class initialization
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003 Fabrice Bellard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "helper-tcg.h"
|
2021-03-22 16:27:40 +03:00
|
|
|
#include "qemu/accel.h"
|
|
|
|
#include "hw/core/accel-cpu.h"
|
2020-12-12 18:55:14 +03:00
|
|
|
|
2021-05-06 18:20:23 +03:00
|
|
|
#include "tcg-cpu.h"
|
2020-12-12 18:55:14 +03:00
|
|
|
|
|
|
|
/* Frob eflags into and out of the CPU temporary format. */
|
|
|
|
|
|
|
|
static void x86_cpu_exec_enter(CPUState *cs)
|
|
|
|
{
|
|
|
|
X86CPU *cpu = X86_CPU(cs);
|
|
|
|
CPUX86State *env = &cpu->env;
|
|
|
|
|
|
|
|
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
|
|
|
env->df = 1 - (2 * ((env->eflags >> 10) & 1));
|
|
|
|
CC_OP = CC_OP_EFLAGS;
|
|
|
|
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void x86_cpu_exec_exit(CPUState *cs)
|
|
|
|
{
|
|
|
|
X86CPU *cpu = X86_CPU(cs);
|
|
|
|
CPUX86State *env = &cpu->env;
|
|
|
|
|
|
|
|
env->eflags = cpu_compute_eflags(env);
|
|
|
|
}
|
|
|
|
|
2020-10-29 22:30:01 +03:00
|
|
|
static void x86_cpu_synchronize_from_tb(CPUState *cs,
|
|
|
|
const TranslationBlock *tb)
|
2020-12-12 18:55:14 +03:00
|
|
|
{
|
2023-02-27 16:51:42 +03:00
|
|
|
/* The instruction pointer is always up to date with CF_PCREL. */
|
|
|
|
if (!(tb_cflags(tb) & CF_PCREL)) {
|
2023-09-14 03:22:49 +03:00
|
|
|
CPUX86State *env = cpu_env(cs);
|
2023-02-27 16:51:57 +03:00
|
|
|
env->eip = tb->pc - tb->cs_base;
|
2022-10-01 17:09:35 +03:00
|
|
|
}
|
2020-12-12 18:55:14 +03:00
|
|
|
}
|
|
|
|
|
2022-10-24 13:18:03 +03:00
|
|
|
static void x86_restore_state_to_opc(CPUState *cs,
|
|
|
|
const TranslationBlock *tb,
|
|
|
|
const uint64_t *data)
|
|
|
|
{
|
|
|
|
X86CPU *cpu = X86_CPU(cs);
|
|
|
|
CPUX86State *env = &cpu->env;
|
|
|
|
int cc_op = data[1];
|
|
|
|
|
2023-02-27 16:51:42 +03:00
|
|
|
if (tb_cflags(tb) & CF_PCREL) {
|
2022-10-24 13:18:03 +03:00
|
|
|
env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
|
|
|
|
} else {
|
|
|
|
env->eip = data[0] - tb->cs_base;
|
|
|
|
}
|
|
|
|
if (cc_op != CC_OP_DYNAMIC) {
|
|
|
|
env->cc_op = cc_op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-19 21:22:47 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
static bool x86_debug_check_breakpoint(CPUState *cs)
|
|
|
|
{
|
|
|
|
X86CPU *cpu = X86_CPU(cs);
|
|
|
|
CPUX86State *env = &cpu->env;
|
|
|
|
|
|
|
|
/* RF disables all architectural breakpoints. */
|
|
|
|
return !(env->eflags & RF_MASK);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-02-04 19:39:23 +03:00
|
|
|
#include "hw/core/tcg-cpu-ops.h"
|
|
|
|
|
2021-02-28 02:21:17 +03:00
|
|
|
static const struct TCGCPUOps x86_tcg_ops = {
|
2021-02-04 19:39:23 +03:00
|
|
|
.initialize = tcg_x86_init,
|
|
|
|
.synchronize_from_tb = x86_cpu_synchronize_from_tb,
|
2022-10-24 13:18:03 +03:00
|
|
|
.restore_state_to_opc = x86_restore_state_to_opc,
|
2021-02-04 19:39:23 +03:00
|
|
|
.cpu_exec_enter = x86_cpu_exec_enter,
|
|
|
|
.cpu_exec_exit = x86_cpu_exec_exit,
|
2021-09-11 19:54:15 +03:00
|
|
|
#ifdef CONFIG_USER_ONLY
|
|
|
|
.fake_user_interrupt = x86_cpu_do_interrupt,
|
2021-09-18 05:10:25 +03:00
|
|
|
.record_sigsegv = x86_cpu_record_sigsegv,
|
2022-09-18 01:27:12 +03:00
|
|
|
.record_sigbus = x86_cpu_record_sigbus,
|
2021-09-11 19:54:15 +03:00
|
|
|
#else
|
2021-09-18 05:10:25 +03:00
|
|
|
.tlb_fill = x86_cpu_tlb_fill,
|
2021-09-11 19:54:15 +03:00
|
|
|
.do_interrupt = x86_cpu_do_interrupt,
|
2021-09-11 19:54:20 +03:00
|
|
|
.cpu_exec_interrupt = x86_cpu_exec_interrupt,
|
2022-09-18 01:27:12 +03:00
|
|
|
.do_unaligned_access = x86_cpu_do_unaligned_access,
|
2021-02-04 19:39:23 +03:00
|
|
|
.debug_excp_handler = breakpoint_handler,
|
2021-07-19 21:22:47 +03:00
|
|
|
.debug_check_breakpoint = x86_debug_check_breakpoint,
|
2021-02-04 19:39:23 +03:00
|
|
|
#endif /* !CONFIG_USER_ONLY */
|
|
|
|
};
|
|
|
|
|
2021-03-22 16:27:59 +03:00
|
|
|
static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
|
2020-12-12 18:55:14 +03:00
|
|
|
{
|
2021-03-22 16:27:59 +03:00
|
|
|
/* for x86, all cpus use the same set of operations */
|
2021-02-04 19:39:23 +03:00
|
|
|
cc->tcg_ops = &x86_tcg_ops;
|
2020-12-12 18:55:14 +03:00
|
|
|
}
|
2021-03-22 16:27:40 +03:00
|
|
|
|
2021-03-22 16:27:59 +03:00
|
|
|
static void tcg_cpu_class_init(CPUClass *cc)
|
|
|
|
{
|
|
|
|
cc->init_accel_cpu = tcg_cpu_init_ops;
|
|
|
|
}
|
|
|
|
|
2021-07-05 13:46:31 +03:00
|
|
|
static void tcg_cpu_xsave_init(void)
|
|
|
|
{
|
|
|
|
#define XO(bit, field) \
|
|
|
|
x86_ext_save_areas[bit].offset = offsetof(X86XSaveArea, field);
|
|
|
|
|
|
|
|
XO(XSTATE_FP_BIT, legacy);
|
|
|
|
XO(XSTATE_SSE_BIT, legacy);
|
|
|
|
XO(XSTATE_YMM_BIT, avx_state);
|
|
|
|
XO(XSTATE_BNDREGS_BIT, bndreg_state);
|
|
|
|
XO(XSTATE_BNDCSR_BIT, bndcsr_state);
|
|
|
|
XO(XSTATE_OPMASK_BIT, opmask_state);
|
|
|
|
XO(XSTATE_ZMM_Hi256_BIT, zmm_hi256_state);
|
|
|
|
XO(XSTATE_Hi16_ZMM_BIT, hi16_zmm_state);
|
|
|
|
XO(XSTATE_PKRU_BIT, pkru_state);
|
|
|
|
|
|
|
|
#undef XO
|
|
|
|
}
|
|
|
|
|
2021-03-22 16:27:40 +03:00
|
|
|
/*
|
i386: do not call cpudef-only models functions for max, host, base
Some cpu properties have to be set only for cpu models in builtin_x86_defs,
registered with x86_register_cpu_model_type, and not for
cpu models "base", "max", and the subclass "host".
These properties are the ones set by function x86_cpu_apply_props,
(also including kvm_default_props, tcg_default_props),
and the "vendor" property for the KVM and HVF accelerators.
After recent refactoring of cpu, which also affected these properties,
they were instead set unconditionally for all x86 cpus.
This has been detected as a bug with Nested on AMD with cpu "host",
as svm was not turned on by default, due to the wrongful setting of
kvm_default_props via x86_cpu_apply_props, which set svm to "off".
Rectify the bug introduced in commit "i386: split cpu accelerators"
and document the functions that are builtin_x86_defs-only.
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Tested-by: Alexander Bulekov <alxndr@bu.edu>
Fixes: f5cc5a5c ("i386: split cpu accelerators from cpu.c,"...)
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/477
Message-Id: <20210723112921.12637-1-cfontana@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-07-23 14:29:21 +03:00
|
|
|
* TCG-specific defaults that override cpudef models when using TCG.
|
|
|
|
* Only for builtin_x86_defs models initialized with x86_register_cpudef_types.
|
2021-03-22 16:27:40 +03:00
|
|
|
*/
|
|
|
|
static PropValue tcg_default_props[] = {
|
|
|
|
{ "vme", "off" },
|
|
|
|
{ NULL, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void tcg_cpu_instance_init(CPUState *cs)
|
|
|
|
{
|
|
|
|
X86CPU *cpu = X86_CPU(cs);
|
i386: do not call cpudef-only models functions for max, host, base
Some cpu properties have to be set only for cpu models in builtin_x86_defs,
registered with x86_register_cpu_model_type, and not for
cpu models "base", "max", and the subclass "host".
These properties are the ones set by function x86_cpu_apply_props,
(also including kvm_default_props, tcg_default_props),
and the "vendor" property for the KVM and HVF accelerators.
After recent refactoring of cpu, which also affected these properties,
they were instead set unconditionally for all x86 cpus.
This has been detected as a bug with Nested on AMD with cpu "host",
as svm was not turned on by default, due to the wrongful setting of
kvm_default_props via x86_cpu_apply_props, which set svm to "off".
Rectify the bug introduced in commit "i386: split cpu accelerators"
and document the functions that are builtin_x86_defs-only.
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Tested-by: Alexander Bulekov <alxndr@bu.edu>
Fixes: f5cc5a5c ("i386: split cpu accelerators from cpu.c,"...)
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/477
Message-Id: <20210723112921.12637-1-cfontana@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-07-23 14:29:21 +03:00
|
|
|
X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
|
|
|
|
|
|
|
|
if (xcc->model) {
|
|
|
|
/* Special cases not set in the X86CPUDefinition structs: */
|
|
|
|
x86_cpu_apply_props(cpu, tcg_default_props);
|
|
|
|
}
|
2021-07-05 13:46:31 +03:00
|
|
|
|
|
|
|
tcg_cpu_xsave_init();
|
2021-03-22 16:27:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
|
|
|
|
{
|
|
|
|
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
|
|
|
|
|
2021-05-06 18:20:23 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2023-10-03 15:30:20 +03:00
|
|
|
acc->cpu_target_realize = tcg_cpu_realizefn;
|
2021-05-06 18:20:23 +03:00
|
|
|
#endif /* CONFIG_USER_ONLY */
|
|
|
|
|
2021-03-22 16:27:40 +03:00
|
|
|
acc->cpu_class_init = tcg_cpu_class_init;
|
|
|
|
acc->cpu_instance_init = tcg_cpu_instance_init;
|
|
|
|
}
|
|
|
|
static const TypeInfo tcg_cpu_accel_type_info = {
|
|
|
|
.name = ACCEL_CPU_NAME("tcg"),
|
|
|
|
|
|
|
|
.parent = TYPE_ACCEL_CPU,
|
|
|
|
.class_init = tcg_cpu_accel_class_init,
|
|
|
|
.abstract = true,
|
|
|
|
};
|
|
|
|
static void tcg_cpu_accel_register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&tcg_cpu_accel_type_info);
|
|
|
|
}
|
|
|
|
type_init(tcg_cpu_accel_register_types);
|