示例#1
0
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
{
    uint64_t addr =  env->regs[r1];
    uint64_t subcode = env->regs[r3];

    if (env->psw.mask & PSW_MASK_PSTATE) {
        program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC);
        return;
    }

    if ((subcode & ~0x0ffffULL) || (subcode > 6)) {
        program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
        return;
    }

    switch (subcode) {
    case 0:
        modified_clear_reset(s390_env_get_cpu(env));
        break;
    case 1:
        load_normal_reset(s390_env_get_cpu(env));
        break;
    case 5:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            return;
        }
        env->regs[r1+1] = DIAG_308_RC_INVALID;
        return;
    case 6:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            return;
        }
        env->regs[r1+1] = DIAG_308_RC_NO_CONF;
        return;
    default:
        hw_error("Unhandled diag308 subcode %" PRIx64, subcode);
        break;
    }
}
示例#2
0
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
{
    uint64_t addr =  env->regs[r1];
    uint64_t subcode = env->regs[r3];
    IplParameterBlock *iplb;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC);
        return;
    }

    if ((subcode & ~0x0ffffULL) || (subcode > 6)) {
        program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
        return;
    }

    switch (subcode) {
    case 0:
        modified_clear_reset(s390_env_get_cpu(env));
        if (tcg_enabled()) {
            cpu_loop_exit(CPU(s390_env_get_cpu(env)));
        }
        break;
    case 1:
        load_normal_reset(s390_env_get_cpu(env));
        if (tcg_enabled()) {
            cpu_loop_exit(CPU(s390_env_get_cpu(env)));
        }
        break;
    case 3:
        s390_reipl_request();
        if (tcg_enabled()) {
            cpu_loop_exit(CPU(s390_env_get_cpu(env)));
        }
        break;
    case 5:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            return;
        }
        if (!address_space_access_valid(&address_space_memory, addr,
                                        sizeof(IplParameterBlock), false)) {
            program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
            return;
        }
        iplb = g_malloc0(sizeof(struct IplParameterBlock));
        cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock));
        if (!s390_ipl_update_diag308(iplb)) {
            env->regs[r1 + 1] = DIAG_308_RC_OK;
        } else {
            env->regs[r1 + 1] = DIAG_308_RC_INVALID;
        }
        g_free(iplb);
        return;
    case 6:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            return;
        }
        if (!address_space_access_valid(&address_space_memory, addr,
                                        sizeof(IplParameterBlock), true)) {
            program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
            return;
        }
        iplb = s390_ipl_get_iplb();
        if (iplb) {
            cpu_physical_memory_write(addr, iplb,
                                      sizeof(struct IplParameterBlock));
            env->regs[r1 + 1] = DIAG_308_RC_OK;
        } else {
            env->regs[r1 + 1] = DIAG_308_RC_NO_CONF;
        }
        return;
    default:
        hw_error("Unhandled diag308 subcode %" PRIx64, subcode);
        break;
    }
}