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