master
h 409 lines 16 KB
Raw
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 "exec/hwaddr.h"
14 #include "exec/vaddr.h"
15 #include "cpu.h"
16 #include "fpu/softfloat.h"
17
18 #ifndef CONFIG_USER_ONLY
19 typedef struct LowCore {
20 /* prefix area: defined by architecture */
21 uint32_t ccw1[2]; /* 0x000 */
22 uint32_t ccw2[4]; /* 0x008 */
23 uint8_t pad1[0x80 - 0x18]; /* 0x018 */
24 uint32_t ext_params; /* 0x080 */
25 uint16_t cpu_addr; /* 0x084 */
26 uint16_t ext_int_code; /* 0x086 */
27 uint16_t svc_ilen; /* 0x088 */
28 uint16_t svc_code; /* 0x08a */
29 uint16_t pgm_ilen; /* 0x08c */
30 uint16_t pgm_code; /* 0x08e */
31 uint32_t data_exc_code; /* 0x090 */
32 uint16_t mon_class_num; /* 0x094 */
33 uint16_t per_perc_atmid; /* 0x096 */
34 uint64_t per_address; /* 0x098 */
35 uint8_t exc_access_id; /* 0x0a0 */
36 uint8_t per_access_id; /* 0x0a1 */
37 uint8_t op_access_id; /* 0x0a2 */
38 uint8_t ar_access_id; /* 0x0a3 */
39 uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
40 uint64_t trans_exc_code; /* 0x0a8 */
41 uint64_t monitor_code; /* 0x0b0 */
42 uint16_t subchannel_id; /* 0x0b8 */
43 uint16_t subchannel_nr; /* 0x0ba */
44 uint32_t io_int_parm; /* 0x0bc */
45 uint32_t io_int_word; /* 0x0c0 */
46 uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
47 uint32_t stfl_fac_list; /* 0x0c8 */
48 uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
49 uint64_t mcic; /* 0x0e8 */
50 uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
51 uint32_t external_damage_code; /* 0x0f4 */
52 uint64_t failing_storage_address; /* 0x0f8 */
53 uint8_t pad6[0x110 - 0x100]; /* 0x100 */
54 uint64_t per_breaking_event_addr; /* 0x110 */
55 uint8_t pad7[0x120 - 0x118]; /* 0x118 */
56 PSW restart_old_psw; /* 0x120 */
57 PSW external_old_psw; /* 0x130 */
58 PSW svc_old_psw; /* 0x140 */
59 PSW program_old_psw; /* 0x150 */
60 PSW mcck_old_psw; /* 0x160 */
61 PSW io_old_psw; /* 0x170 */
62 uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
63 PSW restart_new_psw; /* 0x1a0 */
64 PSW external_new_psw; /* 0x1b0 */
65 PSW svc_new_psw; /* 0x1c0 */
66 PSW program_new_psw; /* 0x1d0 */
67 PSW mcck_new_psw; /* 0x1e0 */
68 PSW io_new_psw; /* 0x1f0 */
69 uint8_t pad13[0x11b0 - 0x200]; /* 0x200 */
70
71 uint64_t mcesad; /* 0x11B0 */
72
73 /* 64 bit extparam used for pfault, diag 250 etc */
74 uint64_t ext_params2; /* 0x11B8 */
75
76 uint8_t pad14[0x1200 - 0x11C0]; /* 0x11C0 */
77
78 /* System info area */
79
80 uint64_t floating_pt_save_area[16]; /* 0x1200 */
81 uint64_t gpregs_save_area[16]; /* 0x1280 */
82 uint32_t st_status_fixed_logout[4]; /* 0x1300 */
83 uint8_t pad15[0x1318 - 0x1310]; /* 0x1310 */
84 uint32_t prefixreg_save_area; /* 0x1318 */
85 uint32_t fpt_creg_save_area; /* 0x131c */
86 uint8_t pad16[0x1324 - 0x1320]; /* 0x1320 */
87 uint32_t tod_progreg_save_area; /* 0x1324 */
88 uint64_t cpu_timer_save_area; /* 0x1328 */
89 uint64_t clock_comp_save_area; /* 0x1330 */
90 uint8_t pad17[0x1340 - 0x1338]; /* 0x1338 */
91 uint32_t access_regs_save_area[16]; /* 0x1340 */
92 uint64_t cregs_save_area[16]; /* 0x1380 */
93
94 /* align to the top of the prefix area */
95
96 uint8_t pad18[0x2000 - 0x1400]; /* 0x1400 */
97 } QEMU_PACKED LowCore;
98 QEMU_BUILD_BUG_ON(sizeof(LowCore) != 8192);
99 #endif /* CONFIG_USER_ONLY */
100
101 #define MAX_ILEN 6
102
103 /* While the PoO talks about ILC (a number between 1-3) what is actually
104 stored in LowCore is shifted left one bit (an even between 2-6). As
105 this is the actual length of the insn and therefore more useful, that
106 is what we want to pass around and manipulate. To make sure that we
107 have applied this distinction universally, rename the "ILC" to "ILEN". */
108 static inline int get_ilen(uint8_t opc)
109 {
110 switch (opc >> 6) {
111 case 0:
112 return 2;
113 case 1:
114 case 2:
115 return 4;
116 default:
117 return 6;
118 }
119 }
120
121 /* Compute the ATMID field that is stored in the per_perc_atmid lowcore
122 entry when a PER exception is triggered. */
123 static inline uint8_t get_per_atmid(CPUS390XState *env)
124 {
125 return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
126 (1 << 6) |
127 ((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
128 ((env->psw.mask & PSW_MASK_DAT) ? (1 << 4) : 0) |
129 ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
130 ((env->psw.mask & PSW_ASC_ACCREG) ? (1 << 2) : 0);
131 }
132
133 static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
134 {
135 if (!(env->psw.mask & PSW_MASK_64)) {
136 if (!(env->psw.mask & PSW_MASK_32)) {
137 /* 24-Bit mode */
138 a &= 0x00ffffff;
139 } else {
140 /* 31-Bit mode */
141 a &= 0x7fffffff;
142 }
143 }
144 return a;
145 }
146
147 /* CC optimization */
148
149 /* Instead of computing the condition codes after each x86 instruction,
150 * QEMU just stores the result (called CC_DST), the type of operation
151 * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
152 * CC_VR). When the condition codes are needed, the condition codes can
153 * be calculated using this information. Condition codes are not generated
154 * if they are only needed for conditional branches.
155 */
156 enum cc_op {
157 CC_OP_CONST0 = 0, /* CC is 0 */
158 CC_OP_CONST1, /* CC is 1 */
159 CC_OP_CONST2, /* CC is 2 */
160 CC_OP_CONST3, /* CC is 3 */
161
162 CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
163 CC_OP_STATIC, /* CC value is env->cc_op */
164
165 CC_OP_NZ, /* env->cc_dst != 0 */
166 CC_OP_ADDU, /* dst != 0, src = carry out (0,1) */
167 CC_OP_SUBU, /* dst != 0, src = borrow out (0,-1) */
168
169 CC_OP_LTGT_32, /* signed less/greater than (32bit) */
170 CC_OP_LTGT_64, /* signed less/greater than (64bit) */
171 CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
172 CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
173 CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
174 CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
175
176 CC_OP_ADD_64, /* overflow on add (64bit) */
177 CC_OP_SUB_64, /* overflow on subtraction (64bit) */
178 CC_OP_ABS_64, /* sign eval on abs (64bit) */
179 CC_OP_NABS_64, /* sign eval on nabs (64bit) */
180 CC_OP_MULS_64, /* overflow on signed multiply (64bit) */
181
182 CC_OP_ADD_32, /* overflow on add (32bit) */
183 CC_OP_SUB_32, /* overflow on subtraction (32bit) */
184 CC_OP_ABS_32, /* sign eval on abs (64bit) */
185 CC_OP_NABS_32, /* sign eval on nabs (64bit) */
186 CC_OP_MULS_32, /* overflow on signed multiply (32bit) */
187
188 CC_OP_COMP_32, /* complement */
189 CC_OP_COMP_64, /* complement */
190
191 CC_OP_TM_32, /* test under mask (32bit) */
192 CC_OP_TM_64, /* test under mask (64bit) */
193
194 CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
195 CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
196 CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
197
198 CC_OP_ICM, /* insert characters under mask */
199 CC_OP_SLA, /* Calculate shift left signed */
200 CC_OP_FLOGR, /* find leftmost one */
201 CC_OP_LCBB, /* load count to block boundary */
202 CC_OP_VC, /* vector compare result */
203 CC_OP_MAX
204 };
205
206 #ifndef CONFIG_USER_ONLY
207
208 static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
209 uint8_t *ar)
210 {
211 hwaddr addr = 0;
212 uint8_t reg;
213
214 reg = ipb >> 28;
215 if (reg > 0) {
216 addr = env->regs[reg];
217 }
218 addr += (ipb >> 16) & 0xfff;
219 if (ar) {
220 *ar = reg;
221 }
222
223 return addr;
224 }
225
226 /* Base/displacement are at the same locations. */
227 #define decode_basedisp_rs decode_basedisp_s
228
229 #endif /* CONFIG_USER_ONLY */
230
231 /* arch_dump.c */
232 int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
233 int cpuid, DumpState *s);
234
235
236 /* cc_helper.c */
237 const char *cc_name(enum cc_op cc_op);
238 uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
239 uint64_t vr);
240
241 /* cpu.c */
242 #ifndef CONFIG_USER_ONLY
243 unsigned int s390_count_running_cpus(void);
244 void s390_cpu_halt(S390CPU *cpu);
245 void s390_cpu_unhalt(S390CPU *cpu);
246 void s390_cpu_system_init(Object *obj);
247 bool s390_cpu_system_realize(DeviceState *dev, Error **errp);
248 void s390_cpu_finalize(Object *obj);
249 void s390_cpu_system_class_init(CPUClass *cc);
250 void s390_cpu_machine_reset_cb(void *opaque);
251 bool s390_cpu_has_work(CPUState *cs);
252 #endif /* CONFIG_USER_ONLY */
253
254
255 /* cpu_models.c */
256 void s390_cpu_model_class_register_props(ObjectClass *oc);
257 void s390_realize_cpu_model(CPUState *cs, Error **errp);
258 S390CPUModel *get_max_cpu_model(Error **errp);
259 void apply_cpu_model(const S390CPUModel *model, Error **errp);
260 ObjectClass *s390_cpu_class_by_name(const char *name);
261
262
263 /* excp_helper.c */
264 void s390_cpu_do_interrupt(CPUState *cpu);
265 bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
266
267 #ifdef CONFIG_USER_ONLY
268 void s390_cpu_record_sigsegv(CPUState *cs, vaddr address,
269 MMUAccessType access_type,
270 bool maperr, uintptr_t retaddr);
271 void s390_cpu_record_sigbus(CPUState *cs, vaddr address,
272 MMUAccessType access_type, uintptr_t retaddr);
273 #else
274 bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
275 MMUAccessType access_type, int mmu_idx,
276 bool probe, uintptr_t retaddr);
277 G_NORETURN void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
278 MMUAccessType access_type, int mmu_idx,
279 uintptr_t retaddr);
280 #endif
281
282
283 /* fpu_helper.c */
284 uint32_t set_cc_nz_f32(float32 v);
285 uint32_t set_cc_nz_f64(float64 v);
286 uint32_t set_cc_nz_f128(float128 v);
287 #define S390_IEEE_MASK_INVALID 0x80
288 #define S390_IEEE_MASK_DIVBYZERO 0x40
289 #define S390_IEEE_MASK_OVERFLOW 0x20
290 #define S390_IEEE_MASK_UNDERFLOW 0x10
291 #define S390_IEEE_MASK_INEXACT 0x08
292 #define S390_IEEE_MASK_QUANTUM 0x04
293 uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
294 int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
295 void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
296 int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare);
297
298 #define DCMASK_ZERO 0x0c00
299 #define DCMASK_NORMAL 0x0300
300 #define DCMASK_SUBNORMAL 0x00c0
301 #define DCMASK_INFINITY 0x0030
302 #define DCMASK_QUIET_NAN 0x000c
303 #define DCMASK_SIGNALING_NAN 0x0003
304 #define DCMASK_NAN 0x000f
305 #define DCMASK_NEGATIVE 0x0555
306 uint16_t float32_dcmask(CPUS390XState *env, float32 f1);
307 uint16_t float64_dcmask(CPUS390XState *env, float64 f1);
308 uint16_t float128_dcmask(CPUS390XState *env, float128 f1);
309
310
311 /* gdbstub.c */
312 int s390_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
313 int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
314 void s390_cpu_gdb_init(CPUState *cs);
315
316
317 /* helper.c */
318 void s390_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
319 void do_restart_interrupt(CPUS390XState *env);
320 #ifndef CONFIG_USER_ONLY
321 void s390x_tod_timer(void *opaque);
322 void s390x_cpu_timer(void *opaque);
323 void s390_handle_wait(S390CPU *cpu);
324 hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
325 LowCore *cpu_map_lowcore(CPUS390XState *env);
326 void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore);
327 #endif /* CONFIG_USER_ONLY */
328
329
330 /* interrupt.c */
331 void trigger_pgm_exception(CPUS390XState *env, uint32_t code);
332 #ifndef CONFIG_USER_ONLY
333 void cpu_inject_clock_comparator(S390CPU *cpu);
334 void cpu_inject_cpu_timer(S390CPU *cpu);
335 void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
336 int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
337 bool s390_cpu_has_io_int(S390CPU *cpu);
338 bool s390_cpu_has_ext_int(S390CPU *cpu);
339 bool s390_cpu_has_mcck_int(S390CPU *cpu);
340 bool s390_cpu_has_int(S390CPU *cpu);
341 bool s390_cpu_has_restart_int(S390CPU *cpu);
342 bool s390_cpu_has_stop_int(S390CPU *cpu);
343 void cpu_inject_restart(S390CPU *cpu);
344 void cpu_inject_stop(S390CPU *cpu);
345 #endif /* CONFIG_USER_ONLY */
346
347
348 /* ioinst.c */
349 #ifndef CONFIG_USER_ONLY
350 void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
351 void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
352 void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
353 void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
354 uintptr_t ra);
355 void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
356 uintptr_t ra);
357 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
358 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
359 uintptr_t ra);
360 int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra);
361 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
362 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
363 uint32_t ipb, uintptr_t ra);
364 void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
365 void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
366 void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
367 #endif /* CONFIG_USER_ONLY */
368
369
370 /* mem_helper.c */
371 void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
372 uintptr_t ra);
373
374
375 /* mmu_helper.c */
376 hwaddr mmu_real2abs(CPUS390XState *env, hwaddr raddr);
377 bool mmu_absolute_addr_valid(hwaddr addr, bool is_write);
378 /* Special access mode only valid for mmu_translate() */
379 #define MMU_S390_LRA -1
380 int mmu_translate(CPUS390XState *env, vaddr vaddr, int rw, uint64_t asc,
381 hwaddr *raddr, int *flags, uint64_t *tec);
382 int mmu_translate_real(CPUS390XState *env, hwaddr raddr, int rw,
383 hwaddr *addr, int *flags, uint64_t *tec);
384
385
386 /* misc_helper.c */
387 int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
388 /* Return whether a CPU reset is pending */
389 bool handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
390 uintptr_t ra);
391 void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3,
392 uintptr_t ra);
393 void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3,
394 uintptr_t ra);
395
396
397 /* translate.c */
398 void s390x_translate_init(void);
399 void s390x_translate_code(CPUState *cs, TranslationBlock *tb,
400 int *max_insns, vaddr pc, void *host_pc);
401 void s390x_restore_state_to_opc(CPUState *cs,
402 const TranslationBlock *tb,
403 const uint64_t *data);
404
405 /* sigp.c */
406 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
407 void do_stop_interrupt(CPUS390XState *env);
408
409 #endif /* S390X_INTERNAL_H */