static void do_program_interrupt(CPUS390XState *env) { uint64_t mask, addr; LowCore *lowcore; int ilen = env->int_pgm_ilen; switch (ilen) { case ILEN_LATER: ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); break; case ILEN_LATER_INC: ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); env->psw.addr += ilen; break; default: assert(ilen == 2 || ilen == 4 || ilen == 6); } qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n", __func__, env->int_pgm_code, ilen); lowcore = cpu_map_lowcore(env); /* Signal PER events with the exception. */ if (env->per_perc_atmid) { env->int_pgm_code |= PGM_PER; lowcore->per_address = cpu_to_be64(env->per_address); lowcore->per_perc_atmid = cpu_to_be16(env->per_perc_atmid); env->per_perc_atmid = 0; } lowcore->pgm_ilen = cpu_to_be16(ilen); lowcore->pgm_code = cpu_to_be16(env->int_pgm_code); lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env)); lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr); mask = be64_to_cpu(lowcore->program_new_psw.mask); addr = be64_to_cpu(lowcore->program_new_psw.addr); lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea); cpu_unmap_lowcore(lowcore); DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__, env->int_pgm_code, ilen, env->psw.mask, env->psw.addr); load_psw(env, mask, addr); }
void HELPER(per_check_exception)(CPUS390XState *env) { CPUState *cs = CPU(s390_env_get_cpu(env)); if (env->per_perc_atmid) { env->int_pgm_code = PGM_PER; env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, env->per_address)); cs->exception_index = EXCP_PGM; cpu_loop_exit(cs); } }
static void do_program_interrupt(CPUS390XState *env) { uint64_t mask, addr; LowCore *lowcore; int ilen = env->int_pgm_ilen; switch (ilen) { case ILEN_LATER: ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); break; case ILEN_LATER_INC: ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); env->psw.addr += ilen; break; default: assert(ilen == 2 || ilen == 4 || ilen == 6); } qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n", __func__, env->int_pgm_code, ilen); lowcore = cpu_map_lowcore(env); lowcore->pgm_ilen = cpu_to_be16(ilen); lowcore->pgm_code = cpu_to_be16(env->int_pgm_code); lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env)); lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr); mask = be64_to_cpu(lowcore->program_new_psw.mask); addr = be64_to_cpu(lowcore->program_new_psw.addr); cpu_unmap_lowcore(lowcore); DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__, env->int_pgm_code, ilen, env->psw.mask, env->psw.addr); load_psw(env, mask, addr); }
/* Raise an exception dynamically from a helper function. */ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr) { int t; env->exception_index = EXCP_PGM; env->int_pgm_code = excp; /* Use the (ultimate) callers address to find the insn that trapped. */ cpu_restore_state(env, retaddr); /* Advance past the insn. */ t = cpu_ldub_code(env, env->psw.addr); env->int_pgm_ilen = t = get_ilen(t); env->psw.addr += 2 * t; cpu_loop_exit(env); }
void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr) { if ((env->cregs[9] & PER_CR9_EVENT_IFETCH) && get_per_in_range(env, addr)) { env->per_address = addr; env->per_perc_atmid = PER_CODE_EVENT_IFETCH | get_per_atmid(env); /* If the instruction has to be nullified, trigger the exception immediately. */ if (env->cregs[9] & PER_CR9_EVENT_NULLIFICATION) { CPUState *cs = CPU(s390_env_get_cpu(env)); env->int_pgm_code = PGM_PER; env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, addr)); cs->exception_index = EXCP_PGM; cpu_loop_exit(cs); } } }