root / target-s390x / cpu.h @ cc3ac9c4
History | View | Annotate | Download (37.7 kB)
1 |
/*
|
---|---|
2 |
* S/390 virtual CPU header
|
3 |
*
|
4 |
* Copyright (c) 2009 Ulrich Hecht
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License as published by the Free Software Foundation; either
|
9 |
* version 2 of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This library is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
* Lesser General Public License for more details.
|
15 |
*
|
16 |
* Contributions after 2012-10-29 are licensed under the terms of the
|
17 |
* GNU GPL, version 2 or (at your option) any later version.
|
18 |
*
|
19 |
* You should have received a copy of the GNU (Lesser) General Public
|
20 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
21 |
*/
|
22 |
#ifndef CPU_S390X_H
|
23 |
#define CPU_S390X_H
|
24 |
|
25 |
#include "config.h" |
26 |
#include "qemu-common.h" |
27 |
|
28 |
#define TARGET_LONG_BITS 64 |
29 |
|
30 |
#define ELF_MACHINE EM_S390
|
31 |
|
32 |
#define CPUArchState struct CPUS390XState |
33 |
|
34 |
#include "exec/cpu-defs.h" |
35 |
#define TARGET_PAGE_BITS 12 |
36 |
|
37 |
#define TARGET_PHYS_ADDR_SPACE_BITS 64 |
38 |
#define TARGET_VIRT_ADDR_SPACE_BITS 64 |
39 |
|
40 |
#include "exec/cpu-all.h" |
41 |
|
42 |
#include "fpu/softfloat.h" |
43 |
|
44 |
#define NB_MMU_MODES 3 |
45 |
|
46 |
#define MMU_MODE0_SUFFIX _primary
|
47 |
#define MMU_MODE1_SUFFIX _secondary
|
48 |
#define MMU_MODE2_SUFFIX _home
|
49 |
|
50 |
#define MMU_USER_IDX 1 |
51 |
|
52 |
#define MAX_EXT_QUEUE 16 |
53 |
#define MAX_IO_QUEUE 16 |
54 |
#define MAX_MCHK_QUEUE 16 |
55 |
|
56 |
#define PSW_MCHK_MASK 0x0004000000000000 |
57 |
#define PSW_IO_MASK 0x0200000000000000 |
58 |
|
59 |
typedef struct PSW { |
60 |
uint64_t mask; |
61 |
uint64_t addr; |
62 |
} PSW; |
63 |
|
64 |
typedef struct ExtQueue { |
65 |
uint32_t code; |
66 |
uint32_t param; |
67 |
uint32_t param64; |
68 |
} ExtQueue; |
69 |
|
70 |
typedef struct IOIntQueue { |
71 |
uint16_t id; |
72 |
uint16_t nr; |
73 |
uint32_t parm; |
74 |
uint32_t word; |
75 |
} IOIntQueue; |
76 |
|
77 |
typedef struct MchkQueue { |
78 |
uint16_t type; |
79 |
} MchkQueue; |
80 |
|
81 |
/* Defined values for CPUS390XState.runtime_reg_dirty_mask */
|
82 |
#define KVM_S390_RUNTIME_DIRTY_NONE 0 |
83 |
#define KVM_S390_RUNTIME_DIRTY_PARTIAL 1 |
84 |
#define KVM_S390_RUNTIME_DIRTY_FULL 2 |
85 |
|
86 |
typedef struct CPUS390XState { |
87 |
uint64_t regs[16]; /* GP registers */ |
88 |
CPU_DoubleU fregs[16]; /* FP registers */ |
89 |
uint32_t aregs[16]; /* access registers */ |
90 |
|
91 |
uint32_t fpc; /* floating-point control register */
|
92 |
uint32_t cc_op; |
93 |
|
94 |
float_status fpu_status; /* passed to softfloat lib */
|
95 |
|
96 |
/* The low part of a 128-bit return, or remainder of a divide. */
|
97 |
uint64_t retxl; |
98 |
|
99 |
PSW psw; |
100 |
|
101 |
uint64_t cc_src; |
102 |
uint64_t cc_dst; |
103 |
uint64_t cc_vr; |
104 |
|
105 |
uint64_t __excp_addr; |
106 |
uint64_t psa; |
107 |
|
108 |
uint32_t int_pgm_code; |
109 |
uint32_t int_pgm_ilen; |
110 |
|
111 |
uint32_t int_svc_code; |
112 |
uint32_t int_svc_ilen; |
113 |
|
114 |
uint64_t cregs[16]; /* control registers */ |
115 |
|
116 |
ExtQueue ext_queue[MAX_EXT_QUEUE]; |
117 |
IOIntQueue io_queue[MAX_IO_QUEUE][8];
|
118 |
MchkQueue mchk_queue[MAX_MCHK_QUEUE]; |
119 |
|
120 |
int pending_int;
|
121 |
int ext_index;
|
122 |
int io_index[8]; |
123 |
int mchk_index;
|
124 |
|
125 |
uint64_t ckc; |
126 |
uint64_t cputm; |
127 |
uint32_t todpr; |
128 |
|
129 |
/* on S390 the runtime register set has two dirty states:
|
130 |
* a partial dirty state in which only the registers that
|
131 |
* are needed all the time are fetched. And a fully dirty
|
132 |
* state in which all runtime registers are fetched.
|
133 |
*/
|
134 |
uint32_t runtime_reg_dirty_mask; |
135 |
|
136 |
CPU_COMMON |
137 |
|
138 |
/* reset does memset(0) up to here */
|
139 |
|
140 |
int cpu_num;
|
141 |
uint8_t *storage_keys; |
142 |
|
143 |
uint64_t tod_offset; |
144 |
uint64_t tod_basetime; |
145 |
QEMUTimer *tod_timer; |
146 |
|
147 |
QEMUTimer *cpu_timer; |
148 |
} CPUS390XState; |
149 |
|
150 |
#include "cpu-qom.h" |
151 |
|
152 |
#if defined(CONFIG_USER_ONLY)
|
153 |
static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp) |
154 |
{ |
155 |
if (newsp) {
|
156 |
env->regs[15] = newsp;
|
157 |
} |
158 |
env->regs[2] = 0; |
159 |
} |
160 |
#endif
|
161 |
|
162 |
/* distinguish between 24 bit and 31 bit addressing */
|
163 |
#define HIGH_ORDER_BIT 0x80000000 |
164 |
|
165 |
/* Interrupt Codes */
|
166 |
/* Program Interrupts */
|
167 |
#define PGM_OPERATION 0x0001 |
168 |
#define PGM_PRIVILEGED 0x0002 |
169 |
#define PGM_EXECUTE 0x0003 |
170 |
#define PGM_PROTECTION 0x0004 |
171 |
#define PGM_ADDRESSING 0x0005 |
172 |
#define PGM_SPECIFICATION 0x0006 |
173 |
#define PGM_DATA 0x0007 |
174 |
#define PGM_FIXPT_OVERFLOW 0x0008 |
175 |
#define PGM_FIXPT_DIVIDE 0x0009 |
176 |
#define PGM_DEC_OVERFLOW 0x000a |
177 |
#define PGM_DEC_DIVIDE 0x000b |
178 |
#define PGM_HFP_EXP_OVERFLOW 0x000c |
179 |
#define PGM_HFP_EXP_UNDERFLOW 0x000d |
180 |
#define PGM_HFP_SIGNIFICANCE 0x000e |
181 |
#define PGM_HFP_DIVIDE 0x000f |
182 |
#define PGM_SEGMENT_TRANS 0x0010 |
183 |
#define PGM_PAGE_TRANS 0x0011 |
184 |
#define PGM_TRANS_SPEC 0x0012 |
185 |
#define PGM_SPECIAL_OP 0x0013 |
186 |
#define PGM_OPERAND 0x0015 |
187 |
#define PGM_TRACE_TABLE 0x0016 |
188 |
#define PGM_SPACE_SWITCH 0x001c |
189 |
#define PGM_HFP_SQRT 0x001d |
190 |
#define PGM_PC_TRANS_SPEC 0x001f |
191 |
#define PGM_AFX_TRANS 0x0020 |
192 |
#define PGM_ASX_TRANS 0x0021 |
193 |
#define PGM_LX_TRANS 0x0022 |
194 |
#define PGM_EX_TRANS 0x0023 |
195 |
#define PGM_PRIM_AUTH 0x0024 |
196 |
#define PGM_SEC_AUTH 0x0025 |
197 |
#define PGM_ALET_SPEC 0x0028 |
198 |
#define PGM_ALEN_SPEC 0x0029 |
199 |
#define PGM_ALE_SEQ 0x002a |
200 |
#define PGM_ASTE_VALID 0x002b |
201 |
#define PGM_ASTE_SEQ 0x002c |
202 |
#define PGM_EXT_AUTH 0x002d |
203 |
#define PGM_STACK_FULL 0x0030 |
204 |
#define PGM_STACK_EMPTY 0x0031 |
205 |
#define PGM_STACK_SPEC 0x0032 |
206 |
#define PGM_STACK_TYPE 0x0033 |
207 |
#define PGM_STACK_OP 0x0034 |
208 |
#define PGM_ASCE_TYPE 0x0038 |
209 |
#define PGM_REG_FIRST_TRANS 0x0039 |
210 |
#define PGM_REG_SEC_TRANS 0x003a |
211 |
#define PGM_REG_THIRD_TRANS 0x003b |
212 |
#define PGM_MONITOR 0x0040 |
213 |
#define PGM_PER 0x0080 |
214 |
#define PGM_CRYPTO 0x0119 |
215 |
|
216 |
/* External Interrupts */
|
217 |
#define EXT_INTERRUPT_KEY 0x0040 |
218 |
#define EXT_CLOCK_COMP 0x1004 |
219 |
#define EXT_CPU_TIMER 0x1005 |
220 |
#define EXT_MALFUNCTION 0x1200 |
221 |
#define EXT_EMERGENCY 0x1201 |
222 |
#define EXT_EXTERNAL_CALL 0x1202 |
223 |
#define EXT_ETR 0x1406 |
224 |
#define EXT_SERVICE 0x2401 |
225 |
#define EXT_VIRTIO 0x2603 |
226 |
|
227 |
/* PSW defines */
|
228 |
#undef PSW_MASK_PER
|
229 |
#undef PSW_MASK_DAT
|
230 |
#undef PSW_MASK_IO
|
231 |
#undef PSW_MASK_EXT
|
232 |
#undef PSW_MASK_KEY
|
233 |
#undef PSW_SHIFT_KEY
|
234 |
#undef PSW_MASK_MCHECK
|
235 |
#undef PSW_MASK_WAIT
|
236 |
#undef PSW_MASK_PSTATE
|
237 |
#undef PSW_MASK_ASC
|
238 |
#undef PSW_MASK_CC
|
239 |
#undef PSW_MASK_PM
|
240 |
#undef PSW_MASK_64
|
241 |
|
242 |
#define PSW_MASK_PER 0x4000000000000000ULL |
243 |
#define PSW_MASK_DAT 0x0400000000000000ULL |
244 |
#define PSW_MASK_IO 0x0200000000000000ULL |
245 |
#define PSW_MASK_EXT 0x0100000000000000ULL |
246 |
#define PSW_MASK_KEY 0x00F0000000000000ULL |
247 |
#define PSW_SHIFT_KEY 56 |
248 |
#define PSW_MASK_MCHECK 0x0004000000000000ULL |
249 |
#define PSW_MASK_WAIT 0x0002000000000000ULL |
250 |
#define PSW_MASK_PSTATE 0x0001000000000000ULL |
251 |
#define PSW_MASK_ASC 0x0000C00000000000ULL |
252 |
#define PSW_MASK_CC 0x0000300000000000ULL |
253 |
#define PSW_MASK_PM 0x00000F0000000000ULL |
254 |
#define PSW_MASK_64 0x0000000100000000ULL |
255 |
#define PSW_MASK_32 0x0000000080000000ULL |
256 |
|
257 |
#undef PSW_ASC_PRIMARY
|
258 |
#undef PSW_ASC_ACCREG
|
259 |
#undef PSW_ASC_SECONDARY
|
260 |
#undef PSW_ASC_HOME
|
261 |
|
262 |
#define PSW_ASC_PRIMARY 0x0000000000000000ULL |
263 |
#define PSW_ASC_ACCREG 0x0000400000000000ULL |
264 |
#define PSW_ASC_SECONDARY 0x0000800000000000ULL |
265 |
#define PSW_ASC_HOME 0x0000C00000000000ULL |
266 |
|
267 |
/* tb flags */
|
268 |
|
269 |
#define FLAG_MASK_PER (PSW_MASK_PER >> 32) |
270 |
#define FLAG_MASK_DAT (PSW_MASK_DAT >> 32) |
271 |
#define FLAG_MASK_IO (PSW_MASK_IO >> 32) |
272 |
#define FLAG_MASK_EXT (PSW_MASK_EXT >> 32) |
273 |
#define FLAG_MASK_KEY (PSW_MASK_KEY >> 32) |
274 |
#define FLAG_MASK_MCHECK (PSW_MASK_MCHECK >> 32) |
275 |
#define FLAG_MASK_WAIT (PSW_MASK_WAIT >> 32) |
276 |
#define FLAG_MASK_PSTATE (PSW_MASK_PSTATE >> 32) |
277 |
#define FLAG_MASK_ASC (PSW_MASK_ASC >> 32) |
278 |
#define FLAG_MASK_CC (PSW_MASK_CC >> 32) |
279 |
#define FLAG_MASK_PM (PSW_MASK_PM >> 32) |
280 |
#define FLAG_MASK_64 (PSW_MASK_64 >> 32) |
281 |
#define FLAG_MASK_32 0x00001000 |
282 |
|
283 |
static inline int cpu_mmu_index (CPUS390XState *env) |
284 |
{ |
285 |
if (env->psw.mask & PSW_MASK_PSTATE) {
|
286 |
return 1; |
287 |
} |
288 |
|
289 |
return 0; |
290 |
} |
291 |
|
292 |
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc, |
293 |
target_ulong *cs_base, int *flags)
|
294 |
{ |
295 |
*pc = env->psw.addr; |
296 |
*cs_base = 0;
|
297 |
*flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) |
|
298 |
((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
|
299 |
} |
300 |
|
301 |
/* While the PoO talks about ILC (a number between 1-3) what is actually
|
302 |
stored in LowCore is shifted left one bit (an even between 2-6). As
|
303 |
this is the actual length of the insn and therefore more useful, that
|
304 |
is what we want to pass around and manipulate. To make sure that we
|
305 |
have applied this distinction universally, rename the "ILC" to "ILEN". */
|
306 |
static inline int get_ilen(uint8_t opc) |
307 |
{ |
308 |
switch (opc >> 6) { |
309 |
case 0: |
310 |
return 2; |
311 |
case 1: |
312 |
case 2: |
313 |
return 4; |
314 |
default:
|
315 |
return 6; |
316 |
} |
317 |
} |
318 |
|
319 |
#ifndef CONFIG_USER_ONLY
|
320 |
/* In several cases of runtime exceptions, we havn't recorded the true
|
321 |
instruction length. Use these codes when raising exceptions in order
|
322 |
to re-compute the length by examining the insn in memory. */
|
323 |
#define ILEN_LATER 0x20 |
324 |
#define ILEN_LATER_INC 0x21 |
325 |
#endif
|
326 |
|
327 |
S390CPU *cpu_s390x_init(const char *cpu_model); |
328 |
void s390x_translate_init(void); |
329 |
int cpu_s390x_exec(CPUS390XState *s);
|
330 |
|
331 |
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
332 |
signal handlers to inform the virtual CPU of exceptions. non zero
|
333 |
is returned if the signal was handled by the virtual CPU. */
|
334 |
int cpu_s390x_signal_handler(int host_signum, void *pinfo, |
335 |
void *puc);
|
336 |
int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw, |
337 |
int mmu_idx);
|
338 |
#define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault
|
339 |
|
340 |
#include "ioinst.h" |
341 |
|
342 |
#ifndef CONFIG_USER_ONLY
|
343 |
void *s390_cpu_physical_memory_map(CPUS390XState *env, hwaddr addr, hwaddr *len,
|
344 |
int is_write);
|
345 |
void s390_cpu_physical_memory_unmap(CPUS390XState *env, void *addr, hwaddr len, |
346 |
int is_write);
|
347 |
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb) |
348 |
{ |
349 |
hwaddr addr = 0;
|
350 |
uint8_t reg; |
351 |
|
352 |
reg = ipb >> 28;
|
353 |
if (reg > 0) { |
354 |
addr = env->regs[reg]; |
355 |
} |
356 |
addr += (ipb >> 16) & 0xfff; |
357 |
|
358 |
return addr;
|
359 |
} |
360 |
|
361 |
void s390x_tod_timer(void *opaque); |
362 |
void s390x_cpu_timer(void *opaque); |
363 |
|
364 |
int s390_virtio_hypercall(CPUS390XState *env);
|
365 |
|
366 |
#ifdef CONFIG_KVM
|
367 |
void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code); |
368 |
void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token); |
369 |
void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, |
370 |
uint64_t parm64, int vm);
|
371 |
#else
|
372 |
static inline void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code) |
373 |
{ |
374 |
} |
375 |
|
376 |
static inline void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, |
377 |
uint64_t token) |
378 |
{ |
379 |
} |
380 |
|
381 |
static inline void kvm_s390_interrupt_internal(S390CPU *cpu, int type, |
382 |
uint32_t parm, uint64_t parm64, |
383 |
int vm)
|
384 |
{ |
385 |
} |
386 |
#endif
|
387 |
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr); |
388 |
void s390_add_running_cpu(S390CPU *cpu);
|
389 |
unsigned s390_del_running_cpu(S390CPU *cpu);
|
390 |
|
391 |
/* service interrupts are floating therefore we must not pass an cpustate */
|
392 |
void s390_sclp_extint(uint32_t parm);
|
393 |
|
394 |
/* from s390-virtio-bus */
|
395 |
extern const hwaddr virtio_size; |
396 |
|
397 |
#else
|
398 |
static inline void s390_add_running_cpu(S390CPU *cpu) |
399 |
{ |
400 |
} |
401 |
|
402 |
static inline unsigned s390_del_running_cpu(S390CPU *cpu) |
403 |
{ |
404 |
return 0; |
405 |
} |
406 |
#endif
|
407 |
void cpu_lock(void); |
408 |
void cpu_unlock(void); |
409 |
|
410 |
typedef struct SubchDev SubchDev; |
411 |
|
412 |
#ifndef CONFIG_USER_ONLY
|
413 |
SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, |
414 |
uint16_t schid); |
415 |
bool css_subch_visible(SubchDev *sch);
|
416 |
void css_conditional_io_interrupt(SubchDev *sch);
|
417 |
int css_do_stsch(SubchDev *sch, SCHIB *schib);
|
418 |
bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid); |
419 |
int css_do_msch(SubchDev *sch, SCHIB *schib);
|
420 |
int css_do_xsch(SubchDev *sch);
|
421 |
int css_do_csch(SubchDev *sch);
|
422 |
int css_do_hsch(SubchDev *sch);
|
423 |
int css_do_ssch(SubchDev *sch, ORB *orb);
|
424 |
int css_do_tsch(SubchDev *sch, IRB *irb);
|
425 |
int css_do_stcrw(CRW *crw);
|
426 |
int css_do_tpi(IOIntCode *int_code, int lowcore); |
427 |
int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid, |
428 |
int rfmt, void *buf); |
429 |
void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo); |
430 |
int css_enable_mcsse(void); |
431 |
int css_enable_mss(void); |
432 |
int css_do_rsch(SubchDev *sch);
|
433 |
int css_do_rchp(uint8_t cssid, uint8_t chpid);
|
434 |
bool css_present(uint8_t cssid);
|
435 |
#else
|
436 |
static inline SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, |
437 |
uint16_t schid) |
438 |
{ |
439 |
return NULL; |
440 |
} |
441 |
static inline bool css_subch_visible(SubchDev *sch) |
442 |
{ |
443 |
return false; |
444 |
} |
445 |
static inline void css_conditional_io_interrupt(SubchDev *sch) |
446 |
{ |
447 |
} |
448 |
static inline int css_do_stsch(SubchDev *sch, SCHIB *schib) |
449 |
{ |
450 |
return -ENODEV;
|
451 |
} |
452 |
static inline bool css_schid_final(uint8_t cssid, uint8_t ssid, uint16_t schid) |
453 |
{ |
454 |
return true; |
455 |
} |
456 |
static inline int css_do_msch(SubchDev *sch, SCHIB *schib) |
457 |
{ |
458 |
return -ENODEV;
|
459 |
} |
460 |
static inline int css_do_xsch(SubchDev *sch) |
461 |
{ |
462 |
return -ENODEV;
|
463 |
} |
464 |
static inline int css_do_csch(SubchDev *sch) |
465 |
{ |
466 |
return -ENODEV;
|
467 |
} |
468 |
static inline int css_do_hsch(SubchDev *sch) |
469 |
{ |
470 |
return -ENODEV;
|
471 |
} |
472 |
static inline int css_do_ssch(SubchDev *sch, ORB *orb) |
473 |
{ |
474 |
return -ENODEV;
|
475 |
} |
476 |
static inline int css_do_tsch(SubchDev *sch, IRB *irb) |
477 |
{ |
478 |
return -ENODEV;
|
479 |
} |
480 |
static inline int css_do_stcrw(CRW *crw) |
481 |
{ |
482 |
return 1; |
483 |
} |
484 |
static inline int css_do_tpi(IOIntCode *int_code, int lowcore) |
485 |
{ |
486 |
return 0; |
487 |
} |
488 |
static inline int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, |
489 |
int rfmt, uint8_t l_chpid, void *buf) |
490 |
{ |
491 |
return 0; |
492 |
} |
493 |
static inline void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo) |
494 |
{ |
495 |
} |
496 |
static inline int css_enable_mss(void) |
497 |
{ |
498 |
return -EINVAL;
|
499 |
} |
500 |
static inline int css_enable_mcsse(void) |
501 |
{ |
502 |
return -EINVAL;
|
503 |
} |
504 |
static inline int css_do_rsch(SubchDev *sch) |
505 |
{ |
506 |
return -ENODEV;
|
507 |
} |
508 |
static inline int css_do_rchp(uint8_t cssid, uint8_t chpid) |
509 |
{ |
510 |
return -ENODEV;
|
511 |
} |
512 |
static inline bool css_present(uint8_t cssid) |
513 |
{ |
514 |
return false; |
515 |
} |
516 |
#endif
|
517 |
|
518 |
static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) |
519 |
{ |
520 |
env->aregs[0] = newtls >> 32; |
521 |
env->aregs[1] = newtls & 0xffffffffULL; |
522 |
} |
523 |
|
524 |
#define cpu_init(model) (&cpu_s390x_init(model)->env)
|
525 |
#define cpu_exec cpu_s390x_exec
|
526 |
#define cpu_gen_code cpu_s390x_gen_code
|
527 |
#define cpu_signal_handler cpu_s390x_signal_handler
|
528 |
|
529 |
void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
530 |
#define cpu_list s390_cpu_list
|
531 |
|
532 |
#include "exec/exec-all.h" |
533 |
|
534 |
#define EXCP_EXT 1 /* external interrupt */ |
535 |
#define EXCP_SVC 2 /* supervisor call (syscall) */ |
536 |
#define EXCP_PGM 3 /* program interruption */ |
537 |
#define EXCP_IO 7 /* I/O interrupt */ |
538 |
#define EXCP_MCHK 8 /* machine check */ |
539 |
|
540 |
#define INTERRUPT_EXT (1 << 0) |
541 |
#define INTERRUPT_TOD (1 << 1) |
542 |
#define INTERRUPT_CPUTIMER (1 << 2) |
543 |
#define INTERRUPT_IO (1 << 3) |
544 |
#define INTERRUPT_MCHK (1 << 4) |
545 |
|
546 |
/* Program Status Word. */
|
547 |
#define S390_PSWM_REGNUM 0 |
548 |
#define S390_PSWA_REGNUM 1 |
549 |
/* General Purpose Registers. */
|
550 |
#define S390_R0_REGNUM 2 |
551 |
#define S390_R1_REGNUM 3 |
552 |
#define S390_R2_REGNUM 4 |
553 |
#define S390_R3_REGNUM 5 |
554 |
#define S390_R4_REGNUM 6 |
555 |
#define S390_R5_REGNUM 7 |
556 |
#define S390_R6_REGNUM 8 |
557 |
#define S390_R7_REGNUM 9 |
558 |
#define S390_R8_REGNUM 10 |
559 |
#define S390_R9_REGNUM 11 |
560 |
#define S390_R10_REGNUM 12 |
561 |
#define S390_R11_REGNUM 13 |
562 |
#define S390_R12_REGNUM 14 |
563 |
#define S390_R13_REGNUM 15 |
564 |
#define S390_R14_REGNUM 16 |
565 |
#define S390_R15_REGNUM 17 |
566 |
/* Access Registers. */
|
567 |
#define S390_A0_REGNUM 18 |
568 |
#define S390_A1_REGNUM 19 |
569 |
#define S390_A2_REGNUM 20 |
570 |
#define S390_A3_REGNUM 21 |
571 |
#define S390_A4_REGNUM 22 |
572 |
#define S390_A5_REGNUM 23 |
573 |
#define S390_A6_REGNUM 24 |
574 |
#define S390_A7_REGNUM 25 |
575 |
#define S390_A8_REGNUM 26 |
576 |
#define S390_A9_REGNUM 27 |
577 |
#define S390_A10_REGNUM 28 |
578 |
#define S390_A11_REGNUM 29 |
579 |
#define S390_A12_REGNUM 30 |
580 |
#define S390_A13_REGNUM 31 |
581 |
#define S390_A14_REGNUM 32 |
582 |
#define S390_A15_REGNUM 33 |
583 |
/* Floating Point Control Word. */
|
584 |
#define S390_FPC_REGNUM 34 |
585 |
/* Floating Point Registers. */
|
586 |
#define S390_F0_REGNUM 35 |
587 |
#define S390_F1_REGNUM 36 |
588 |
#define S390_F2_REGNUM 37 |
589 |
#define S390_F3_REGNUM 38 |
590 |
#define S390_F4_REGNUM 39 |
591 |
#define S390_F5_REGNUM 40 |
592 |
#define S390_F6_REGNUM 41 |
593 |
#define S390_F7_REGNUM 42 |
594 |
#define S390_F8_REGNUM 43 |
595 |
#define S390_F9_REGNUM 44 |
596 |
#define S390_F10_REGNUM 45 |
597 |
#define S390_F11_REGNUM 46 |
598 |
#define S390_F12_REGNUM 47 |
599 |
#define S390_F13_REGNUM 48 |
600 |
#define S390_F14_REGNUM 49 |
601 |
#define S390_F15_REGNUM 50 |
602 |
/* Total. */
|
603 |
#define S390_NUM_REGS 51 |
604 |
|
605 |
/* CC optimization */
|
606 |
|
607 |
enum cc_op {
|
608 |
CC_OP_CONST0 = 0, /* CC is 0 */ |
609 |
CC_OP_CONST1, /* CC is 1 */
|
610 |
CC_OP_CONST2, /* CC is 2 */
|
611 |
CC_OP_CONST3, /* CC is 3 */
|
612 |
|
613 |
CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
|
614 |
CC_OP_STATIC, /* CC value is env->cc_op */
|
615 |
|
616 |
CC_OP_NZ, /* env->cc_dst != 0 */
|
617 |
CC_OP_LTGT_32, /* signed less/greater than (32bit) */
|
618 |
CC_OP_LTGT_64, /* signed less/greater than (64bit) */
|
619 |
CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
|
620 |
CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
|
621 |
CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
|
622 |
CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
|
623 |
|
624 |
CC_OP_ADD_64, /* overflow on add (64bit) */
|
625 |
CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
|
626 |
CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
|
627 |
CC_OP_SUB_64, /* overflow on subtraction (64bit) */
|
628 |
CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
|
629 |
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
|
630 |
CC_OP_ABS_64, /* sign eval on abs (64bit) */
|
631 |
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
|
632 |
|
633 |
CC_OP_ADD_32, /* overflow on add (32bit) */
|
634 |
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
|
635 |
CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
|
636 |
CC_OP_SUB_32, /* overflow on subtraction (32bit) */
|
637 |
CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
|
638 |
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
|
639 |
CC_OP_ABS_32, /* sign eval on abs (64bit) */
|
640 |
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
|
641 |
|
642 |
CC_OP_COMP_32, /* complement */
|
643 |
CC_OP_COMP_64, /* complement */
|
644 |
|
645 |
CC_OP_TM_32, /* test under mask (32bit) */
|
646 |
CC_OP_TM_64, /* test under mask (64bit) */
|
647 |
|
648 |
CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
|
649 |
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
|
650 |
CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
|
651 |
|
652 |
CC_OP_ICM, /* insert characters under mask */
|
653 |
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
|
654 |
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
|
655 |
CC_OP_FLOGR, /* find leftmost one */
|
656 |
CC_OP_MAX |
657 |
}; |
658 |
|
659 |
static const char *cc_names[] = { |
660 |
[CC_OP_CONST0] = "CC_OP_CONST0",
|
661 |
[CC_OP_CONST1] = "CC_OP_CONST1",
|
662 |
[CC_OP_CONST2] = "CC_OP_CONST2",
|
663 |
[CC_OP_CONST3] = "CC_OP_CONST3",
|
664 |
[CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
|
665 |
[CC_OP_STATIC] = "CC_OP_STATIC",
|
666 |
[CC_OP_NZ] = "CC_OP_NZ",
|
667 |
[CC_OP_LTGT_32] = "CC_OP_LTGT_32",
|
668 |
[CC_OP_LTGT_64] = "CC_OP_LTGT_64",
|
669 |
[CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
|
670 |
[CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
|
671 |
[CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
|
672 |
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
|
673 |
[CC_OP_ADD_64] = "CC_OP_ADD_64",
|
674 |
[CC_OP_ADDU_64] = "CC_OP_ADDU_64",
|
675 |
[CC_OP_ADDC_64] = "CC_OP_ADDC_64",
|
676 |
[CC_OP_SUB_64] = "CC_OP_SUB_64",
|
677 |
[CC_OP_SUBU_64] = "CC_OP_SUBU_64",
|
678 |
[CC_OP_SUBB_64] = "CC_OP_SUBB_64",
|
679 |
[CC_OP_ABS_64] = "CC_OP_ABS_64",
|
680 |
[CC_OP_NABS_64] = "CC_OP_NABS_64",
|
681 |
[CC_OP_ADD_32] = "CC_OP_ADD_32",
|
682 |
[CC_OP_ADDU_32] = "CC_OP_ADDU_32",
|
683 |
[CC_OP_ADDC_32] = "CC_OP_ADDC_32",
|
684 |
[CC_OP_SUB_32] = "CC_OP_SUB_32",
|
685 |
[CC_OP_SUBU_32] = "CC_OP_SUBU_32",
|
686 |
[CC_OP_SUBB_32] = "CC_OP_SUBB_32",
|
687 |
[CC_OP_ABS_32] = "CC_OP_ABS_32",
|
688 |
[CC_OP_NABS_32] = "CC_OP_NABS_32",
|
689 |
[CC_OP_COMP_32] = "CC_OP_COMP_32",
|
690 |
[CC_OP_COMP_64] = "CC_OP_COMP_64",
|
691 |
[CC_OP_TM_32] = "CC_OP_TM_32",
|
692 |
[CC_OP_TM_64] = "CC_OP_TM_64",
|
693 |
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
|
694 |
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
|
695 |
[CC_OP_NZ_F128] = "CC_OP_NZ_F128",
|
696 |
[CC_OP_ICM] = "CC_OP_ICM",
|
697 |
[CC_OP_SLA_32] = "CC_OP_SLA_32",
|
698 |
[CC_OP_SLA_64] = "CC_OP_SLA_64",
|
699 |
[CC_OP_FLOGR] = "CC_OP_FLOGR",
|
700 |
}; |
701 |
|
702 |
static inline const char *cc_name(int cc_op) |
703 |
{ |
704 |
return cc_names[cc_op];
|
705 |
} |
706 |
|
707 |
typedef struct LowCore |
708 |
{ |
709 |
/* prefix area: defined by architecture */
|
710 |
uint32_t ccw1[2]; /* 0x000 */ |
711 |
uint32_t ccw2[4]; /* 0x008 */ |
712 |
uint8_t pad1[0x80-0x18]; /* 0x018 */ |
713 |
uint32_t ext_params; /* 0x080 */
|
714 |
uint16_t cpu_addr; /* 0x084 */
|
715 |
uint16_t ext_int_code; /* 0x086 */
|
716 |
uint16_t svc_ilen; /* 0x088 */
|
717 |
uint16_t svc_code; /* 0x08a */
|
718 |
uint16_t pgm_ilen; /* 0x08c */
|
719 |
uint16_t pgm_code; /* 0x08e */
|
720 |
uint32_t data_exc_code; /* 0x090 */
|
721 |
uint16_t mon_class_num; /* 0x094 */
|
722 |
uint16_t per_perc_atmid; /* 0x096 */
|
723 |
uint64_t per_address; /* 0x098 */
|
724 |
uint8_t exc_access_id; /* 0x0a0 */
|
725 |
uint8_t per_access_id; /* 0x0a1 */
|
726 |
uint8_t op_access_id; /* 0x0a2 */
|
727 |
uint8_t ar_access_id; /* 0x0a3 */
|
728 |
uint8_t pad2[0xA8-0xA4]; /* 0x0a4 */ |
729 |
uint64_t trans_exc_code; /* 0x0a8 */
|
730 |
uint64_t monitor_code; /* 0x0b0 */
|
731 |
uint16_t subchannel_id; /* 0x0b8 */
|
732 |
uint16_t subchannel_nr; /* 0x0ba */
|
733 |
uint32_t io_int_parm; /* 0x0bc */
|
734 |
uint32_t io_int_word; /* 0x0c0 */
|
735 |
uint8_t pad3[0xc8-0xc4]; /* 0x0c4 */ |
736 |
uint32_t stfl_fac_list; /* 0x0c8 */
|
737 |
uint8_t pad4[0xe8-0xcc]; /* 0x0cc */ |
738 |
uint32_t mcck_interruption_code[2]; /* 0x0e8 */ |
739 |
uint8_t pad5[0xf4-0xf0]; /* 0x0f0 */ |
740 |
uint32_t external_damage_code; /* 0x0f4 */
|
741 |
uint64_t failing_storage_address; /* 0x0f8 */
|
742 |
uint8_t pad6[0x120-0x100]; /* 0x100 */ |
743 |
PSW restart_old_psw; /* 0x120 */
|
744 |
PSW external_old_psw; /* 0x130 */
|
745 |
PSW svc_old_psw; /* 0x140 */
|
746 |
PSW program_old_psw; /* 0x150 */
|
747 |
PSW mcck_old_psw; /* 0x160 */
|
748 |
PSW io_old_psw; /* 0x170 */
|
749 |
uint8_t pad7[0x1a0-0x180]; /* 0x180 */ |
750 |
PSW restart_psw; /* 0x1a0 */
|
751 |
PSW external_new_psw; /* 0x1b0 */
|
752 |
PSW svc_new_psw; /* 0x1c0 */
|
753 |
PSW program_new_psw; /* 0x1d0 */
|
754 |
PSW mcck_new_psw; /* 0x1e0 */
|
755 |
PSW io_new_psw; /* 0x1f0 */
|
756 |
PSW return_psw; /* 0x200 */
|
757 |
uint8_t irb[64]; /* 0x210 */ |
758 |
uint64_t sync_enter_timer; /* 0x250 */
|
759 |
uint64_t async_enter_timer; /* 0x258 */
|
760 |
uint64_t exit_timer; /* 0x260 */
|
761 |
uint64_t last_update_timer; /* 0x268 */
|
762 |
uint64_t user_timer; /* 0x270 */
|
763 |
uint64_t system_timer; /* 0x278 */
|
764 |
uint64_t last_update_clock; /* 0x280 */
|
765 |
uint64_t steal_clock; /* 0x288 */
|
766 |
PSW return_mcck_psw; /* 0x290 */
|
767 |
uint8_t pad8[0xc00-0x2a0]; /* 0x2a0 */ |
768 |
/* System info area */
|
769 |
uint64_t save_area[16]; /* 0xc00 */ |
770 |
uint8_t pad9[0xd40-0xc80]; /* 0xc80 */ |
771 |
uint64_t kernel_stack; /* 0xd40 */
|
772 |
uint64_t thread_info; /* 0xd48 */
|
773 |
uint64_t async_stack; /* 0xd50 */
|
774 |
uint64_t kernel_asce; /* 0xd58 */
|
775 |
uint64_t user_asce; /* 0xd60 */
|
776 |
uint64_t panic_stack; /* 0xd68 */
|
777 |
uint64_t user_exec_asce; /* 0xd70 */
|
778 |
uint8_t pad10[0xdc0-0xd78]; /* 0xd78 */ |
779 |
|
780 |
/* SMP info area: defined by DJB */
|
781 |
uint64_t clock_comparator; /* 0xdc0 */
|
782 |
uint64_t ext_call_fast; /* 0xdc8 */
|
783 |
uint64_t percpu_offset; /* 0xdd0 */
|
784 |
uint64_t current_task; /* 0xdd8 */
|
785 |
uint32_t softirq_pending; /* 0xde0 */
|
786 |
uint32_t pad_0x0de4; /* 0xde4 */
|
787 |
uint64_t int_clock; /* 0xde8 */
|
788 |
uint8_t pad12[0xe00-0xdf0]; /* 0xdf0 */ |
789 |
|
790 |
/* 0xe00 is used as indicator for dump tools */
|
791 |
/* whether the kernel died with panic() or not */
|
792 |
uint32_t panic_magic; /* 0xe00 */
|
793 |
|
794 |
uint8_t pad13[0x11b8-0xe04]; /* 0xe04 */ |
795 |
|
796 |
/* 64 bit extparam used for pfault, diag 250 etc */
|
797 |
uint64_t ext_params2; /* 0x11B8 */
|
798 |
|
799 |
uint8_t pad14[0x1200-0x11C0]; /* 0x11C0 */ |
800 |
|
801 |
/* System info area */
|
802 |
|
803 |
uint64_t floating_pt_save_area[16]; /* 0x1200 */ |
804 |
uint64_t gpregs_save_area[16]; /* 0x1280 */ |
805 |
uint32_t st_status_fixed_logout[4]; /* 0x1300 */ |
806 |
uint8_t pad15[0x1318-0x1310]; /* 0x1310 */ |
807 |
uint32_t prefixreg_save_area; /* 0x1318 */
|
808 |
uint32_t fpt_creg_save_area; /* 0x131c */
|
809 |
uint8_t pad16[0x1324-0x1320]; /* 0x1320 */ |
810 |
uint32_t tod_progreg_save_area; /* 0x1324 */
|
811 |
uint32_t cpu_timer_save_area[2]; /* 0x1328 */ |
812 |
uint32_t clock_comp_save_area[2]; /* 0x1330 */ |
813 |
uint8_t pad17[0x1340-0x1338]; /* 0x1338 */ |
814 |
uint32_t access_regs_save_area[16]; /* 0x1340 */ |
815 |
uint64_t cregs_save_area[16]; /* 0x1380 */ |
816 |
|
817 |
/* align to the top of the prefix area */
|
818 |
|
819 |
uint8_t pad18[0x2000-0x1400]; /* 0x1400 */ |
820 |
} QEMU_PACKED LowCore; |
821 |
|
822 |
/* STSI */
|
823 |
#define STSI_LEVEL_MASK 0x00000000f0000000ULL |
824 |
#define STSI_LEVEL_CURRENT 0x0000000000000000ULL |
825 |
#define STSI_LEVEL_1 0x0000000010000000ULL |
826 |
#define STSI_LEVEL_2 0x0000000020000000ULL |
827 |
#define STSI_LEVEL_3 0x0000000030000000ULL |
828 |
#define STSI_R0_RESERVED_MASK 0x000000000fffff00ULL |
829 |
#define STSI_R0_SEL1_MASK 0x00000000000000ffULL |
830 |
#define STSI_R1_RESERVED_MASK 0x00000000ffff0000ULL |
831 |
#define STSI_R1_SEL2_MASK 0x000000000000ffffULL |
832 |
|
833 |
/* Basic Machine Configuration */
|
834 |
struct sysib_111 {
|
835 |
uint32_t res1[8];
|
836 |
uint8_t manuf[16];
|
837 |
uint8_t type[4];
|
838 |
uint8_t res2[12];
|
839 |
uint8_t model[16];
|
840 |
uint8_t sequence[16];
|
841 |
uint8_t plant[4];
|
842 |
uint8_t res3[156];
|
843 |
}; |
844 |
|
845 |
/* Basic Machine CPU */
|
846 |
struct sysib_121 {
|
847 |
uint32_t res1[80];
|
848 |
uint8_t sequence[16];
|
849 |
uint8_t plant[4];
|
850 |
uint8_t res2[2];
|
851 |
uint16_t cpu_addr; |
852 |
uint8_t res3[152];
|
853 |
}; |
854 |
|
855 |
/* Basic Machine CPUs */
|
856 |
struct sysib_122 {
|
857 |
uint8_t res1[32];
|
858 |
uint32_t capability; |
859 |
uint16_t total_cpus; |
860 |
uint16_t active_cpus; |
861 |
uint16_t standby_cpus; |
862 |
uint16_t reserved_cpus; |
863 |
uint16_t adjustments[2026];
|
864 |
}; |
865 |
|
866 |
/* LPAR CPU */
|
867 |
struct sysib_221 {
|
868 |
uint32_t res1[80];
|
869 |
uint8_t sequence[16];
|
870 |
uint8_t plant[4];
|
871 |
uint16_t cpu_id; |
872 |
uint16_t cpu_addr; |
873 |
uint8_t res3[152];
|
874 |
}; |
875 |
|
876 |
/* LPAR CPUs */
|
877 |
struct sysib_222 {
|
878 |
uint32_t res1[32];
|
879 |
uint16_t lpar_num; |
880 |
uint8_t res2; |
881 |
uint8_t lcpuc; |
882 |
uint16_t total_cpus; |
883 |
uint16_t conf_cpus; |
884 |
uint16_t standby_cpus; |
885 |
uint16_t reserved_cpus; |
886 |
uint8_t name[8];
|
887 |
uint32_t caf; |
888 |
uint8_t res3[16];
|
889 |
uint16_t dedicated_cpus; |
890 |
uint16_t shared_cpus; |
891 |
uint8_t res4[180];
|
892 |
}; |
893 |
|
894 |
/* VM CPUs */
|
895 |
struct sysib_322 {
|
896 |
uint8_t res1[31];
|
897 |
uint8_t count; |
898 |
struct {
|
899 |
uint8_t res2[4];
|
900 |
uint16_t total_cpus; |
901 |
uint16_t conf_cpus; |
902 |
uint16_t standby_cpus; |
903 |
uint16_t reserved_cpus; |
904 |
uint8_t name[8];
|
905 |
uint32_t caf; |
906 |
uint8_t cpi[16];
|
907 |
uint8_t res3[24];
|
908 |
} vm[8];
|
909 |
uint8_t res4[3552];
|
910 |
}; |
911 |
|
912 |
/* MMU defines */
|
913 |
#define _ASCE_ORIGIN ~0xfffULL /* segment table origin */ |
914 |
#define _ASCE_SUBSPACE 0x200 /* subspace group control */ |
915 |
#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */ |
916 |
#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */ |
917 |
#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */ |
918 |
#define _ASCE_REAL_SPACE 0x20 /* real space control */ |
919 |
#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */ |
920 |
#define _ASCE_TYPE_REGION1 0x0c /* region first table type */ |
921 |
#define _ASCE_TYPE_REGION2 0x08 /* region second table type */ |
922 |
#define _ASCE_TYPE_REGION3 0x04 /* region third table type */ |
923 |
#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */ |
924 |
#define _ASCE_TABLE_LENGTH 0x03 /* region table length */ |
925 |
|
926 |
#define _REGION_ENTRY_ORIGIN ~0xfffULL /* region/segment table origin */ |
927 |
#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */ |
928 |
#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */ |
929 |
#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */ |
930 |
#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */ |
931 |
#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */ |
932 |
#define _REGION_ENTRY_LENGTH 0x03 /* region third length */ |
933 |
|
934 |
#define _SEGMENT_ENTRY_ORIGIN ~0x7ffULL /* segment table origin */ |
935 |
#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */ |
936 |
#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */ |
937 |
|
938 |
#define _PAGE_RO 0x200 /* HW read-only bit */ |
939 |
#define _PAGE_INVALID 0x400 /* HW invalid bit */ |
940 |
|
941 |
#define SK_C (0x1 << 1) |
942 |
#define SK_R (0x1 << 2) |
943 |
#define SK_F (0x1 << 3) |
944 |
#define SK_ACC_MASK (0xf << 4) |
945 |
|
946 |
#define SIGP_SENSE 0x01 |
947 |
#define SIGP_EXTERNAL_CALL 0x02 |
948 |
#define SIGP_EMERGENCY 0x03 |
949 |
#define SIGP_START 0x04 |
950 |
#define SIGP_STOP 0x05 |
951 |
#define SIGP_RESTART 0x06 |
952 |
#define SIGP_STOP_STORE_STATUS 0x09 |
953 |
#define SIGP_INITIAL_CPU_RESET 0x0b |
954 |
#define SIGP_CPU_RESET 0x0c |
955 |
#define SIGP_SET_PREFIX 0x0d |
956 |
#define SIGP_STORE_STATUS_ADDR 0x0e |
957 |
#define SIGP_SET_ARCH 0x12 |
958 |
|
959 |
/* cpu status bits */
|
960 |
#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL |
961 |
#define SIGP_STAT_INCORRECT_STATE 0x00000200UL |
962 |
#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL |
963 |
#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL |
964 |
#define SIGP_STAT_STOPPED 0x00000040UL |
965 |
#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL |
966 |
#define SIGP_STAT_CHECK_STOP 0x00000010UL |
967 |
#define SIGP_STAT_INOPERATIVE 0x00000004UL |
968 |
#define SIGP_STAT_INVALID_ORDER 0x00000002UL |
969 |
#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL |
970 |
|
971 |
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
|
972 |
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, |
973 |
target_ulong *raddr, int *flags);
|
974 |
int sclp_service_call(uint32_t sccb, uint64_t code);
|
975 |
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, |
976 |
uint64_t vr); |
977 |
|
978 |
#define TARGET_HAS_ICE 1 |
979 |
|
980 |
/* The value of the TOD clock for 1.1.1970. */
|
981 |
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL |
982 |
|
983 |
/* Converts ns to s390's clock format */
|
984 |
static inline uint64_t time2tod(uint64_t ns) { |
985 |
return (ns << 9) / 125; |
986 |
} |
987 |
|
988 |
static inline void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param, |
989 |
uint64_t param64) |
990 |
{ |
991 |
CPUS390XState *env = &cpu->env; |
992 |
|
993 |
if (env->ext_index == MAX_EXT_QUEUE - 1) { |
994 |
/* ugh - can't queue anymore. Let's drop. */
|
995 |
return;
|
996 |
} |
997 |
|
998 |
env->ext_index++; |
999 |
assert(env->ext_index < MAX_EXT_QUEUE); |
1000 |
|
1001 |
env->ext_queue[env->ext_index].code = code; |
1002 |
env->ext_queue[env->ext_index].param = param; |
1003 |
env->ext_queue[env->ext_index].param64 = param64; |
1004 |
|
1005 |
env->pending_int |= INTERRUPT_EXT; |
1006 |
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); |
1007 |
} |
1008 |
|
1009 |
static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id, |
1010 |
uint16_t subchannel_number, |
1011 |
uint32_t io_int_parm, uint32_t io_int_word) |
1012 |
{ |
1013 |
CPUS390XState *env = &cpu->env; |
1014 |
int isc = IO_INT_WORD_ISC(io_int_word);
|
1015 |
|
1016 |
if (env->io_index[isc] == MAX_IO_QUEUE - 1) { |
1017 |
/* ugh - can't queue anymore. Let's drop. */
|
1018 |
return;
|
1019 |
} |
1020 |
|
1021 |
env->io_index[isc]++; |
1022 |
assert(env->io_index[isc] < MAX_IO_QUEUE); |
1023 |
|
1024 |
env->io_queue[env->io_index[isc]][isc].id = subchannel_id; |
1025 |
env->io_queue[env->io_index[isc]][isc].nr = subchannel_number; |
1026 |
env->io_queue[env->io_index[isc]][isc].parm = io_int_parm; |
1027 |
env->io_queue[env->io_index[isc]][isc].word = io_int_word; |
1028 |
|
1029 |
env->pending_int |= INTERRUPT_IO; |
1030 |
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); |
1031 |
} |
1032 |
|
1033 |
static inline void cpu_inject_crw_mchk(S390CPU *cpu) |
1034 |
{ |
1035 |
CPUS390XState *env = &cpu->env; |
1036 |
|
1037 |
if (env->mchk_index == MAX_MCHK_QUEUE - 1) { |
1038 |
/* ugh - can't queue anymore. Let's drop. */
|
1039 |
return;
|
1040 |
} |
1041 |
|
1042 |
env->mchk_index++; |
1043 |
assert(env->mchk_index < MAX_MCHK_QUEUE); |
1044 |
|
1045 |
env->mchk_queue[env->mchk_index].type = 1;
|
1046 |
|
1047 |
env->pending_int |= INTERRUPT_MCHK; |
1048 |
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); |
1049 |
} |
1050 |
|
1051 |
static inline bool cpu_has_work(CPUState *cpu) |
1052 |
{ |
1053 |
S390CPU *s390_cpu = S390_CPU(cpu); |
1054 |
CPUS390XState *env = &s390_cpu->env; |
1055 |
|
1056 |
return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
|
1057 |
(env->psw.mask & PSW_MASK_EXT); |
1058 |
} |
1059 |
|
1060 |
static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb) |
1061 |
{ |
1062 |
env->psw.addr = tb->pc; |
1063 |
} |
1064 |
|
1065 |
/* fpu_helper.c */
|
1066 |
uint32_t set_cc_nz_f32(float32 v); |
1067 |
uint32_t set_cc_nz_f64(float64 v); |
1068 |
uint32_t set_cc_nz_f128(float128 v); |
1069 |
|
1070 |
/* misc_helper.c */
|
1071 |
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); |
1072 |
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, |
1073 |
uintptr_t retaddr); |
1074 |
|
1075 |
#include <sysemu/kvm.h> |
1076 |
|
1077 |
#ifdef CONFIG_KVM
|
1078 |
void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id,
|
1079 |
uint16_t subchannel_nr, uint32_t io_int_parm, |
1080 |
uint32_t io_int_word); |
1081 |
void kvm_s390_crw_mchk(S390CPU *cpu);
|
1082 |
void kvm_s390_enable_css_support(S390CPU *cpu);
|
1083 |
int kvm_s390_get_registers_partial(CPUState *cpu);
|
1084 |
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
|
1085 |
int vq, bool assign); |
1086 |
#else
|
1087 |
static inline void kvm_s390_io_interrupt(S390CPU *cpu, |
1088 |
uint16_t subchannel_id, |
1089 |
uint16_t subchannel_nr, |
1090 |
uint32_t io_int_parm, |
1091 |
uint32_t io_int_word) |
1092 |
{ |
1093 |
} |
1094 |
static inline void kvm_s390_crw_mchk(S390CPU *cpu) |
1095 |
{ |
1096 |
} |
1097 |
static inline void kvm_s390_enable_css_support(S390CPU *cpu) |
1098 |
{ |
1099 |
} |
1100 |
static inline int kvm_s390_get_registers_partial(CPUState *cpu) |
1101 |
{ |
1102 |
return -ENOSYS;
|
1103 |
} |
1104 |
static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, |
1105 |
uint32_t sch, int vq,
|
1106 |
bool assign)
|
1107 |
{ |
1108 |
return -ENOSYS;
|
1109 |
} |
1110 |
#endif
|
1111 |
|
1112 |
static inline void s390_io_interrupt(S390CPU *cpu, |
1113 |
uint16_t subchannel_id, |
1114 |
uint16_t subchannel_nr, |
1115 |
uint32_t io_int_parm, |
1116 |
uint32_t io_int_word) |
1117 |
{ |
1118 |
if (kvm_enabled()) {
|
1119 |
kvm_s390_io_interrupt(cpu, subchannel_id, subchannel_nr, io_int_parm, |
1120 |
io_int_word); |
1121 |
} else {
|
1122 |
cpu_inject_io(cpu, subchannel_id, subchannel_nr, io_int_parm, |
1123 |
io_int_word); |
1124 |
} |
1125 |
} |
1126 |
|
1127 |
static inline void s390_crw_mchk(S390CPU *cpu) |
1128 |
{ |
1129 |
if (kvm_enabled()) {
|
1130 |
kvm_s390_crw_mchk(cpu); |
1131 |
} else {
|
1132 |
cpu_inject_crw_mchk(cpu); |
1133 |
} |
1134 |
} |
1135 |
|
1136 |
static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier, |
1137 |
uint32_t sch_id, int vq,
|
1138 |
bool assign)
|
1139 |
{ |
1140 |
if (kvm_enabled()) {
|
1141 |
return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
|
1142 |
} else {
|
1143 |
return -ENOSYS;
|
1144 |
} |
1145 |
} |
1146 |
|
1147 |
#endif
|