1 /*
2 * s390x exception / interrupt helpers
3 *
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2011 Alexander Graf
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "qemu/osdep.h"
22 #include "qemu/log.h"
23 #include "cpu.h"
24 #include "exec/helper-proto.h"
25 #include "exec/exec-all.h"
26 #include "s390x-internal.h"
27 #include "tcg_s390x.h"
28 #ifndef CONFIG_USER_ONLY
29 #include "qemu/timer.h"
30 #include "exec/address-spaces.h"
31 #include "hw/s390x/ioinst.h"
32 #include "hw/s390x/s390_flic.h"
33 #include "hw/boards.h"
34 #endif
35
tcg_s390_program_interrupt(CPUS390XState * env,uint32_t code,uintptr_t ra)36 G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env,
37 uint32_t code, uintptr_t ra)
38 {
39 CPUState *cs = env_cpu(env);
40
41 cpu_restore_state(cs, ra);
42 qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
43 env->psw.addr);
44 trigger_pgm_exception(env, code);
45 cpu_loop_exit(cs);
46 }
47
tcg_s390_data_exception(CPUS390XState * env,uint32_t dxc,uintptr_t ra)48 G_NORETURN void tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
49 uintptr_t ra)
50 {
51 g_assert(dxc <= 0xff);
52 #if !defined(CONFIG_USER_ONLY)
53 /* Store the DXC into the lowcore */
54 stl_phys(env_cpu(env)->as,
55 env->psa + offsetof(LowCore, data_exc_code), dxc);
56 #endif
57
58 /* Store the DXC into the FPC if AFP is enabled */
59 if (env->cregs[0] & CR0_AFP) {
60 env->fpc = deposit32(env->fpc, 8, 8, dxc);
61 }
62 tcg_s390_program_interrupt(env, PGM_DATA, ra);
63 }
64
tcg_s390_vector_exception(CPUS390XState * env,uint32_t vxc,uintptr_t ra)65 G_NORETURN void tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc,
66 uintptr_t ra)
67 {
68 g_assert(vxc <= 0xff);
69 #if !defined(CONFIG_USER_ONLY)
70 /* Always store the VXC into the lowcore, without AFP it is undefined */
71 stl_phys(env_cpu(env)->as,
72 env->psa + offsetof(LowCore, data_exc_code), vxc);
73 #endif
74
75 /* Always store the VXC into the FPC, without AFP it is undefined */
76 env->fpc = deposit32(env->fpc, 8, 8, vxc);
77 tcg_s390_program_interrupt(env, PGM_VECTOR_PROCESSING, ra);
78 }
79
HELPER(data_exception)80 void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
81 {
82 tcg_s390_data_exception(env, dxc, GETPC());
83 }
84
85 /*
86 * Unaligned accesses are only diagnosed with MO_ALIGN. At the moment,
87 * this is only for the atomic and relative long operations, for which we want
88 * to raise a specification exception.
89 */
90 static G_NORETURN
do_unaligned_access(CPUState * cs,uintptr_t retaddr)91 void do_unaligned_access(CPUState *cs, uintptr_t retaddr)
92 {
93 S390CPU *cpu = S390_CPU(cs);
94 CPUS390XState *env = &cpu->env;
95
96 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
97 }
98
99 #if defined(CONFIG_USER_ONLY)
100
s390_cpu_do_interrupt(CPUState * cs)101 void s390_cpu_do_interrupt(CPUState *cs)
102 {
103 cs->exception_index = -1;
104 }
105
s390_cpu_record_sigsegv(CPUState * cs,vaddr address,MMUAccessType access_type,bool maperr,uintptr_t retaddr)106 void s390_cpu_record_sigsegv(CPUState *cs, vaddr address,
107 MMUAccessType access_type,
108 bool maperr, uintptr_t retaddr)
109 {
110 S390CPU *cpu = S390_CPU(cs);
111
112 trigger_pgm_exception(&cpu->env, maperr ? PGM_ADDRESSING : PGM_PROTECTION);
113 /*
114 * On real machines this value is dropped into LowMem. Since this
115 * is userland, simply put this someplace that cpu_loop can find it.
116 * S390 only gives the page of the fault, not the exact address.
117 * C.f. the construction of TEC in mmu_translate().
118 */
119 cpu->env.__excp_addr = address & TARGET_PAGE_MASK;
120 cpu_loop_exit_restore(cs, retaddr);
121 }
122
s390_cpu_record_sigbus(CPUState * cs,vaddr address,MMUAccessType access_type,uintptr_t retaddr)123 void s390_cpu_record_sigbus(CPUState *cs, vaddr address,
124 MMUAccessType access_type, uintptr_t retaddr)
125 {
126 do_unaligned_access(cs, retaddr);
127 }
128
129 #else /* !CONFIG_USER_ONLY */
130
cpu_mmu_idx_to_asc(int mmu_idx)131 static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
132 {
133 switch (mmu_idx) {
134 case MMU_PRIMARY_IDX:
135 return PSW_ASC_PRIMARY;
136 case MMU_SECONDARY_IDX:
137 return PSW_ASC_SECONDARY;
138 case MMU_HOME_IDX:
139 return PSW_ASC_HOME;
140 default:
141 abort();
142 }
143 }
144
s390_cpu_tlb_fill(CPUState * cs,vaddr address,int size,MMUAccessType access_type,int mmu_idx,bool probe,uintptr_t retaddr)145 bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
146 MMUAccessType access_type, int mmu_idx,
147 bool probe, uintptr_t retaddr)
148 {
149 S390CPU *cpu = S390_CPU(cs);
150 CPUS390XState *env = &cpu->env;
151 target_ulong vaddr, raddr;
152 uint64_t asc, tec;
153 int prot, excp;
154
155 qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
156 __func__, address, access_type, mmu_idx);
157
158 vaddr = address;
159
160 if (mmu_idx < MMU_REAL_IDX) {
161 asc = cpu_mmu_idx_to_asc(mmu_idx);
162 /* 31-Bit mode */
163 if (!(env->psw.mask & PSW_MASK_64)) {
164 vaddr &= 0x7fffffff;
165 }
166 excp = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, &tec);
167 } else if (mmu_idx == MMU_REAL_IDX) {
168 /* 31-Bit mode */
169 if (!(env->psw.mask & PSW_MASK_64)) {
170 vaddr &= 0x7fffffff;
171 }
172 excp = mmu_translate_real(env, vaddr, access_type, &raddr, &prot, &tec);
173 } else {
174 g_assert_not_reached();
175 }
176
177 env->tlb_fill_exc = excp;
178 env->tlb_fill_tec = tec;
179
180 if (!excp) {
181 qemu_log_mask(CPU_LOG_MMU,
182 "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
183 __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
184 tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot,
185 mmu_idx, TARGET_PAGE_SIZE);
186 return true;
187 }
188 if (probe) {
189 return false;
190 }
191
192 /*
193 * For data accesses, ILEN will be filled in from the unwind info,
194 * within cpu_loop_exit_restore. For code accesses, retaddr == 0,
195 * and so unwinding will not occur. However, ILEN is also undefined
196 * for that case -- we choose to set ILEN = 2.
197 */
198 env->int_pgm_ilen = 2;
199 trigger_pgm_exception(env, excp);
200 cpu_loop_exit_restore(cs, retaddr);
201 }
202
do_program_interrupt(CPUS390XState * env)203 static void do_program_interrupt(CPUS390XState *env)
204 {
205 uint64_t mask, addr;
206 LowCore *lowcore;
207 int ilen = env->int_pgm_ilen;
208 bool set_trans_exc_code = false;
209 bool advance = false;
210
211 assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
212 ilen == 2 || ilen == 4 || ilen == 6);
213
214 switch (env->int_pgm_code) {
215 case PGM_PER:
216 advance = !(env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION);
217 break;
218 case PGM_ASCE_TYPE:
219 case PGM_REG_FIRST_TRANS:
220 case PGM_REG_SEC_TRANS:
221 case PGM_REG_THIRD_TRANS:
222 case PGM_SEGMENT_TRANS:
223 case PGM_PAGE_TRANS:
224 assert(env->int_pgm_code == env->tlb_fill_exc);
225 set_trans_exc_code = true;
226 break;
227 case PGM_PROTECTION:
228 assert(env->int_pgm_code == env->tlb_fill_exc);
229 set_trans_exc_code = true;
230 advance = true;
231 break;
232 case PGM_OPERATION:
233 case PGM_PRIVILEGED:
234 case PGM_EXECUTE:
235 case PGM_ADDRESSING:
236 case PGM_SPECIFICATION:
237 case PGM_DATA:
238 case PGM_FIXPT_OVERFLOW:
239 case PGM_FIXPT_DIVIDE:
240 case PGM_DEC_OVERFLOW:
241 case PGM_DEC_DIVIDE:
242 case PGM_HFP_EXP_OVERFLOW:
243 case PGM_HFP_EXP_UNDERFLOW:
244 case PGM_HFP_SIGNIFICANCE:
245 case PGM_HFP_DIVIDE:
246 case PGM_TRANS_SPEC:
247 case PGM_SPECIAL_OP:
248 case PGM_OPERAND:
249 case PGM_HFP_SQRT:
250 case PGM_PC_TRANS_SPEC:
251 case PGM_ALET_SPEC:
252 case PGM_MONITOR:
253 advance = true;
254 break;
255 }
256
257 /* advance the PSW if our exception is not nullifying */
258 if (advance) {
259 env->psw.addr += ilen;
260 }
261
262 qemu_log_mask(CPU_LOG_INT,
263 "%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
264 __func__, env->int_pgm_code, ilen, env->psw.mask,
265 env->psw.addr);
266
267 lowcore = cpu_map_lowcore(env);
268
269 /* Signal PER events with the exception. */
270 if (env->per_perc_atmid) {
271 env->int_pgm_code |= PGM_PER;
272 lowcore->per_address = cpu_to_be64(env->per_address);
273 lowcore->per_perc_atmid = cpu_to_be16(env->per_perc_atmid);
274 env->per_perc_atmid = 0;
275 }
276
277 if (set_trans_exc_code) {
278 lowcore->trans_exc_code = cpu_to_be64(env->tlb_fill_tec);
279 }
280
281 lowcore->pgm_ilen = cpu_to_be16(ilen);
282 lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
283 lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
284 lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
285 mask = be64_to_cpu(lowcore->program_new_psw.mask);
286 addr = be64_to_cpu(lowcore->program_new_psw.addr);
287 lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea);
288
289 cpu_unmap_lowcore(lowcore);
290
291 s390_cpu_set_psw(env, mask, addr);
292 }
293
do_svc_interrupt(CPUS390XState * env)294 static void do_svc_interrupt(CPUS390XState *env)
295 {
296 uint64_t mask, addr;
297 LowCore *lowcore;
298
299 lowcore = cpu_map_lowcore(env);
300
301 lowcore->svc_code = cpu_to_be16(env->int_svc_code);
302 lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
303 lowcore->svc_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
304 lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
305 mask = be64_to_cpu(lowcore->svc_new_psw.mask);
306 addr = be64_to_cpu(lowcore->svc_new_psw.addr);
307
308 cpu_unmap_lowcore(lowcore);
309
310 s390_cpu_set_psw(env, mask, addr);
311
312 /* When a PER event is pending, the PER exception has to happen
313 immediately after the SERVICE CALL one. */
314 if (env->per_perc_atmid) {
315 env->int_pgm_code = PGM_PER;
316 env->int_pgm_ilen = env->int_svc_ilen;
317 do_program_interrupt(env);
318 }
319 }
320
321 #define VIRTIO_SUBCODE_64 0x0D00
322
do_ext_interrupt(CPUS390XState * env)323 static void do_ext_interrupt(CPUS390XState *env)
324 {
325 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
326 S390CPU *cpu = env_archcpu(env);
327 uint64_t mask, addr;
328 uint16_t cpu_addr;
329 LowCore *lowcore;
330
331 if (!(env->psw.mask & PSW_MASK_EXT)) {
332 cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
333 }
334
335 lowcore = cpu_map_lowcore(env);
336
337 if ((env->pending_int & INTERRUPT_EMERGENCY_SIGNAL) &&
338 (env->cregs[0] & CR0_EMERGENCY_SIGNAL_SC)) {
339 MachineState *ms = MACHINE(qdev_get_machine());
340 unsigned int max_cpus = ms->smp.max_cpus;
341
342 lowcore->ext_int_code = cpu_to_be16(EXT_EMERGENCY);
343 cpu_addr = find_first_bit(env->emergency_signals, S390_MAX_CPUS);
344 g_assert(cpu_addr < S390_MAX_CPUS);
345 lowcore->cpu_addr = cpu_to_be16(cpu_addr);
346 clear_bit(cpu_addr, env->emergency_signals);
347 if (bitmap_empty(env->emergency_signals, max_cpus)) {
348 env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
349 }
350 } else if ((env->pending_int & INTERRUPT_EXTERNAL_CALL) &&
351 (env->cregs[0] & CR0_EXTERNAL_CALL_SC)) {
352 lowcore->ext_int_code = cpu_to_be16(EXT_EXTERNAL_CALL);
353 lowcore->cpu_addr = cpu_to_be16(env->external_call_addr);
354 env->pending_int &= ~INTERRUPT_EXTERNAL_CALL;
355 } else if ((env->pending_int & INTERRUPT_EXT_CLOCK_COMPARATOR) &&
356 (env->cregs[0] & CR0_CKC_SC)) {
357 lowcore->ext_int_code = cpu_to_be16(EXT_CLOCK_COMP);
358 lowcore->cpu_addr = 0;
359 env->pending_int &= ~INTERRUPT_EXT_CLOCK_COMPARATOR;
360 } else if ((env->pending_int & INTERRUPT_EXT_CPU_TIMER) &&
361 (env->cregs[0] & CR0_CPU_TIMER_SC)) {
362 lowcore->ext_int_code = cpu_to_be16(EXT_CPU_TIMER);
363 lowcore->cpu_addr = 0;
364 env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
365 } else if (qemu_s390_flic_has_service(flic) &&
366 (env->cregs[0] & CR0_SERVICE_SC)) {
367 uint32_t param;
368
369 param = qemu_s390_flic_dequeue_service(flic);
370 lowcore->ext_int_code = cpu_to_be16(EXT_SERVICE);
371 lowcore->ext_params = cpu_to_be32(param);
372 lowcore->cpu_addr = 0;
373 } else {
374 g_assert_not_reached();
375 }
376
377 mask = be64_to_cpu(lowcore->external_new_psw.mask);
378 addr = be64_to_cpu(lowcore->external_new_psw.addr);
379 lowcore->external_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
380 lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr);
381
382 cpu_unmap_lowcore(lowcore);
383
384 s390_cpu_set_psw(env, mask, addr);
385 }
386
do_io_interrupt(CPUS390XState * env)387 static void do_io_interrupt(CPUS390XState *env)
388 {
389 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
390 uint64_t mask, addr;
391 QEMUS390FlicIO *io;
392 LowCore *lowcore;
393
394 g_assert(env->psw.mask & PSW_MASK_IO);
395 io = qemu_s390_flic_dequeue_io(flic, env->cregs[6]);
396 g_assert(io);
397
398 lowcore = cpu_map_lowcore(env);
399
400 lowcore->subchannel_id = cpu_to_be16(io->id);
401 lowcore->subchannel_nr = cpu_to_be16(io->nr);
402 lowcore->io_int_parm = cpu_to_be32(io->parm);
403 lowcore->io_int_word = cpu_to_be32(io->word);
404 lowcore->io_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
405 lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
406 mask = be64_to_cpu(lowcore->io_new_psw.mask);
407 addr = be64_to_cpu(lowcore->io_new_psw.addr);
408
409 cpu_unmap_lowcore(lowcore);
410 g_free(io);
411
412 s390_cpu_set_psw(env, mask, addr);
413 }
414
415 typedef struct MchkExtSaveArea {
416 uint64_t vregs[32][2]; /* 0x0000 */
417 uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
418 } MchkExtSaveArea;
419 QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
420
mchk_store_vregs(CPUS390XState * env,uint64_t mcesao)421 static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
422 {
423 hwaddr len = sizeof(MchkExtSaveArea);
424 MchkExtSaveArea *sa;
425 int i;
426
427 sa = cpu_physical_memory_map(mcesao, &len, true);
428 if (!sa) {
429 return -EFAULT;
430 }
431 if (len != sizeof(MchkExtSaveArea)) {
432 cpu_physical_memory_unmap(sa, len, 1, 0);
433 return -EFAULT;
434 }
435
436 for (i = 0; i < 32; i++) {
437 sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0]);
438 sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1]);
439 }
440
441 cpu_physical_memory_unmap(sa, len, 1, len);
442 return 0;
443 }
444
do_mchk_interrupt(CPUS390XState * env)445 static void do_mchk_interrupt(CPUS390XState *env)
446 {
447 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
448 uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
449 uint64_t mask, addr, mcesao = 0;
450 LowCore *lowcore;
451 int i;
452
453 /* for now we only support channel report machine checks (floating) */
454 g_assert(env->psw.mask & PSW_MASK_MCHECK);
455 g_assert(env->cregs[14] & CR14_CHANNEL_REPORT_SC);
456
457 qemu_s390_flic_dequeue_crw_mchk(flic);
458
459 lowcore = cpu_map_lowcore(env);
460
461 /* extended save area */
462 if (mcic & MCIC_VB_VR) {
463 /* length and alignment is 1024 bytes */
464 mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
465 }
466
467 /* try to store vector registers */
468 if (!mcesao || mchk_store_vregs(env, mcesao)) {
469 mcic &= ~MCIC_VB_VR;
470 }
471
472 /* we are always in z/Architecture mode */
473 lowcore->ar_access_id = 1;
474
475 for (i = 0; i < 16; i++) {
476 lowcore->floating_pt_save_area[i] = cpu_to_be64(*get_freg(env, i));
477 lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]);
478 lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]);
479 lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]);
480 }
481 lowcore->prefixreg_save_area = cpu_to_be32(env->psa);
482 lowcore->fpt_creg_save_area = cpu_to_be32(env->fpc);
483 lowcore->tod_progreg_save_area = cpu_to_be32(env->todpr);
484 lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
485 lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
486
487 lowcore->mcic = cpu_to_be64(mcic);
488 lowcore->mcck_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
489 lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
490 mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
491 addr = be64_to_cpu(lowcore->mcck_new_psw.addr);
492
493 cpu_unmap_lowcore(lowcore);
494
495 s390_cpu_set_psw(env, mask, addr);
496 }
497
s390_cpu_do_interrupt(CPUState * cs)498 void s390_cpu_do_interrupt(CPUState *cs)
499 {
500 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
501 S390CPU *cpu = S390_CPU(cs);
502 CPUS390XState *env = &cpu->env;
503 bool stopped = false;
504
505 qemu_log_mask(CPU_LOG_INT, "%s: %d at psw=%" PRIx64 ":%" PRIx64 "\n",
506 __func__, cs->exception_index, env->psw.mask, env->psw.addr);
507
508 try_deliver:
509 /* handle machine checks */
510 if (cs->exception_index == -1 && s390_cpu_has_mcck_int(cpu)) {
511 cs->exception_index = EXCP_MCHK;
512 }
513 /* handle external interrupts */
514 if (cs->exception_index == -1 && s390_cpu_has_ext_int(cpu)) {
515 cs->exception_index = EXCP_EXT;
516 }
517 /* handle I/O interrupts */
518 if (cs->exception_index == -1 && s390_cpu_has_io_int(cpu)) {
519 cs->exception_index = EXCP_IO;
520 }
521 /* RESTART interrupt */
522 if (cs->exception_index == -1 && s390_cpu_has_restart_int(cpu)) {
523 cs->exception_index = EXCP_RESTART;
524 }
525 /* STOP interrupt has least priority */
526 if (cs->exception_index == -1 && s390_cpu_has_stop_int(cpu)) {
527 cs->exception_index = EXCP_STOP;
528 }
529
530 switch (cs->exception_index) {
531 case EXCP_PGM:
532 do_program_interrupt(env);
533 break;
534 case EXCP_SVC:
535 do_svc_interrupt(env);
536 break;
537 case EXCP_EXT:
538 do_ext_interrupt(env);
539 break;
540 case EXCP_IO:
541 do_io_interrupt(env);
542 break;
543 case EXCP_MCHK:
544 do_mchk_interrupt(env);
545 break;
546 case EXCP_RESTART:
547 do_restart_interrupt(env);
548 break;
549 case EXCP_STOP:
550 do_stop_interrupt(env);
551 stopped = true;
552 break;
553 }
554
555 if (cs->exception_index != -1 && !stopped) {
556 /* check if there are more pending interrupts to deliver */
557 cs->exception_index = -1;
558 goto try_deliver;
559 }
560 cs->exception_index = -1;
561
562 /* we might still have pending interrupts, but not deliverable */
563 if (!env->pending_int && !qemu_s390_flic_has_any(flic)) {
564 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
565 }
566
567 /* WAIT PSW during interrupt injection or STOP interrupt */
568 if ((env->psw.mask & PSW_MASK_WAIT) || stopped) {
569 /* don't trigger a cpu_loop_exit(), use an interrupt instead */
570 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
571 } else if (cs->halted) {
572 /* unhalt if we had a WAIT PSW somewhere in our injection chain */
573 s390_cpu_unhalt(cpu);
574 }
575 }
576
s390_cpu_exec_interrupt(CPUState * cs,int interrupt_request)577 bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
578 {
579 if (interrupt_request & CPU_INTERRUPT_HARD) {
580 S390CPU *cpu = S390_CPU(cs);
581 CPUS390XState *env = &cpu->env;
582
583 if (env->ex_value) {
584 /* Execution of the target insn is indivisible from
585 the parent EXECUTE insn. */
586 return false;
587 }
588 if (s390_cpu_has_int(cpu)) {
589 s390_cpu_do_interrupt(cs);
590 return true;
591 }
592 if (env->psw.mask & PSW_MASK_WAIT) {
593 /* Woken up because of a floating interrupt but it has already
594 * been delivered. Go back to sleep. */
595 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
596 }
597 }
598 return false;
599 }
600
s390x_cpu_debug_excp_handler(CPUState * cs)601 void s390x_cpu_debug_excp_handler(CPUState *cs)
602 {
603 S390CPU *cpu = S390_CPU(cs);
604 CPUS390XState *env = &cpu->env;
605 CPUWatchpoint *wp_hit = cs->watchpoint_hit;
606
607 if (wp_hit && wp_hit->flags & BP_CPU) {
608 /* FIXME: When the storage-alteration-space control bit is set,
609 the exception should only be triggered if the memory access
610 is done using an address space with the storage-alteration-event
611 bit set. We have no way to detect that with the current
612 watchpoint code. */
613 cs->watchpoint_hit = NULL;
614
615 env->per_address = env->psw.addr;
616 env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
617 /* FIXME: We currently no way to detect the address space used
618 to trigger the watchpoint. For now just consider it is the
619 current default ASC. This turn to be true except when MVCP
620 and MVCS instrutions are not used. */
621 env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
622
623 /*
624 * Remove all watchpoints to re-execute the code. A PER exception
625 * will be triggered, it will call s390_cpu_set_psw which will
626 * recompute the watchpoints.
627 */
628 cpu_watchpoint_remove_all(cs, BP_CPU);
629 cpu_loop_exit_noexc(cs);
630 }
631 }
632
s390x_cpu_do_unaligned_access(CPUState * cs,vaddr addr,MMUAccessType access_type,int mmu_idx,uintptr_t retaddr)633 void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
634 MMUAccessType access_type,
635 int mmu_idx, uintptr_t retaddr)
636 {
637 do_unaligned_access(cs, retaddr);
638 }
639
640 static G_NORETURN
monitor_event(CPUS390XState * env,uint64_t monitor_code,uint8_t monitor_class,uintptr_t ra)641 void monitor_event(CPUS390XState *env,
642 uint64_t monitor_code,
643 uint8_t monitor_class, uintptr_t ra)
644 {
645 /* Store the Monitor Code and the Monitor Class Number into the lowcore */
646 stq_phys(env_cpu(env)->as,
647 env->psa + offsetof(LowCore, monitor_code), monitor_code);
648 stw_phys(env_cpu(env)->as,
649 env->psa + offsetof(LowCore, mon_class_num), monitor_class);
650
651 tcg_s390_program_interrupt(env, PGM_MONITOR, ra);
652 }
653
HELPER(monitor_call)654 void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code,
655 uint32_t monitor_class)
656 {
657 g_assert(monitor_class <= 0xf);
658
659 if (env->cregs[8] & (0x8000 >> monitor_class)) {
660 monitor_event(env, monitor_code, monitor_class, GETPC());
661 }
662 }
663
664 #endif /* !CONFIG_USER_ONLY */
665