xref: /openbmc/qemu/target/s390x/cpu.c (revision f15f7273ea55472d5904c53566c82369d81214c1)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  * QEMU S/390 CPU
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  * Copyright (c) 2009 Ulrich Hecht
5fcf5ef2aSThomas Huth  * Copyright (c) 2011 Alexander Graf
6fcf5ef2aSThomas Huth  * Copyright (c) 2012 SUSE LINUX Products GmbH
7fcf5ef2aSThomas Huth  * Copyright (c) 2012 IBM Corp.
8fcf5ef2aSThomas Huth  *
944699e1cSThomas Huth  * This program is free software; you can redistribute it and/or modify
1044699e1cSThomas Huth  * it under the terms of the GNU General Public License as published by
1144699e1cSThomas Huth  * the Free Software Foundation; either version 2 of the License, or
1244699e1cSThomas Huth  * (at your option) any later version.
13fcf5ef2aSThomas Huth  *
1444699e1cSThomas Huth  * This program is distributed in the hope that it will be useful,
15fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1744699e1cSThomas Huth  * General Public License for more details.
18fcf5ef2aSThomas Huth  *
1944699e1cSThomas Huth  * You should have received a copy of the GNU General Public License
2044699e1cSThomas Huth  * along with this program; if not, see <http://www.gnu.org/licenses/>.
21fcf5ef2aSThomas Huth  */
22fcf5ef2aSThomas Huth 
23fcf5ef2aSThomas Huth #include "qemu/osdep.h"
24fcf5ef2aSThomas Huth #include "qapi/error.h"
25fcf5ef2aSThomas Huth #include "cpu.h"
26b6b47223SCho, Yu-Chen #include "s390x-internal.h"
2767043607SCho, Yu-Chen #include "kvm/kvm_s390x.h"
28f16bbb9bSDavid Hildenbrand #include "sysemu/kvm.h"
290b8fa32fSMarkus Armbruster #include "qemu/module.h"
30fcf5ef2aSThomas Huth #include "trace.h"
318ac25c84SMarkus Armbruster #include "qapi/qapi-types-machine.h"
324ada99adSChristian Borntraeger #include "sysemu/hw_accel.h"
33ca5c1457SDavid Hildenbrand #include "hw/qdev-properties.h"
345de1aff2SPierre Morel #include "hw/qdev-properties-system.h"
35cf7f61d1SPeter Maydell #include "hw/resettable.h"
365f8ab000SAlex Bennée #include "fpu/softfloat-helpers.h"
373d562845SRichard Henderson #include "disas/capstone.h"
3898be64d2SCho, Yu-Chen #include "sysemu/tcg.h"
39057733f2SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
40057733f2SPhilippe Mathieu-Daudé #include "sysemu/reset.h"
41057733f2SPhilippe Mathieu-Daudé #endif
42ad2d1afcSPierre Morel #include "hw/s390x/cpu-topology.h"
43fcf5ef2aSThomas Huth 
44fcf5ef2aSThomas Huth #define CR0_RESET       0xE0UL
45fcf5ef2aSThomas Huth #define CR14_RESET      0xC2000000UL;
46fcf5ef2aSThomas Huth 
47199c42a6SIlya Leoshkevich #ifndef CONFIG_USER_ONLY
is_early_exception_psw(uint64_t mask,uint64_t addr)48199c42a6SIlya Leoshkevich static bool is_early_exception_psw(uint64_t mask, uint64_t addr)
49199c42a6SIlya Leoshkevich {
50199c42a6SIlya Leoshkevich     if (mask & PSW_MASK_RESERVED) {
51199c42a6SIlya Leoshkevich         return true;
52199c42a6SIlya Leoshkevich     }
53199c42a6SIlya Leoshkevich 
54199c42a6SIlya Leoshkevich     switch (mask & (PSW_MASK_32 | PSW_MASK_64)) {
55199c42a6SIlya Leoshkevich     case 0:
56199c42a6SIlya Leoshkevich         return addr & ~0xffffffULL;
57199c42a6SIlya Leoshkevich     case PSW_MASK_32:
58199c42a6SIlya Leoshkevich         return addr & ~0x7fffffffULL;
59199c42a6SIlya Leoshkevich     case PSW_MASK_32 | PSW_MASK_64:
60199c42a6SIlya Leoshkevich         return false;
61199c42a6SIlya Leoshkevich     default: /* PSW_MASK_64 */
62199c42a6SIlya Leoshkevich         return true;
63199c42a6SIlya Leoshkevich     }
64199c42a6SIlya Leoshkevich }
65199c42a6SIlya Leoshkevich #endif
66199c42a6SIlya Leoshkevich 
s390_cpu_set_psw(CPUS390XState * env,uint64_t mask,uint64_t addr)6798be64d2SCho, Yu-Chen void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
6898be64d2SCho, Yu-Chen {
6998be64d2SCho, Yu-Chen #ifndef CONFIG_USER_ONLY
7098be64d2SCho, Yu-Chen     uint64_t old_mask = env->psw.mask;
7198be64d2SCho, Yu-Chen #endif
7298be64d2SCho, Yu-Chen 
7398be64d2SCho, Yu-Chen     env->psw.addr = addr;
7498be64d2SCho, Yu-Chen     env->psw.mask = mask;
7598be64d2SCho, Yu-Chen 
7698be64d2SCho, Yu-Chen     /* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
7798be64d2SCho, Yu-Chen     if (!tcg_enabled()) {
7898be64d2SCho, Yu-Chen         return;
7998be64d2SCho, Yu-Chen     }
8098be64d2SCho, Yu-Chen     env->cc_op = (mask >> 44) & 3;
8198be64d2SCho, Yu-Chen 
8298be64d2SCho, Yu-Chen #ifndef CONFIG_USER_ONLY
83199c42a6SIlya Leoshkevich     if (is_early_exception_psw(mask, addr)) {
84199c42a6SIlya Leoshkevich         env->int_pgm_ilen = 0;
85199c42a6SIlya Leoshkevich         trigger_pgm_exception(env, PGM_SPECIFICATION);
86199c42a6SIlya Leoshkevich         return;
87199c42a6SIlya Leoshkevich     }
88199c42a6SIlya Leoshkevich 
8998be64d2SCho, Yu-Chen     if ((old_mask ^ mask) & PSW_MASK_PER) {
9098be64d2SCho, Yu-Chen         s390_cpu_recompute_watchpoints(env_cpu(env));
9198be64d2SCho, Yu-Chen     }
9298be64d2SCho, Yu-Chen 
9398be64d2SCho, Yu-Chen     if (mask & PSW_MASK_WAIT) {
9498be64d2SCho, Yu-Chen         s390_handle_wait(env_archcpu(env));
9598be64d2SCho, Yu-Chen     }
9698be64d2SCho, Yu-Chen #endif
9798be64d2SCho, Yu-Chen }
9898be64d2SCho, Yu-Chen 
s390_cpu_get_psw_mask(CPUS390XState * env)9998be64d2SCho, Yu-Chen uint64_t s390_cpu_get_psw_mask(CPUS390XState *env)
10098be64d2SCho, Yu-Chen {
10198be64d2SCho, Yu-Chen     uint64_t r = env->psw.mask;
10298be64d2SCho, Yu-Chen 
10398be64d2SCho, Yu-Chen     if (tcg_enabled()) {
10498be64d2SCho, Yu-Chen         uint64_t cc = calc_cc(env, env->cc_op, env->cc_src,
10598be64d2SCho, Yu-Chen                               env->cc_dst, env->cc_vr);
10698be64d2SCho, Yu-Chen 
10798be64d2SCho, Yu-Chen         assert(cc <= 3);
10898be64d2SCho, Yu-Chen         r &= ~PSW_MASK_CC;
10998be64d2SCho, Yu-Chen         r |= cc << 44;
11098be64d2SCho, Yu-Chen     }
11198be64d2SCho, Yu-Chen 
11298be64d2SCho, Yu-Chen     return r;
11398be64d2SCho, Yu-Chen }
11498be64d2SCho, Yu-Chen 
s390_cpu_set_pc(CPUState * cs,vaddr value)115fcf5ef2aSThomas Huth static void s390_cpu_set_pc(CPUState *cs, vaddr value)
116fcf5ef2aSThomas Huth {
117fcf5ef2aSThomas Huth     S390CPU *cpu = S390_CPU(cs);
118fcf5ef2aSThomas Huth 
119fcf5ef2aSThomas Huth     cpu->env.psw.addr = value;
120fcf5ef2aSThomas Huth }
121fcf5ef2aSThomas Huth 
s390_cpu_get_pc(CPUState * cs)122e4fdf9dfSRichard Henderson static vaddr s390_cpu_get_pc(CPUState *cs)
123e4fdf9dfSRichard Henderson {
124e4fdf9dfSRichard Henderson     S390CPU *cpu = S390_CPU(cs);
125e4fdf9dfSRichard Henderson 
126e4fdf9dfSRichard Henderson     return cpu->env.psw.addr;
127e4fdf9dfSRichard Henderson }
128e4fdf9dfSRichard Henderson 
s390_cpu_has_work(CPUState * cs)129fcf5ef2aSThomas Huth static bool s390_cpu_has_work(CPUState *cs)
130fcf5ef2aSThomas Huth {
131fcf5ef2aSThomas Huth     S390CPU *cpu = S390_CPU(cs);
132fcf5ef2aSThomas Huth 
1334beab671SDavid Hildenbrand     /* STOPPED cpus can never wake up */
1349d0306dfSViktor Mihajlovski     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD &&
1359d0306dfSViktor Mihajlovski         s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
1364beab671SDavid Hildenbrand         return false;
1374beab671SDavid Hildenbrand     }
1384beab671SDavid Hildenbrand 
1398417f904SDavid Hildenbrand     if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
1408417f904SDavid Hildenbrand         return false;
1418417f904SDavid Hildenbrand     }
1428417f904SDavid Hildenbrand 
1438417f904SDavid Hildenbrand     return s390_cpu_has_int(cpu);
144fcf5ef2aSThomas Huth }
145fcf5ef2aSThomas Huth 
s390x_cpu_mmu_index(CPUState * cs,bool ifetch)1464ef80b27SRichard Henderson static int s390x_cpu_mmu_index(CPUState *cs, bool ifetch)
1474ef80b27SRichard Henderson {
1484ef80b27SRichard Henderson     return s390x_env_mmu_index(cpu_env(cs), ifetch);
1494ef80b27SRichard Henderson }
1504ef80b27SRichard Henderson 
s390_query_cpu_fast(CPUState * cpu,CpuInfoFast * value)1515503da4aSThomas Huth static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
1525503da4aSThomas Huth {
1535503da4aSThomas Huth     S390CPU *s390_cpu = S390_CPU(cpu);
1545503da4aSThomas Huth 
1555503da4aSThomas Huth     value->u.s390x.cpu_state = s390_cpu->env.cpu_state;
156ad2d1afcSPierre Morel #if !defined(CONFIG_USER_ONLY)
157ad2d1afcSPierre Morel     if (s390_has_topology()) {
158ad2d1afcSPierre Morel         value->u.s390x.has_dedicated = true;
159ad2d1afcSPierre Morel         value->u.s390x.dedicated = s390_cpu->env.dedicated;
160ad2d1afcSPierre Morel         value->u.s390x.has_entitlement = true;
161ad2d1afcSPierre Morel         value->u.s390x.entitlement = s390_cpu->env.entitlement;
162ad2d1afcSPierre Morel     }
163ad2d1afcSPierre Morel #endif
1645503da4aSThomas Huth }
1655503da4aSThomas Huth 
166cf7f61d1SPeter Maydell /* S390CPUClass Resettable reset_hold phase method */
s390_cpu_reset_hold(Object * obj,ResetType type)167cf7f61d1SPeter Maydell static void s390_cpu_reset_hold(Object *obj, ResetType type)
168fcf5ef2aSThomas Huth {
169cf7f61d1SPeter Maydell     S390CPU *cpu = S390_CPU(obj);
170fcf5ef2aSThomas Huth     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
171fcf5ef2aSThomas Huth     CPUS390XState *env = &cpu->env;
172fcf5ef2aSThomas Huth 
173cf7f61d1SPeter Maydell     if (scc->parent_phases.hold) {
174cf7f61d1SPeter Maydell         scc->parent_phases.hold(obj, type);
175cf7f61d1SPeter Maydell     }
176fcf5ef2aSThomas Huth     cpu->env.sigp_order = 0;
1779d0306dfSViktor Mihajlovski     s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
178eac4f827SJanosch Frank 
179eac4f827SJanosch Frank     switch (type) {
180cf7f61d1SPeter Maydell     default:
181cf7f61d1SPeter Maydell         /* RESET_TYPE_COLD: power on or "clear" reset */
182eb8adcc3SJanosch Frank         memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields));
183eb8adcc3SJanosch Frank         /* fall through */
184cf7f61d1SPeter Maydell     case RESET_TYPE_S390_CPU_INITIAL:
18581b92223SJanosch Frank         /* initial reset does not clear everything! */
18681b92223SJanosch Frank         memset(&env->start_initial_reset_fields, 0,
187e893baeeSJanosch Frank                offsetof(CPUS390XState, start_normal_reset_fields) -
18881b92223SJanosch Frank                offsetof(CPUS390XState, start_initial_reset_fields));
18981b92223SJanosch Frank 
19081b92223SJanosch Frank         /* architectured initial value for Breaking-Event-Address register */
19181b92223SJanosch Frank         env->gbea = 1;
19281b92223SJanosch Frank 
19381b92223SJanosch Frank         /* architectured initial values for CR 0 and 14 */
19481b92223SJanosch Frank         env->cregs[0] = CR0_RESET;
19581b92223SJanosch Frank         env->cregs[14] = CR14_RESET;
19681b92223SJanosch Frank 
197eb8adcc3SJanosch Frank #if defined(CONFIG_USER_ONLY)
198eb8adcc3SJanosch Frank         /* user mode should always be allowed to use the full FPU */
199eb8adcc3SJanosch Frank         env->cregs[0] |= CR0_AFP;
200eb8adcc3SJanosch Frank         if (s390_has_feat(S390_FEAT_VECTOR)) {
201eb8adcc3SJanosch Frank             env->cregs[0] |= CR0_VECTOR;
202eb8adcc3SJanosch Frank         }
203eb8adcc3SJanosch Frank #endif
204eb8adcc3SJanosch Frank 
20581b92223SJanosch Frank         /* tininess for underflow is detected before rounding */
20681b92223SJanosch Frank         set_float_detect_tininess(float_tininess_before_rounding,
20781b92223SJanosch Frank                                   &env->fpu_status);
208*841f9d74SPeter Maydell         set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20981b92223SJanosch Frank        /* fall through */
210cf7f61d1SPeter Maydell     case RESET_TYPE_S390_CPU_NORMAL:
211e893baeeSJanosch Frank         env->psw.mask &= ~PSW_MASK_RI;
212e893baeeSJanosch Frank         memset(&env->start_normal_reset_fields, 0,
213e893baeeSJanosch Frank                offsetof(CPUS390XState, end_reset_fields) -
214e893baeeSJanosch Frank                offsetof(CPUS390XState, start_normal_reset_fields));
215e893baeeSJanosch Frank 
216eac4f827SJanosch Frank         env->pfault_token = -1UL;
217eac4f827SJanosch Frank         env->bpbc = false;
218eac4f827SJanosch Frank         break;
219eac4f827SJanosch Frank     }
220fcf5ef2aSThomas Huth 
221fcf5ef2aSThomas Huth     /* Reset state inside the kernel that we cannot access yet from QEMU. */
222b91a0394SJanosch Frank     if (kvm_enabled()) {
223b91a0394SJanosch Frank         switch (type) {
224cf7f61d1SPeter Maydell         default:
225b91a0394SJanosch Frank             kvm_s390_reset_vcpu_clear(cpu);
226b91a0394SJanosch Frank             break;
227cf7f61d1SPeter Maydell         case RESET_TYPE_S390_CPU_INITIAL:
228b91a0394SJanosch Frank             kvm_s390_reset_vcpu_initial(cpu);
229b91a0394SJanosch Frank             break;
230cf7f61d1SPeter Maydell         case RESET_TYPE_S390_CPU_NORMAL:
231b91a0394SJanosch Frank             kvm_s390_reset_vcpu_normal(cpu);
232b91a0394SJanosch Frank             break;
233b91a0394SJanosch Frank         }
234fcf5ef2aSThomas Huth     }
235fcf5ef2aSThomas Huth }
236fcf5ef2aSThomas Huth 
s390_cpu_disas_set_info(CPUState * cpu,disassemble_info * info)237fcf5ef2aSThomas Huth static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
238fcf5ef2aSThomas Huth {
239fcf5ef2aSThomas Huth     info->mach = bfd_mach_s390_64;
2403d562845SRichard Henderson     info->cap_arch = CS_ARCH_SYSZ;
2413d562845SRichard Henderson     info->cap_insn_unit = 2;
2423d562845SRichard Henderson     info->cap_insn_split = 6;
243fcf5ef2aSThomas Huth }
244fcf5ef2aSThomas Huth 
s390_cpu_realizefn(DeviceState * dev,Error ** errp)245fcf5ef2aSThomas Huth static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
246fcf5ef2aSThomas Huth {
247fcf5ef2aSThomas Huth     CPUState *cs = CPU(dev);
248fcf5ef2aSThomas Huth     S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
249fcf5ef2aSThomas Huth     Error *err = NULL;
250fcf5ef2aSThomas Huth 
251fcf5ef2aSThomas Huth     /* the model has to be realized before qemu_init_vcpu() due to kvm */
252fcf5ef2aSThomas Huth     s390_realize_cpu_model(cs, &err);
253fcf5ef2aSThomas Huth     if (err) {
254fcf5ef2aSThomas Huth         goto out;
255fcf5ef2aSThomas Huth     }
256fcf5ef2aSThomas Huth 
257fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
25872ffb631SCho, Yu-Chen     if (!s390_cpu_realize_sysemu(dev, &err)) {
259fcf5ef2aSThomas Huth         goto out;
260fcf5ef2aSThomas Huth     }
2611e70ba24SDavid Hildenbrand #endif
2621e70ba24SDavid Hildenbrand 
263fcf5ef2aSThomas Huth     cpu_exec_realizefn(cs, &err);
264fcf5ef2aSThomas Huth     if (err != NULL) {
265fcf5ef2aSThomas Huth         goto out;
266fcf5ef2aSThomas Huth     }
267fcf5ef2aSThomas Huth 
268fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
26972ffb631SCho, Yu-Chen     qemu_register_reset(s390_cpu_machine_reset_cb, S390_CPU(dev));
270fcf5ef2aSThomas Huth #endif
271fcf5ef2aSThomas Huth     s390_cpu_gdb_init(cs);
272fcf5ef2aSThomas Huth     qemu_init_vcpu(cs);
273d66b43c8SDavid Hildenbrand 
274d66b43c8SDavid Hildenbrand     /*
275d66b43c8SDavid Hildenbrand      * KVM requires the initial CPU reset ioctl to be executed on the target
276d66b43c8SDavid Hildenbrand      * CPU thread. CPU hotplug under single-threaded TCG will not work with
277d66b43c8SDavid Hildenbrand      * run_on_cpu(), as run_on_cpu() will not work properly if called while
278d66b43c8SDavid Hildenbrand      * the main thread is already running but the CPU hasn't been realized.
279d66b43c8SDavid Hildenbrand      */
280d66b43c8SDavid Hildenbrand     if (kvm_enabled()) {
281fcf5ef2aSThomas Huth         run_on_cpu(cs, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
282d66b43c8SDavid Hildenbrand     } else {
283fcf5ef2aSThomas Huth         cpu_reset(cs);
284d66b43c8SDavid Hildenbrand     }
285fcf5ef2aSThomas Huth 
286fcf5ef2aSThomas Huth     scc->parent_realize(dev, &err);
287fcf5ef2aSThomas Huth out:
288fcf5ef2aSThomas Huth     error_propagate(errp, err);
289fcf5ef2aSThomas Huth }
290fcf5ef2aSThomas Huth 
s390_cpu_initfn(Object * obj)291fcf5ef2aSThomas Huth static void s390_cpu_initfn(Object *obj)
292fcf5ef2aSThomas Huth {
293fcf5ef2aSThomas Huth     CPUState *cs = CPU(obj);
294fcf5ef2aSThomas Huth 
295fcf5ef2aSThomas Huth     cs->exception_index = EXCP_HLT;
296fcf5ef2aSThomas Huth 
297fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
29872ffb631SCho, Yu-Chen     s390_cpu_init_sysemu(obj);
299fcf5ef2aSThomas Huth #endif
30072ffb631SCho, Yu-Chen }
301fcf5ef2aSThomas Huth 
s390_gdb_arch_name(CPUState * cs)302a6506838SAkihiko Odaki static const gchar *s390_gdb_arch_name(CPUState *cs)
303fcf5ef2aSThomas Huth {
304a6506838SAkihiko Odaki     return "s390:64-bit";
305fcf5ef2aSThomas Huth }
306fcf5ef2aSThomas Huth 
307ca5c1457SDavid Hildenbrand static Property s390x_cpu_properties[] = {
3081e70ba24SDavid Hildenbrand #if !defined(CONFIG_USER_ONLY)
309ca5c1457SDavid Hildenbrand     DEFINE_PROP_UINT32("core-id", S390CPU, env.core_id, 0),
3105de1aff2SPierre Morel     DEFINE_PROP_INT32("socket-id", S390CPU, env.socket_id, -1),
3115de1aff2SPierre Morel     DEFINE_PROP_INT32("book-id", S390CPU, env.book_id, -1),
3125de1aff2SPierre Morel     DEFINE_PROP_INT32("drawer-id", S390CPU, env.drawer_id, -1),
3135de1aff2SPierre Morel     DEFINE_PROP_BOOL("dedicated", S390CPU, env.dedicated, false),
3145de1aff2SPierre Morel     DEFINE_PROP_CPUS390ENTITLEMENT("entitlement", S390CPU, env.entitlement,
3155de1aff2SPierre Morel                                    S390_CPU_ENTITLEMENT_AUTO),
3161e70ba24SDavid Hildenbrand #endif
317ca5c1457SDavid Hildenbrand     DEFINE_PROP_END_OF_LIST()
318ca5c1457SDavid Hildenbrand };
319ca5c1457SDavid Hildenbrand 
32078271684SClaudio Fontana #ifdef CONFIG_TCG
32178271684SClaudio Fontana #include "hw/core/tcg-cpu-ops.h"
32278271684SClaudio Fontana 
cpu_get_tb_cpu_state(CPUS390XState * env,vaddr * pc,uint64_t * cs_base,uint32_t * pflags)32336db37afSRichard Henderson void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
32462613ca0SRichard Henderson                           uint64_t *cs_base, uint32_t *pflags)
32536db37afSRichard Henderson {
32662613ca0SRichard Henderson     uint32_t flags;
32762613ca0SRichard Henderson 
32836db37afSRichard Henderson     if (env->psw.addr & 1) {
32936db37afSRichard Henderson         /*
33036db37afSRichard Henderson          * Instructions must be at even addresses.
33136db37afSRichard Henderson          * This needs to be checked before address translation.
33236db37afSRichard Henderson          */
33336db37afSRichard Henderson         env->int_pgm_ilen = 2; /* see s390_cpu_tlb_fill() */
33436db37afSRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, 0);
33536db37afSRichard Henderson     }
33662613ca0SRichard Henderson 
33736db37afSRichard Henderson     *pc = env->psw.addr;
33836db37afSRichard Henderson     *cs_base = env->ex_value;
33962613ca0SRichard Henderson 
34062613ca0SRichard Henderson     flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
34162613ca0SRichard Henderson     if (env->psw.mask & PSW_MASK_PER) {
34262613ca0SRichard Henderson         flags |= env->cregs[9] & (FLAG_MASK_PER_BRANCH |
34362613ca0SRichard Henderson                                   FLAG_MASK_PER_IFETCH |
34462613ca0SRichard Henderson                                   FLAG_MASK_PER_IFETCH_NULLIFY);
34562613ca0SRichard Henderson         if ((env->cregs[9] & PER_CR9_EVENT_STORE) &&
34662613ca0SRichard Henderson             (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
34762613ca0SRichard Henderson             flags |= FLAG_MASK_PER_STORE_REAL;
34862613ca0SRichard Henderson         }
34962613ca0SRichard Henderson     }
35036db37afSRichard Henderson     if (env->cregs[0] & CR0_AFP) {
35162613ca0SRichard Henderson         flags |= FLAG_MASK_AFP;
35236db37afSRichard Henderson     }
35336db37afSRichard Henderson     if (env->cregs[0] & CR0_VECTOR) {
35462613ca0SRichard Henderson         flags |= FLAG_MASK_VECTOR;
35536db37afSRichard Henderson     }
35662613ca0SRichard Henderson     *pflags = flags;
35736db37afSRichard Henderson }
35836db37afSRichard Henderson 
3591764ad70SRichard Henderson static const TCGCPUOps s390_tcg_ops = {
36078271684SClaudio Fontana     .initialize = s390x_translate_init,
3613479783bSRichard Henderson     .restore_state_to_opc = s390x_restore_state_to_opc,
36278271684SClaudio Fontana 
363c8e7fef1SRichard Henderson #ifdef CONFIG_USER_ONLY
364c8e7fef1SRichard Henderson     .record_sigsegv = s390_cpu_record_sigsegv,
3655bcbf356SRichard Henderson     .record_sigbus = s390_cpu_record_sigbus,
366c8e7fef1SRichard Henderson #else
367c8e7fef1SRichard Henderson     .tlb_fill = s390_cpu_tlb_fill,
36878271684SClaudio Fontana     .cpu_exec_interrupt = s390_cpu_exec_interrupt,
3694f7b1ecbSPeter Maydell     .cpu_exec_halt = s390_cpu_has_work,
37078271684SClaudio Fontana     .do_interrupt = s390_cpu_do_interrupt,
37178271684SClaudio Fontana     .debug_excp_handler = s390x_cpu_debug_excp_handler,
37278271684SClaudio Fontana     .do_unaligned_access = s390x_cpu_do_unaligned_access,
37378271684SClaudio Fontana #endif /* !CONFIG_USER_ONLY */
37478271684SClaudio Fontana };
37578271684SClaudio Fontana #endif /* CONFIG_TCG */
37678271684SClaudio Fontana 
s390_cpu_class_init(ObjectClass * oc,void * data)377fcf5ef2aSThomas Huth static void s390_cpu_class_init(ObjectClass *oc, void *data)
378fcf5ef2aSThomas Huth {
379fcf5ef2aSThomas Huth     S390CPUClass *scc = S390_CPU_CLASS(oc);
380fcf5ef2aSThomas Huth     CPUClass *cc = CPU_CLASS(scc);
381fcf5ef2aSThomas Huth     DeviceClass *dc = DEVICE_CLASS(oc);
382cf7f61d1SPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(oc);
383fcf5ef2aSThomas Huth 
384bf853881SPhilippe Mathieu-Daudé     device_class_set_parent_realize(dc, s390_cpu_realizefn,
385bf853881SPhilippe Mathieu-Daudé                                     &scc->parent_realize);
3864f67d30bSMarc-André Lureau     device_class_set_props(dc, s390x_cpu_properties);
3870347ab84SDavid Hildenbrand     dc->user_creatable = true;
388fcf5ef2aSThomas Huth 
389cf7f61d1SPeter Maydell     resettable_class_set_parent_phases(rc, NULL, s390_cpu_reset_hold, NULL,
390cf7f61d1SPeter Maydell                                        &scc->parent_phases);
39172ffb631SCho, Yu-Chen 
392fcf5ef2aSThomas Huth     cc->class_by_name = s390_cpu_class_by_name,
393fcf5ef2aSThomas Huth     cc->has_work = s390_cpu_has_work;
3944ef80b27SRichard Henderson     cc->mmu_index = s390x_cpu_mmu_index;
395fcf5ef2aSThomas Huth     cc->dump_state = s390_cpu_dump_state;
3965503da4aSThomas Huth     cc->query_cpu_fast = s390_query_cpu_fast;
397fcf5ef2aSThomas Huth     cc->set_pc = s390_cpu_set_pc;
398e4fdf9dfSRichard Henderson     cc->get_pc = s390_cpu_get_pc;
399fcf5ef2aSThomas Huth     cc->gdb_read_register = s390_cpu_gdb_read_register;
400fcf5ef2aSThomas Huth     cc->gdb_write_register = s390_cpu_gdb_write_register;
40182851985SRichard Henderson #ifndef CONFIG_USER_ONLY
40272ffb631SCho, Yu-Chen     s390_cpu_class_init_sysemu(cc);
403b114588cSThomas Huth #endif
404fcf5ef2aSThomas Huth     cc->disas_set_info = s390_cpu_disas_set_info;
405fcf5ef2aSThomas Huth     cc->gdb_core_xml_file = "s390x-core64.xml";
406fcf5ef2aSThomas Huth     cc->gdb_arch_name = s390_gdb_arch_name;
407fcf5ef2aSThomas Huth 
408fcf5ef2aSThomas Huth     s390_cpu_model_class_register_props(oc);
40978271684SClaudio Fontana 
41078271684SClaudio Fontana #ifdef CONFIG_TCG
41178271684SClaudio Fontana     cc->tcg_ops = &s390_tcg_ops;
41278271684SClaudio Fontana #endif /* CONFIG_TCG */
413fcf5ef2aSThomas Huth }
414fcf5ef2aSThomas Huth 
415fcf5ef2aSThomas Huth static const TypeInfo s390_cpu_type_info = {
416fcf5ef2aSThomas Huth     .name = TYPE_S390_CPU,
417fcf5ef2aSThomas Huth     .parent = TYPE_CPU,
418fcf5ef2aSThomas Huth     .instance_size = sizeof(S390CPU),
419f62192a2SRichard Henderson     .instance_align = __alignof__(S390CPU),
420fcf5ef2aSThomas Huth     .instance_init = s390_cpu_initfn,
42172ffb631SCho, Yu-Chen 
42272ffb631SCho, Yu-Chen #ifndef CONFIG_USER_ONLY
423fcf5ef2aSThomas Huth     .instance_finalize = s390_cpu_finalize,
42472ffb631SCho, Yu-Chen #endif /* !CONFIG_USER_ONLY */
42572ffb631SCho, Yu-Chen 
426fcf5ef2aSThomas Huth     .abstract = true,
427fcf5ef2aSThomas Huth     .class_size = sizeof(S390CPUClass),
428fcf5ef2aSThomas Huth     .class_init = s390_cpu_class_init,
429fcf5ef2aSThomas Huth };
430fcf5ef2aSThomas Huth 
s390_cpu_register_types(void)431fcf5ef2aSThomas Huth static void s390_cpu_register_types(void)
432fcf5ef2aSThomas Huth {
433fcf5ef2aSThomas Huth     type_register_static(&s390_cpu_type_info);
434fcf5ef2aSThomas Huth }
435fcf5ef2aSThomas Huth 
436fcf5ef2aSThomas Huth type_init(s390_cpu_register_types)
437