aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/cpu.c')
-rw-r--r--target/s390x/cpu.c138
1 files changed, 73 insertions, 65 deletions
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 0fbfcd3..f05ce31 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -25,18 +25,19 @@
#include "cpu.h"
#include "s390x-internal.h"
#include "kvm/kvm_s390x.h"
-#include "sysemu/kvm.h"
+#include "system/kvm.h"
#include "qemu/module.h"
#include "trace.h"
#include "qapi/qapi-types-machine.h"
-#include "sysemu/hw_accel.h"
+#include "system/hw_accel.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
+#include "hw/resettable.h"
#include "fpu/softfloat-helpers.h"
#include "disas/capstone.h"
-#include "sysemu/tcg.h"
+#include "system/tcg.h"
#ifndef CONFIG_USER_ONLY
-#include "sysemu/reset.h"
+#include "system/reset.h"
#endif
#include "hw/s390x/cpu-topology.h"
@@ -125,28 +126,6 @@ static vaddr s390_cpu_get_pc(CPUState *cs)
return cpu->env.psw.addr;
}
-static bool s390_cpu_has_work(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
-
- /* STOPPED cpus can never wake up */
- if (s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD &&
- s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
- return false;
- }
-
- if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
- return false;
- }
-
- return s390_cpu_has_int(cpu);
-}
-
-static int s390x_cpu_mmu_index(CPUState *cs, bool ifetch)
-{
- return s390x_env_mmu_index(cpu_env(cs), ifetch);
-}
-
static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
{
S390CPU *s390_cpu = S390_CPU(cpu);
@@ -162,23 +141,25 @@ static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
#endif
}
-/* S390CPUClass::reset() */
-static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
+/* S390CPUClass Resettable reset_hold phase method */
+static void s390_cpu_reset_hold(Object *obj, ResetType type)
{
- S390CPU *cpu = S390_CPU(s);
+ S390CPU *cpu = S390_CPU(obj);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env;
- DeviceState *dev = DEVICE(s);
- scc->parent_reset(dev);
+ if (scc->parent_phases.hold) {
+ scc->parent_phases.hold(obj, type);
+ }
cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
switch (type) {
- case S390_CPU_RESET_CLEAR:
+ default:
+ /* RESET_TYPE_COLD: power on or "clear" reset */
memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields));
/* fall through */
- case S390_CPU_RESET_INITIAL:
+ case RESET_TYPE_S390_CPU_INITIAL:
/* initial reset does not clear everything! */
memset(&env->start_initial_reset_fields, 0,
offsetof(CPUS390XState, start_normal_reset_fields) -
@@ -202,8 +183,14 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,
&env->fpu_status);
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
+ &env->fpu_status);
+ /* Default NaN value: sign bit clear, frac msb set */
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
/* fall through */
- case S390_CPU_RESET_NORMAL:
+ case RESET_TYPE_S390_CPU_NORMAL:
env->psw.mask &= ~PSW_MASK_RI;
memset(&env->start_normal_reset_fields, 0,
offsetof(CPUS390XState, end_reset_fields) -
@@ -212,20 +199,18 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
env->pfault_token = -1UL;
env->bpbc = false;
break;
- default:
- g_assert_not_reached();
}
/* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) {
switch (type) {
- case S390_CPU_RESET_CLEAR:
+ default:
kvm_s390_reset_vcpu_clear(cpu);
break;
- case S390_CPU_RESET_INITIAL:
+ case RESET_TYPE_S390_CPU_INITIAL:
kvm_s390_reset_vcpu_initial(cpu);
break;
- case S390_CPU_RESET_NORMAL:
+ case RESET_TYPE_S390_CPU_NORMAL:
kvm_s390_reset_vcpu_normal(cpu);
break;
}
@@ -236,6 +221,7 @@ static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
{
info->mach = bfd_mach_s390_64;
info->cap_arch = CS_ARCH_SYSZ;
+ info->endian = BFD_ENDIAN_BIG;
info->cap_insn_unit = 2;
info->cap_insn_split = 6;
}
@@ -253,7 +239,7 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
}
#if !defined(CONFIG_USER_ONLY)
- if (!s390_cpu_realize_sysemu(dev, &err)) {
+ if (!s390_cpu_system_realize(dev, &err)) {
goto out;
}
#endif
@@ -293,7 +279,7 @@ static void s390_cpu_initfn(Object *obj)
cs->exception_index = EXCP_HLT;
#if !defined(CONFIG_USER_ONLY)
- s390_cpu_init_sysemu(obj);
+ s390_cpu_system_init(obj);
#endif
}
@@ -302,8 +288,8 @@ static const gchar *s390_gdb_arch_name(CPUState *cs)
return "s390:64-bit";
}
-static Property s390x_cpu_properties[] = {
-#if !defined(CONFIG_USER_ONLY)
+#ifndef CONFIG_USER_ONLY
+static const Property s390x_cpu_properties[] = {
DEFINE_PROP_UINT32("core-id", S390CPU, env.core_id, 0),
DEFINE_PROP_INT32("socket-id", S390CPU, env.socket_id, -1),
DEFINE_PROP_INT32("book-id", S390CPU, env.book_id, -1),
@@ -311,22 +297,21 @@ static Property s390x_cpu_properties[] = {
DEFINE_PROP_BOOL("dedicated", S390CPU, env.dedicated, false),
DEFINE_PROP_CPUS390ENTITLEMENT("entitlement", S390CPU, env.entitlement,
S390_CPU_ENTITLEMENT_AUTO),
-#endif
- DEFINE_PROP_END_OF_LIST()
};
+#endif
-static void s390_cpu_reset_full(DeviceState *dev)
+#ifdef CONFIG_TCG
+#include "accel/tcg/cpu-ops.h"
+#include "tcg/tcg_s390x.h"
+
+static int s390x_cpu_mmu_index(CPUState *cs, bool ifetch)
{
- CPUState *s = CPU(dev);
- return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
+ return s390x_env_mmu_index(cpu_env(cs), ifetch);
}
-#ifdef CONFIG_TCG
-#include "hw/core/tcg-cpu-ops.h"
-
-void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
- uint64_t *cs_base, uint32_t *pflags)
+static TCGTBCPUState s390x_get_tb_cpu_state(CPUState *cs)
{
+ CPUS390XState *env = cpu_env(cs);
uint32_t flags;
if (env->psw.addr & 1) {
@@ -338,9 +323,6 @@ void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, 0);
}
- *pc = env->psw.addr;
- *cs_base = env->ex_value;
-
flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
if (env->psw.mask & PSW_MASK_PER) {
flags |= env->cregs[9] & (FLAG_MASK_PER_BRANCH |
@@ -357,20 +339,46 @@ void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
if (env->cregs[0] & CR0_VECTOR) {
flags |= FLAG_MASK_VECTOR;
}
- *pflags = flags;
+
+ return (TCGTBCPUState){
+ .pc = env->psw.addr,
+ .flags = flags,
+ .cs_base = env->ex_value,
+ };
}
+#ifndef CONFIG_USER_ONLY
+static vaddr s390_pointer_wrap(CPUState *cs, int mmu_idx,
+ vaddr result, vaddr base)
+{
+ return wrap_address(cpu_env(cs), result);
+}
+#endif
+
static const TCGCPUOps s390_tcg_ops = {
+ .mttcg_supported = true,
+ .precise_smc = true,
+ /*
+ * The z/Architecture has a strong memory model with some
+ * store-after-load re-ordering.
+ */
+ .guest_default_memory_order = TCG_MO_ALL & ~TCG_MO_ST_LD,
+
.initialize = s390x_translate_init,
+ .translate_code = s390x_translate_code,
+ .get_tb_cpu_state = s390x_get_tb_cpu_state,
.restore_state_to_opc = s390x_restore_state_to_opc,
+ .mmu_index = s390x_cpu_mmu_index,
#ifdef CONFIG_USER_ONLY
.record_sigsegv = s390_cpu_record_sigsegv,
.record_sigbus = s390_cpu_record_sigbus,
#else
.tlb_fill = s390_cpu_tlb_fill,
+ .pointer_wrap = s390_pointer_wrap,
.cpu_exec_interrupt = s390_cpu_exec_interrupt,
.cpu_exec_halt = s390_cpu_has_work,
+ .cpu_exec_reset = cpu_reset,
.do_interrupt = s390_cpu_do_interrupt,
.debug_excp_handler = s390x_cpu_debug_excp_handler,
.do_unaligned_access = s390x_cpu_do_unaligned_access,
@@ -378,23 +386,22 @@ static const TCGCPUOps s390_tcg_ops = {
};
#endif /* CONFIG_TCG */
-static void s390_cpu_class_init(ObjectClass *oc, void *data)
+static void s390_cpu_class_init(ObjectClass *oc, const void *data)
{
S390CPUClass *scc = S390_CPU_CLASS(oc);
CPUClass *cc = CPU_CLASS(scc);
DeviceClass *dc = DEVICE_CLASS(oc);
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
device_class_set_parent_realize(dc, s390_cpu_realizefn,
&scc->parent_realize);
- device_class_set_props(dc, s390x_cpu_properties);
dc->user_creatable = true;
- device_class_set_parent_reset(dc, s390_cpu_reset_full, &scc->parent_reset);
+ resettable_class_set_parent_phases(rc, NULL, s390_cpu_reset_hold, NULL,
+ &scc->parent_phases);
- scc->reset = s390_cpu_reset;
- cc->class_by_name = s390_cpu_class_by_name,
- cc->has_work = s390_cpu_has_work;
- cc->mmu_index = s390x_cpu_mmu_index;
+ cc->class_by_name = s390_cpu_class_by_name;
+ cc->list_cpus = s390_cpu_list;
cc->dump_state = s390_cpu_dump_state;
cc->query_cpu_fast = s390_query_cpu_fast;
cc->set_pc = s390_cpu_set_pc;
@@ -402,7 +409,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->gdb_write_register = s390_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- s390_cpu_class_init_sysemu(cc);
+ device_class_set_props(dc, s390x_cpu_properties);
+ s390_cpu_system_class_init(cc);
#endif
cc->disas_set_info = s390_cpu_disas_set_info;
cc->gdb_core_xml_file = "s390x-core64.xml";