]> Git Repo - qemu.git/blob - target/s390x/internal.h
7baf0e2404b414ace75bf7046438a8f61a763593
[qemu.git] / target / s390x / internal.h
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
16 typedef 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     uint64_t        mcic;                     /* 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[0x11b0 - 0xe04];    /* 0xe04 */
105
106     uint64_t        mcesad;                    /* 0x11B0 */
107
108     /* 64 bit extparam used for pfault, diag 250 etc  */
109     uint64_t        ext_params2;               /* 0x11B8 */
110
111     uint8_t         pad14[0x1200 - 0x11C0];    /* 0x11C0 */
112
113     /* System info area */
114
115     uint64_t        floating_pt_save_area[16]; /* 0x1200 */
116     uint64_t        gpregs_save_area[16];      /* 0x1280 */
117     uint32_t        st_status_fixed_logout[4]; /* 0x1300 */
118     uint8_t         pad15[0x1318 - 0x1310];    /* 0x1310 */
119     uint32_t        prefixreg_save_area;       /* 0x1318 */
120     uint32_t        fpt_creg_save_area;        /* 0x131c */
121     uint8_t         pad16[0x1324 - 0x1320];    /* 0x1320 */
122     uint32_t        tod_progreg_save_area;     /* 0x1324 */
123     uint64_t        cpu_timer_save_area;       /* 0x1328 */
124     uint64_t        clock_comp_save_area;      /* 0x1330 */
125     uint8_t         pad17[0x1340 - 0x1338];    /* 0x1338 */
126     uint32_t        access_regs_save_area[16]; /* 0x1340 */
127     uint64_t        cregs_save_area[16];       /* 0x1380 */
128
129     /* align to the top of the prefix area */
130
131     uint8_t         pad18[0x2000 - 0x1400];    /* 0x1400 */
132 } QEMU_PACKED LowCore;
133 #endif /* CONFIG_USER_ONLY */
134
135 #define MAX_ILEN 6
136
137 /* While the PoO talks about ILC (a number between 1-3) what is actually
138    stored in LowCore is shifted left one bit (an even between 2-6).  As
139    this is the actual length of the insn and therefore more useful, that
140    is what we want to pass around and manipulate.  To make sure that we
141    have applied this distinction universally, rename the "ILC" to "ILEN".  */
142 static inline int get_ilen(uint8_t opc)
143 {
144     switch (opc >> 6) {
145     case 0:
146         return 2;
147     case 1:
148     case 2:
149         return 4;
150     default:
151         return 6;
152     }
153 }
154
155 /* Compute the ATMID field that is stored in the per_perc_atmid lowcore
156    entry when a PER exception is triggered.  */
157 static inline uint8_t get_per_atmid(CPUS390XState *env)
158 {
159     return ((env->psw.mask & PSW_MASK_64) ?       (1 << 7) : 0) |
160                                                   (1 << 6)      |
161            ((env->psw.mask & PSW_MASK_32) ?       (1 << 5) : 0) |
162            ((env->psw.mask & PSW_MASK_DAT) ?      (1 << 4) : 0) |
163            ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
164            ((env->psw.mask & PSW_ASC_ACCREG) ?    (1 << 2) : 0);
165 }
166
167 static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
168 {
169     if (!(env->psw.mask & PSW_MASK_64)) {
170         if (!(env->psw.mask & PSW_MASK_32)) {
171             /* 24-Bit mode */
172             a &= 0x00ffffff;
173         } else {
174             /* 31-Bit mode */
175             a &= 0x7fffffff;
176         }
177     }
178     return a;
179 }
180
181 /* CC optimization */
182
183 /* Instead of computing the condition codes after each x86 instruction,
184  * QEMU just stores the result (called CC_DST), the type of operation
185  * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
186  * CC_VR). When the condition codes are needed, the condition codes can
187  * be calculated using this information. Condition codes are not generated
188  * if they are only needed for conditional branches.
189  */
190 enum cc_op {
191     CC_OP_CONST0 = 0,           /* CC is 0 */
192     CC_OP_CONST1,               /* CC is 1 */
193     CC_OP_CONST2,               /* CC is 2 */
194     CC_OP_CONST3,               /* CC is 3 */
195
196     CC_OP_DYNAMIC,              /* CC calculation defined by env->cc_op */
197     CC_OP_STATIC,               /* CC value is env->cc_op */
198
199     CC_OP_NZ,                   /* env->cc_dst != 0 */
200     CC_OP_LTGT_32,              /* signed less/greater than (32bit) */
201     CC_OP_LTGT_64,              /* signed less/greater than (64bit) */
202     CC_OP_LTUGTU_32,            /* unsigned less/greater than (32bit) */
203     CC_OP_LTUGTU_64,            /* unsigned less/greater than (64bit) */
204     CC_OP_LTGT0_32,             /* signed less/greater than 0 (32bit) */
205     CC_OP_LTGT0_64,             /* signed less/greater than 0 (64bit) */
206
207     CC_OP_ADD_64,               /* overflow on add (64bit) */
208     CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
209     CC_OP_ADDC_64,              /* overflow on unsigned add-carry (64bit) */
210     CC_OP_SUB_64,               /* overflow on subtraction (64bit) */
211     CC_OP_SUBU_64,              /* overflow on unsigned subtraction (64bit) */
212     CC_OP_SUBB_64,              /* overflow on unsigned sub-borrow (64bit) */
213     CC_OP_ABS_64,               /* sign eval on abs (64bit) */
214     CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
215
216     CC_OP_ADD_32,               /* overflow on add (32bit) */
217     CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
218     CC_OP_ADDC_32,              /* overflow on unsigned add-carry (32bit) */
219     CC_OP_SUB_32,               /* overflow on subtraction (32bit) */
220     CC_OP_SUBU_32,              /* overflow on unsigned subtraction (32bit) */
221     CC_OP_SUBB_32,              /* overflow on unsigned sub-borrow (32bit) */
222     CC_OP_ABS_32,               /* sign eval on abs (64bit) */
223     CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
224
225     CC_OP_COMP_32,              /* complement */
226     CC_OP_COMP_64,              /* complement */
227
228     CC_OP_TM_32,                /* test under mask (32bit) */
229     CC_OP_TM_64,                /* test under mask (64bit) */
230
231     CC_OP_NZ_F32,               /* FP dst != 0 (32bit) */
232     CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
233     CC_OP_NZ_F128,              /* FP dst != 0 (128bit) */
234
235     CC_OP_ICM,                  /* insert characters under mask */
236     CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
237     CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
238     CC_OP_FLOGR,                /* find leftmost one */
239     CC_OP_LCBB,                 /* load count to block boundary */
240     CC_OP_MAX
241 };
242
243 static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
244                                        uint8_t *ar)
245 {
246     hwaddr addr = 0;
247     uint8_t reg;
248
249     reg = ipb >> 28;
250     if (reg > 0) {
251         addr = env->regs[reg];
252     }
253     addr += (ipb >> 16) & 0xfff;
254     if (ar) {
255         *ar = reg;
256     }
257
258     return addr;
259 }
260
261 /* Base/displacement are at the same locations. */
262 #define decode_basedisp_rs decode_basedisp_s
263
264 /* arch_dump.c */
265 int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
266                               int cpuid, void *opaque);
267
268
269 /* cc_helper.c */
270 const char *cc_name(enum cc_op cc_op);
271 void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
272 uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
273                  uint64_t vr);
274
275
276 /* cpu.c */
277 #ifndef CONFIG_USER_ONLY
278 unsigned int s390_cpu_halt(S390CPU *cpu);
279 void s390_cpu_unhalt(S390CPU *cpu);
280 #else
281 static inline unsigned int s390_cpu_halt(S390CPU *cpu)
282 {
283     return 0;
284 }
285
286 static inline void s390_cpu_unhalt(S390CPU *cpu)
287 {
288 }
289 #endif /* CONFIG_USER_ONLY */
290
291
292 /* cpu_models.c */
293 void s390_cpu_model_register_props(Object *obj);
294 void s390_cpu_model_class_register_props(ObjectClass *oc);
295 void s390_realize_cpu_model(CPUState *cs, Error **errp);
296 ObjectClass *s390_cpu_class_by_name(const char *name);
297
298
299 /* excp_helper.c */
300 void s390x_cpu_debug_excp_handler(CPUState *cs);
301 void s390_cpu_do_interrupt(CPUState *cpu);
302 bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
303 int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
304                               int mmu_idx);
305 void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
306                                    MMUAccessType access_type,
307                                    int mmu_idx, uintptr_t retaddr);
308
309
310 /* fpu_helper.c */
311 uint32_t set_cc_nz_f32(float32 v);
312 uint32_t set_cc_nz_f64(float64 v);
313 uint32_t set_cc_nz_f128(float128 v);
314 #define S390_IEEE_MASK_INVALID   0x80
315 #define S390_IEEE_MASK_DIVBYZERO 0x40
316 #define S390_IEEE_MASK_OVERFLOW  0x20
317 #define S390_IEEE_MASK_UNDERFLOW 0x10
318 #define S390_IEEE_MASK_INEXACT   0x08
319 #define S390_IEEE_MASK_QUANTUM   0x04
320 uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
321 int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
322 void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
323
324
325 /* gdbstub.c */
326 int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
327 int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
328 void s390_cpu_gdb_init(CPUState *cs);
329
330
331 /* helper.c */
332 void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
333                          int flags);
334 hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
335 hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
336 uint64_t get_psw_mask(CPUS390XState *env);
337 void s390_cpu_recompute_watchpoints(CPUState *cs);
338 void s390x_tod_timer(void *opaque);
339 void s390x_cpu_timer(void *opaque);
340 void do_restart_interrupt(CPUS390XState *env);
341 void s390_handle_wait(S390CPU *cpu);
342 #define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
343 int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch);
344 int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len);
345 #ifndef CONFIG_USER_ONLY
346 LowCore *cpu_map_lowcore(CPUS390XState *env);
347 void cpu_unmap_lowcore(LowCore *lowcore);
348 #endif /* CONFIG_USER_ONLY */
349
350
351 /* interrupt.c */
352 void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
353 void cpu_inject_clock_comparator(S390CPU *cpu);
354 void cpu_inject_cpu_timer(S390CPU *cpu);
355 void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
356 int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
357 bool s390_cpu_has_io_int(S390CPU *cpu);
358 bool s390_cpu_has_ext_int(S390CPU *cpu);
359 bool s390_cpu_has_mcck_int(S390CPU *cpu);
360 bool s390_cpu_has_int(S390CPU *cpu);
361 bool s390_cpu_has_restart_int(S390CPU *cpu);
362 bool s390_cpu_has_stop_int(S390CPU *cpu);
363 void cpu_inject_restart(S390CPU *cpu);
364 void cpu_inject_stop(S390CPU *cpu);
365
366
367 /* ioinst.c */
368 void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
369 void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
370 void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
371 void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
372                         uintptr_t ra);
373 void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
374                         uintptr_t ra);
375 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
376 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
377                          uintptr_t ra);
378 int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra);
379 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
380 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
381                         uint32_t ipb, uintptr_t ra);
382 void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
383 void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
384 void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
385
386
387 /* mem_helper.c */
388 target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
389
390
391 /* mmu_helper.c */
392 int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
393                   target_ulong *raddr, int *flags, bool exc);
394 int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
395                        target_ulong *addr, int *flags);
396
397
398 /* misc_helper.c */
399 int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
400 void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
401                      uintptr_t ra);
402
403
404 /* translate.c */
405 void s390x_translate_init(void);
406
407
408 /* sigp.c */
409 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
410 void do_stop_interrupt(CPUS390XState *env);
411
412 #endif /* S390X_INTERNAL_H */
This page took 0.038567 seconds and 2 git commands to generate.