xref: /openbmc/qemu/target/s390x/tcg/excp_helper.c (revision a6a33760)
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