]> git.proxmox.com Git - mirror_qemu.git/blame - target/s390x/internal.h
s390x/ioinst: pass the retaddr to all IO instructions
[mirror_qemu.git] / target / s390x / internal.h
CommitLineData
4e58b838
DH
1/*
2 * s390x internal definitions and helpers
3 *
4 * Copyright (c) 2009 Ulrich Hecht
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9
10#ifndef S390X_INTERNAL_H
11#define S390X_INTERNAL_H
12
13#include "cpu.h"
14
15#ifndef CONFIG_USER_ONLY
16typedef struct LowCore {
17 /* prefix area: defined by architecture */
18 uint32_t ccw1[2]; /* 0x000 */
19 uint32_t ccw2[4]; /* 0x008 */
20 uint8_t pad1[0x80 - 0x18]; /* 0x018 */
21 uint32_t ext_params; /* 0x080 */
22 uint16_t cpu_addr; /* 0x084 */
23 uint16_t ext_int_code; /* 0x086 */
24 uint16_t svc_ilen; /* 0x088 */
25 uint16_t svc_code; /* 0x08a */
26 uint16_t pgm_ilen; /* 0x08c */
27 uint16_t pgm_code; /* 0x08e */
28 uint32_t data_exc_code; /* 0x090 */
29 uint16_t mon_class_num; /* 0x094 */
30 uint16_t per_perc_atmid; /* 0x096 */
31 uint64_t per_address; /* 0x098 */
32 uint8_t exc_access_id; /* 0x0a0 */
33 uint8_t per_access_id; /* 0x0a1 */
34 uint8_t op_access_id; /* 0x0a2 */
35 uint8_t ar_access_id; /* 0x0a3 */
36 uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
37 uint64_t trans_exc_code; /* 0x0a8 */
38 uint64_t monitor_code; /* 0x0b0 */
39 uint16_t subchannel_id; /* 0x0b8 */
40 uint16_t subchannel_nr; /* 0x0ba */
41 uint32_t io_int_parm; /* 0x0bc */
42 uint32_t io_int_word; /* 0x0c0 */
43 uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
44 uint32_t stfl_fac_list; /* 0x0c8 */
45 uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
46 uint32_t mcck_interruption_code[2]; /* 0x0e8 */
47 uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
48 uint32_t external_damage_code; /* 0x0f4 */
49 uint64_t failing_storage_address; /* 0x0f8 */
50 uint8_t pad6[0x110 - 0x100]; /* 0x100 */
51 uint64_t per_breaking_event_addr; /* 0x110 */
52 uint8_t pad7[0x120 - 0x118]; /* 0x118 */
53 PSW restart_old_psw; /* 0x120 */
54 PSW external_old_psw; /* 0x130 */
55 PSW svc_old_psw; /* 0x140 */
56 PSW program_old_psw; /* 0x150 */
57 PSW mcck_old_psw; /* 0x160 */
58 PSW io_old_psw; /* 0x170 */
59 uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
60 PSW restart_new_psw; /* 0x1a0 */
61 PSW external_new_psw; /* 0x1b0 */
62 PSW svc_new_psw; /* 0x1c0 */
63 PSW program_new_psw; /* 0x1d0 */
64 PSW mcck_new_psw; /* 0x1e0 */
65 PSW io_new_psw; /* 0x1f0 */
66 PSW return_psw; /* 0x200 */
67 uint8_t irb[64]; /* 0x210 */
68 uint64_t sync_enter_timer; /* 0x250 */
69 uint64_t async_enter_timer; /* 0x258 */
70 uint64_t exit_timer; /* 0x260 */
71 uint64_t last_update_timer; /* 0x268 */
72 uint64_t user_timer; /* 0x270 */
73 uint64_t system_timer; /* 0x278 */
74 uint64_t last_update_clock; /* 0x280 */
75 uint64_t steal_clock; /* 0x288 */
76 PSW return_mcck_psw; /* 0x290 */
77 uint8_t pad9[0xc00 - 0x2a0]; /* 0x2a0 */
78 /* System info area */
79 uint64_t save_area[16]; /* 0xc00 */
80 uint8_t pad10[0xd40 - 0xc80]; /* 0xc80 */
81 uint64_t kernel_stack; /* 0xd40 */
82 uint64_t thread_info; /* 0xd48 */
83 uint64_t async_stack; /* 0xd50 */
84 uint64_t kernel_asce; /* 0xd58 */
85 uint64_t user_asce; /* 0xd60 */
86 uint64_t panic_stack; /* 0xd68 */
87 uint64_t user_exec_asce; /* 0xd70 */
88 uint8_t pad11[0xdc0 - 0xd78]; /* 0xd78 */
89
90 /* SMP info area: defined by DJB */
91 uint64_t clock_comparator; /* 0xdc0 */
92 uint64_t ext_call_fast; /* 0xdc8 */
93 uint64_t percpu_offset; /* 0xdd0 */
94 uint64_t current_task; /* 0xdd8 */
95 uint32_t softirq_pending; /* 0xde0 */
96 uint32_t pad_0x0de4; /* 0xde4 */
97 uint64_t int_clock; /* 0xde8 */
98 uint8_t pad12[0xe00 - 0xdf0]; /* 0xdf0 */
99
100 /* 0xe00 is used as indicator for dump tools */
101 /* whether the kernel died with panic() or not */
102 uint32_t panic_magic; /* 0xe00 */
103
104 uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
105
106 /* 64 bit extparam used for pfault, diag 250 etc */
107 uint64_t ext_params2; /* 0x11B8 */
108
109 uint8_t pad14[0x1200 - 0x11C0]; /* 0x11C0 */
110
111 /* System info area */
112
113 uint64_t floating_pt_save_area[16]; /* 0x1200 */
114 uint64_t gpregs_save_area[16]; /* 0x1280 */
115 uint32_t st_status_fixed_logout[4]; /* 0x1300 */
116 uint8_t pad15[0x1318 - 0x1310]; /* 0x1310 */
117 uint32_t prefixreg_save_area; /* 0x1318 */
118 uint32_t fpt_creg_save_area; /* 0x131c */
119 uint8_t pad16[0x1324 - 0x1320]; /* 0x1320 */
120 uint32_t tod_progreg_save_area; /* 0x1324 */
121 uint32_t cpu_timer_save_area[2]; /* 0x1328 */
122 uint32_t clock_comp_save_area[2]; /* 0x1330 */
123 uint8_t pad17[0x1340 - 0x1338]; /* 0x1338 */
124 uint32_t access_regs_save_area[16]; /* 0x1340 */
125 uint64_t cregs_save_area[16]; /* 0x1380 */
126
127 /* align to the top of the prefix area */
128
129 uint8_t pad18[0x2000 - 0x1400]; /* 0x1400 */
130} QEMU_PACKED LowCore;
131#endif /* CONFIG_USER_ONLY */
132
133#define MAX_ILEN 6
134
135/* While the PoO talks about ILC (a number between 1-3) what is actually
136 stored in LowCore is shifted left one bit (an even between 2-6). As
137 this is the actual length of the insn and therefore more useful, that
138 is what we want to pass around and manipulate. To make sure that we
139 have applied this distinction universally, rename the "ILC" to "ILEN". */
140static inline int get_ilen(uint8_t opc)
141{
142 switch (opc >> 6) {
143 case 0:
144 return 2;
145 case 1:
146 case 2:
147 return 4;
148 default:
149 return 6;
150 }
151}
152
153/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
154 entry when a PER exception is triggered. */
155static inline uint8_t get_per_atmid(CPUS390XState *env)
156{
157 return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
158 (1 << 6) |
159 ((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
160 ((env->psw.mask & PSW_MASK_DAT) ? (1 << 4) : 0) |
161 ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
162 ((env->psw.mask & PSW_ASC_ACCREG) ? (1 << 2) : 0);
163}
164
7634d658
DH
165static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
166{
167 if (!(env->psw.mask & PSW_MASK_64)) {
168 if (!(env->psw.mask & PSW_MASK_32)) {
169 /* 24-Bit mode */
170 a &= 0x00ffffff;
171 } else {
172 /* 31-Bit mode */
173 a &= 0x7fffffff;
174 }
175 }
176 return a;
177}
178
4e58b838
DH
179/* CC optimization */
180
181/* Instead of computing the condition codes after each x86 instruction,
182 * QEMU just stores the result (called CC_DST), the type of operation
183 * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
184 * CC_VR). When the condition codes are needed, the condition codes can
185 * be calculated using this information. Condition codes are not generated
186 * if they are only needed for conditional branches.
187 */
188enum cc_op {
189 CC_OP_CONST0 = 0, /* CC is 0 */
190 CC_OP_CONST1, /* CC is 1 */
191 CC_OP_CONST2, /* CC is 2 */
192 CC_OP_CONST3, /* CC is 3 */
193
194 CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
195 CC_OP_STATIC, /* CC value is env->cc_op */
196
197 CC_OP_NZ, /* env->cc_dst != 0 */
198 CC_OP_LTGT_32, /* signed less/greater than (32bit) */
199 CC_OP_LTGT_64, /* signed less/greater than (64bit) */
200 CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
201 CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
202 CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
203 CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
204
205 CC_OP_ADD_64, /* overflow on add (64bit) */
206 CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
207 CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
208 CC_OP_SUB_64, /* overflow on subtraction (64bit) */
209 CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
210 CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
211 CC_OP_ABS_64, /* sign eval on abs (64bit) */
212 CC_OP_NABS_64, /* sign eval on nabs (64bit) */
213
214 CC_OP_ADD_32, /* overflow on add (32bit) */
215 CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
216 CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
217 CC_OP_SUB_32, /* overflow on subtraction (32bit) */
218 CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
219 CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
220 CC_OP_ABS_32, /* sign eval on abs (64bit) */
221 CC_OP_NABS_32, /* sign eval on nabs (64bit) */
222
223 CC_OP_COMP_32, /* complement */
224 CC_OP_COMP_64, /* complement */
225
226 CC_OP_TM_32, /* test under mask (32bit) */
227 CC_OP_TM_64, /* test under mask (64bit) */
228
229 CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
230 CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
231 CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
232
233 CC_OP_ICM, /* insert characters under mask */
234 CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
235 CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
236 CC_OP_FLOGR, /* find leftmost one */
237 CC_OP_MAX
238};
239
240/* The value of the TOD clock for 1.1.1970. */
241#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
242
243/* Converts ns to s390's clock format */
244static inline uint64_t time2tod(uint64_t ns)
245{
246 return (ns << 9) / 125;
247}
248
249/* Converts s390's clock format to ns */
250static inline uint64_t tod2time(uint64_t t)
251{
252 return (t * 125) >> 9;
253}
254
255static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
256 uint8_t *ar)
257{
258 hwaddr addr = 0;
259 uint8_t reg;
260
261 reg = ipb >> 28;
262 if (reg > 0) {
263 addr = env->regs[reg];
264 }
265 addr += (ipb >> 16) & 0xfff;
266 if (ar) {
267 *ar = reg;
268 }
269
270 return addr;
271}
272
273/* Base/displacement are at the same locations. */
274#define decode_basedisp_rs decode_basedisp_s
275
276static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
277{
278 cpu_reset(cs);
279}
280
281static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
282{
283 return cpu->env.cpu_state;
284}
285
286
287/* arch_dump.c */
288int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
289 int cpuid, void *opaque);
290
291
292/* cc_helper.c */
293const char *cc_name(enum cc_op cc_op);
294void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
295uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
296 uint64_t vr);
297
298
299/* cpu.c */
300#ifndef CONFIG_USER_ONLY
301unsigned int s390_cpu_halt(S390CPU *cpu);
302void s390_cpu_unhalt(S390CPU *cpu);
303#else
304static inline unsigned int s390_cpu_halt(S390CPU *cpu)
305{
306 return 0;
307}
308
309static inline void s390_cpu_unhalt(S390CPU *cpu)
310{
311}
312#endif /* CONFIG_USER_ONLY */
313
314
315/* cpu_models.c */
316void s390_cpu_model_register_props(Object *obj);
317void s390_cpu_model_class_register_props(ObjectClass *oc);
318void s390_realize_cpu_model(CPUState *cs, Error **errp);
319ObjectClass *s390_cpu_class_by_name(const char *name);
320
321
322/* excp_helper.c */
323void s390x_cpu_debug_excp_handler(CPUState *cs);
324void s390_cpu_do_interrupt(CPUState *cpu);
325bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
326int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
327 int mmu_idx);
328void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
329 MMUAccessType access_type,
330 int mmu_idx, uintptr_t retaddr);
331
332
333/* fpu_helper.c */
334uint32_t set_cc_nz_f32(float32 v);
335uint32_t set_cc_nz_f64(float64 v);
336uint32_t set_cc_nz_f128(float128 v);
337
338
339/* gdbstub.c */
340int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
341int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
342void s390_cpu_gdb_init(CPUState *cs);
343
344
345/* helper.c */
346void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
347 int flags);
348hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
349hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
350uint64_t get_psw_mask(CPUS390XState *env);
351void s390_cpu_recompute_watchpoints(CPUState *cs);
352void s390x_tod_timer(void *opaque);
353void s390x_cpu_timer(void *opaque);
4e58b838 354void do_restart_interrupt(CPUS390XState *env);
83f7f329 355void s390_handle_wait(S390CPU *cpu);
cf729baa
DH
356#define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
357int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch);
f875cb0c 358int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len);
4e58b838
DH
359#ifndef CONFIG_USER_ONLY
360LowCore *cpu_map_lowcore(CPUS390XState *env);
361void cpu_unmap_lowcore(LowCore *lowcore);
362#endif /* CONFIG_USER_ONLY */
363
364
365/* interrupt.c */
366void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
6482b0ff
DH
367void cpu_inject_clock_comparator(S390CPU *cpu);
368void cpu_inject_cpu_timer(S390CPU *cpu);
14ca122e
DH
369void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
370int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
8417f904
DH
371bool s390_cpu_has_io_int(S390CPU *cpu);
372bool s390_cpu_has_ext_int(S390CPU *cpu);
373bool s390_cpu_has_mcck_int(S390CPU *cpu);
374bool s390_cpu_has_int(S390CPU *cpu);
b1ab5f60
DH
375bool s390_cpu_has_restart_int(S390CPU *cpu);
376bool s390_cpu_has_stop_int(S390CPU *cpu);
eabcea18
DH
377void cpu_inject_restart(S390CPU *cpu);
378void cpu_inject_stop(S390CPU *cpu);
4e58b838
DH
379
380
381/* ioinst.c */
1b98fb99
DH
382void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
383void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
384void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
385void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
386 uintptr_t ra);
387void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
388 uintptr_t ra);
389void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
390void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
391 uintptr_t ra);
392int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra);
393void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
4e58b838 394void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
1b98fb99
DH
395 uint32_t ipb, uintptr_t ra);
396void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
397void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
398void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
4e58b838
DH
399
400
401/* mem_helper.c */
402target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
403
404
405/* mmu_helper.c */
406int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
407 target_ulong *raddr, int *flags, bool exc);
fb66944d
DH
408int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
409 target_ulong *addr, int *flags);
4e58b838
DH
410
411
412/* misc_helper.c */
4e58b838
DH
413int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
414void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
415
416
417/* translate.c */
418void s390x_translate_init(void);
419
74b4c74d
DH
420
421/* sigp.c */
422int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
3047f8b5 423void do_stop_interrupt(CPUS390XState *env);
74b4c74d 424
4e58b838 425#endif /* S390X_INTERNAL_H */