示例#1
0
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
{
    CRW *crw;
    uint64_t addr;
    int cc;
    hwaddr len = sizeof(*crw);
    CPUS390XState *env = &cpu->env;

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    crw = s390_cpu_physical_memory_map(env, addr, &len, 1);
    if (!crw || len != sizeof(*crw)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        goto out;
    }
    cc = css_do_stcrw(crw);
    /* 0 - crw stored, 1 - zeroes stored */
    setcc(cpu, cc);

out:
    s390_cpu_physical_memory_unmap(env, crw, len, 1);
}
示例#2
0
int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    ORB *orig_orb, orb;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    hwaddr len = sizeof(*orig_orb);

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return -EIO;
    }
    orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0);
    if (!orig_orb || len != sizeof(*orig_orb)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        cc = -EIO;
        goto out;
    }
    copy_orb_from_guest(&orb, orig_orb);
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_orb_valid(&orb)) {
        program_interrupt(env, PGM_OPERAND, 2);
        cc = -EIO;
        goto out;
    }
    trace_ioinst_sch_id("ssch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_ssch(sch, &orb);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }

out:
    s390_cpu_physical_memory_unmap(env, orig_orb, len, 0);
    return cc;
}
示例#3
0
void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    SCHIB *schib;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    hwaddr len = sizeof(*schib);
    CPUS390XState *env = &cpu->env;

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    schib = s390_cpu_physical_memory_map(env, addr, &len, 0);
    if (!schib || len != sizeof(*schib)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        goto out;
    }
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_schib_valid(schib)) {
        program_interrupt(env, PGM_OPERAND, 2);
        goto out;
    }
    trace_ioinst_sch_id("msch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_msch(sch, schib);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }
    setcc(cpu, cc);

out:
    s390_cpu_physical_memory_unmap(env, schib, len, 0);
}
示例#4
0
int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    uint64_t addr;
    int cc;
    SCHIB *schib;
    hwaddr len = sizeof(*schib);

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return -EIO;
    }
    schib = s390_cpu_physical_memory_map(env, addr, &len, 1);
    if (!schib || len != sizeof(*schib)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        cc = -EIO;
        goto out;
    }

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        program_interrupt(env, PGM_OPERAND, 2);
        cc = -EIO;
        goto out;
    }
    trace_ioinst_sch_id("stsch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch) {
        if (css_subch_visible(sch)) {
            css_do_stsch(sch, schib);
            cc = 0;
        } else {
            /* Indicate no more subchannels in this css/ss */
            cc = 3;
        }
    } else {
        if (css_schid_final(m, cssid, ssid, schid)) {
            cc = 3; /* No more subchannels in this css/ss */
        } else {
            /* Store an empty schib. */
            memset(schib, 0, sizeof(*schib));
            cc = 0;
        }
    }
out:
    s390_cpu_physical_memory_unmap(env, schib, len, 1);
    return cc;
}
示例#5
0
int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    IRB *irb;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    hwaddr len = sizeof(*irb);

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        program_interrupt(env, PGM_OPERAND, 2);
        return -EIO;
    }
    trace_ioinst_sch_id("tsch", cssid, ssid, schid);
    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return -EIO;
    }
    irb = s390_cpu_physical_memory_map(env, addr, &len, 1);
    if (!irb || len != sizeof(*irb)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        cc = -EIO;
        goto out;
    }
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_tsch(sch, irb);
        /* 0 - status pending, 1 - not status pending */
        cc = ret;
    } else {
        cc = 3;
    }
out:
    s390_cpu_physical_memory_unmap(env, irb, sizeof(*irb), 1);
    return cc;
}