Beispiel #1
0
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);
}
Beispiel #2
0
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);
    }
}
Beispiel #3
0
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);
}
Beispiel #4
0
/* 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);
}
Beispiel #5
0
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);
        }
    }
}