target/s390x: Emulate CVDG
[qemu/kevin.git] / target / s390x / tcg / excp_helper.c
blobb875bf14e561d87be8c7db01aec722cae1035522
1 /*
2 * s390x exception / interrupt helpers
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2011 Alexander Graf
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.
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.
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/>.
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
36 G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env,
37 uint32_t code, uintptr_t ra)
39 CPUState *cs = env_cpu(env);
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);
48 G_NORETURN void tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
49 uintptr_t ra)
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
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);
62 tcg_s390_program_interrupt(env, PGM_DATA, ra);
65 G_NORETURN void tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc,
66 uintptr_t ra)
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
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);
80 void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
82 tcg_s390_data_exception(env, dxc, GETPC());
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.
90 static G_NORETURN
91 void do_unaligned_access(CPUState *cs, uintptr_t retaddr)
93 S390CPU *cpu = S390_CPU(cs);
94 CPUS390XState *env = &cpu->env;
96 tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
99 #if defined(CONFIG_USER_ONLY)
101 void s390_cpu_do_interrupt(CPUState *cs)
103 cs->exception_index = -1;
106 void s390_cpu_record_sigsegv(CPUState *cs, vaddr address,
107 MMUAccessType access_type,
108 bool maperr, uintptr_t retaddr)
110 S390CPU *cpu = S390_CPU(cs);
112 trigger_pgm_exception(&cpu->env, maperr ? PGM_ADDRESSING : PGM_PROTECTION);
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().
119 cpu->env.__excp_addr = address & TARGET_PAGE_MASK;
120 cpu_loop_exit_restore(cs, retaddr);
123 void s390_cpu_record_sigbus(CPUState *cs, vaddr address,
124 MMUAccessType access_type, uintptr_t retaddr)
126 do_unaligned_access(cs, retaddr);
129 #else /* !CONFIG_USER_ONLY */
131 static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
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();
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)
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;
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);
158 vaddr = address;
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;
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;
172 excp = mmu_translate_real(env, vaddr, access_type, &raddr, &prot, &tec);
173 } else {
174 g_assert_not_reached();
177 env->tlb_fill_exc = excp;
178 env->tlb_fill_tec = tec;
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;
188 if (probe) {
189 return false;
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.
198 env->int_pgm_ilen = 2;
199 trigger_pgm_exception(env, excp);
200 cpu_loop_exit_restore(cs, retaddr);
203 static void do_program_interrupt(CPUS390XState *env)
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;
211 assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
212 ilen == 2 || ilen == 4 || ilen == 6);
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;
257 /* advance the PSW if our exception is not nullifying */
258 if (advance) {
259 env->psw.addr += ilen;
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);
267 lowcore = cpu_map_lowcore(env);
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;
277 if (set_trans_exc_code) {
278 lowcore->trans_exc_code = cpu_to_be64(env->tlb_fill_tec);
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);
289 cpu_unmap_lowcore(lowcore);
291 s390_cpu_set_psw(env, mask, addr);
294 static void do_svc_interrupt(CPUS390XState *env)
296 uint64_t mask, addr;
297 LowCore *lowcore;
299 lowcore = cpu_map_lowcore(env);
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);
308 cpu_unmap_lowcore(lowcore);
310 s390_cpu_set_psw(env, mask, addr);
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);
321 #define VIRTIO_SUBCODE_64 0x0D00
323 static void do_ext_interrupt(CPUS390XState *env)
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;
331 if (!(env->psw.mask & PSW_MASK_EXT)) {
332 cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
335 lowcore = cpu_map_lowcore(env);
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;
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;
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;
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();
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);
382 cpu_unmap_lowcore(lowcore);
384 s390_cpu_set_psw(env, mask, addr);
387 static void do_io_interrupt(CPUS390XState *env)
389 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
390 uint64_t mask, addr;
391 QEMUS390FlicIO *io;
392 LowCore *lowcore;
394 g_assert(env->psw.mask & PSW_MASK_IO);
395 io = qemu_s390_flic_dequeue_io(flic, env->cregs[6]);
396 g_assert(io);
398 lowcore = cpu_map_lowcore(env);
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);
409 cpu_unmap_lowcore(lowcore);
410 g_free(io);
412 s390_cpu_set_psw(env, mask, addr);
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);
421 static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
423 hwaddr len = sizeof(MchkExtSaveArea);
424 MchkExtSaveArea *sa;
425 int i;
427 sa = cpu_physical_memory_map(mcesao, &len, true);
428 if (!sa) {
429 return -EFAULT;
431 if (len != sizeof(MchkExtSaveArea)) {
432 cpu_physical_memory_unmap(sa, len, 1, 0);
433 return -EFAULT;
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]);
441 cpu_physical_memory_unmap(sa, len, 1, len);
442 return 0;
445 static void do_mchk_interrupt(CPUS390XState *env)
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;
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);
457 qemu_s390_flic_dequeue_crw_mchk(flic);
459 lowcore = cpu_map_lowcore(env);
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;
467 /* try to store vector registers */
468 if (!mcesao || mchk_store_vregs(env, mcesao)) {
469 mcic &= ~MCIC_VB_VR;
472 /* we are always in z/Architecture mode */
473 lowcore->ar_access_id = 1;
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]);
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);
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);
493 cpu_unmap_lowcore(lowcore);
495 s390_cpu_set_psw(env, mask, addr);
498 void s390_cpu_do_interrupt(CPUState *cs)
500 QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
501 S390CPU *cpu = S390_CPU(cs);
502 CPUS390XState *env = &cpu->env;
503 bool stopped = false;
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);
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;
513 /* handle external interrupts */
514 if (cs->exception_index == -1 && s390_cpu_has_ext_int(cpu)) {
515 cs->exception_index = EXCP_EXT;
517 /* handle I/O interrupts */
518 if (cs->exception_index == -1 && s390_cpu_has_io_int(cpu)) {
519 cs->exception_index = EXCP_IO;
521 /* RESTART interrupt */
522 if (cs->exception_index == -1 && s390_cpu_has_restart_int(cpu)) {
523 cs->exception_index = EXCP_RESTART;
525 /* STOP interrupt has least priority */
526 if (cs->exception_index == -1 && s390_cpu_has_stop_int(cpu)) {
527 cs->exception_index = EXCP_STOP;
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;
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;
560 cs->exception_index = -1;
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;
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);
577 bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
579 if (interrupt_request & CPU_INTERRUPT_HARD) {
580 S390CPU *cpu = S390_CPU(cs);
581 CPUS390XState *env = &cpu->env;
583 if (env->ex_value) {
584 /* Execution of the target insn is indivisible from
585 the parent EXECUTE insn. */
586 return false;
588 if (s390_cpu_has_int(cpu)) {
589 s390_cpu_do_interrupt(cs);
590 return true;
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);
598 return false;
601 void s390x_cpu_debug_excp_handler(CPUState *cs)
603 S390CPU *cpu = S390_CPU(cs);
604 CPUS390XState *env = &cpu->env;
605 CPUWatchpoint *wp_hit = cs->watchpoint_hit;
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;
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;
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.
628 cpu_watchpoint_remove_all(cs, BP_CPU);
629 cpu_loop_exit_noexc(cs);
633 void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
634 MMUAccessType access_type,
635 int mmu_idx, uintptr_t retaddr)
637 do_unaligned_access(cs, retaddr);
640 static G_NORETURN
641 void monitor_event(CPUS390XState *env,
642 uint64_t monitor_code,
643 uint8_t monitor_class, uintptr_t ra)
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);
651 tcg_s390_program_interrupt(env, PGM_MONITOR, ra);
654 void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code,
655 uint32_t monitor_class)
657 g_assert(monitor_class <= 0xf);
659 if (env->cregs[8] & (0x8000 >> monitor_class)) {
660 monitor_event(env, monitor_code, monitor_class, GETPC());
664 #endif /* !CONFIG_USER_ONLY */