Example #1
0
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
{
    CRW crw;
    uint64_t addr;
    int cc;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        return;
    }

    cc = css_do_stcrw(&crw);
    /* 0 - crw stored, 1 - zeroes stored */

    if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
        setcc(cpu, cc);
    } else {
        if (cc == 0) {
            /* Write failed: requeue CRW since STCRW is suppressing */
            css_undo_stcrw(&crw);
        }
        s390_cpu_virt_mem_handle_exc(cpu, ra);
    }
}
Example #2
0
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    uint64_t addr;
    int cc;
    SCHIB schib;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        /*
         * As operand exceptions have a lower priority than access exceptions,
         * we check whether the memory area is writeable (injecting the
         * access execption if it is not) first.
         */
        if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
            program_interrupt(env, PGM_OPERAND, 2);
        }
        return;
    }
    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;
        }
    }
    if (cc != 3) {
        if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
                                    sizeof(schib)) != 0) {
            return;
        }
    } else {
        /* Access exceptions have a higher priority than cc3 */
        if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
            return;
        }
    }
    setcc(cpu, cc);
}
Example #3
0
int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
{
    CPUS390XState *env = &cpu->env;
    int cssid, ssid, schid, m;
    SubchDev *sch;
    IRB irb;
    uint64_t addr;
    int cc, irb_len;
    uint8_t ar;

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        return -EIO;
    }
    trace_ioinst_sch_id("tsch", cssid, ssid, schid);
    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        return -EIO;
    }

    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
    } else {
        cc = 3;
    }
    /* 0 - status pending, 1 - not status pending, 3 - not operational */
    if (cc != 3) {
        if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
            s390_cpu_virt_mem_handle_exc(cpu, ra);
            return -EFAULT;
        }
        css_do_tsch_update_subch(sch);
    } else {
        irb_len = sizeof(irb) - sizeof(irb.emw);
        /* Access exceptions have a higher priority than cc3 */
        if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
            s390_cpu_virt_mem_handle_exc(cpu, ra);
            return -EFAULT;
        }
    }

    setcc(cpu, cc);
    return 0;
}