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