Commit 718757ec authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20171020' into staging



The last big chunk of s390x changes:
- (experimental) smp support under tcg
- provide the virtio-input devices for virtio-ccw
- improve error handling in the css code
- enable some simple virtio tests for s390x
- low-address protection in tcg
- some more cleanups and fixes

# gpg: Signature made Fri 20 Oct 2017 12:49:22 BST
# gpg:                using RSA key 0xDECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>"
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20171020: (46 commits)
  s390x/tcg: low-address protection support
  accel/tcg: allow to invalidate a write TLB entry immediately
  tests: Enable the very simple virtio tests on s390x, too
  libqtest: Add qtest_[v]startf()
  s390x: refactor error handling for MSCH handler
  s390x: refactor error handling for HSCH handler
  s390x: refactor error handling for CSCH handler
  s390x: refactor error handling for XSCH handler
  s390x: improve error handling for SSCH and RSCH
  s390x/css: IO instr handler ending control
  s390x: move s390x_new_cpu() into board code
  s390x: fix cpu object referrence leak in s390x_new_cpu()
  s390x/event-facility: variable-length event masks
  s390x/MAINTAINERS: add mailing list
  virtio-ccw: Add the virtio-input devices for CCW bus
  target/s390x: special handling when starting a CPU with WAIT PSW
  s390x/tcg: refactor stfl(e) to use s390_get_feat_block()
  s390x/tcg: unlock NMI
  s390x/cpumodel: allow to enable SENSE RUNNING STATUS for qemu
  s390x/tcg: switch to new SIGP handling code
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 27825bc9 2bcf0183
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ S: Maintained
F: target/s390x/
F: hw/s390x/
F: disas/s390.c
L: qemu-s390x@nongnu.org

SH4
M: Aurelien Jarno <aurelien@aurel32.net>
@@ -303,12 +304,14 @@ F: target/s390x/kvm_s390x.h
F: target/s390x/kvm-stub.c
F: target/s390x/ioinst.[ch]
F: target/s390x/machine.c
F: target/s390x/sigp.c
F: hw/intc/s390_flic.c
F: hw/intc/s390_flic_kvm.c
F: include/hw/s390x/s390_flic.h
F: gdb-xml/s390*.xml
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org

X86
M: Paolo Bonzini <pbonzini@redhat.com>
@@ -807,6 +810,7 @@ F: pc-bios/s390-ccw.img
F: default-configs/s390x-softmmu.mak
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org

UniCore32 Machines
-------------
@@ -1031,6 +1035,7 @@ F: hw/vfio/ccw.c
F: hw/s390x/s390-ccw.c
F: include/hw/s390x/s390-ccw.h
T: git git://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org

vhost
M: Michael S. Tsirkin <mst@redhat.com>
@@ -1074,6 +1079,7 @@ S: Supported
F: hw/s390x/virtio-ccw.[hc]
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org

virtio-input
M: Gerd Hoffmann <kraxel@redhat.com>
@@ -1717,6 +1723,7 @@ M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: tcg/s390/
F: disas/s390.c
L: qemu-s390x@nongnu.org

SPARC target
S: Odd Fixes
+4 −1
Original line number Diff line number Diff line
@@ -694,6 +694,9 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
        } else {
            tn.addr_write = address;
        }
        if (prot & PAGE_WRITE_INV) {
            tn.addr_write |= TLB_INVALID_MASK;
        }
    }

    /* Pairs with flag setting in tlb_reset_dirty_range */
@@ -978,7 +981,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
        if (!VICTIM_TLB_HIT(addr_write, addr)) {
            tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
        }
        tlb_addr = tlbe->addr_write;
        tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
    }

    /* Check notdirty */
+2 −2
Original line number Diff line number Diff line
@@ -285,7 +285,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
        if (!VICTIM_TLB_HIT(addr_write, addr)) {
            tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
        }
        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
        tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
    }

    /* Handle an IO access.  */
@@ -361,7 +361,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
        if (!VICTIM_TLB_HIT(addr_write, addr)) {
            tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
        }
        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
        tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
    }

    /* Handle an IO access.  */
+50 −123
Original line number Diff line number Diff line
@@ -488,7 +488,7 @@ int css_create_css_image(uint8_t cssid, bool default_image)
    if (channel_subsys.css[cssid]) {
        return -EBUSY;
    }
    channel_subsys.css[cssid] = g_malloc0(sizeof(CssImage));
    channel_subsys.css[cssid] = g_new0(CssImage, 1);
    if (default_image) {
        channel_subsys.default_cssid = cssid;
    }
@@ -1181,12 +1181,11 @@ static void sch_handle_start_func_virtual(SubchDev *sch)

}

static int sch_handle_start_func_passthrough(SubchDev *sch)
static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
{

    PMCW *p = &sch->curr_status.pmcw;
    SCSW *s = &sch->curr_status.scsw;
    int ret;

    ORB *orb = &sch->orb;
    if (!(s->ctrl & SCSW_ACTL_SUSP)) {
@@ -1200,31 +1199,12 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
     */
    if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
        !(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
        return -EINVAL;
        warn_report("vfio-ccw requires PFCH and C64 flags set");
        sch_gen_unit_exception(sch);
        css_inject_io_interrupt(sch);
        return IOINST_CC_EXPECTED;
    }

    ret = s390_ccw_cmd_request(orb, s, sch->driver_data);
    switch (ret) {
    /* Currently we don't update control block and just return the cc code. */
    case 0:
        break;
    case -EBUSY:
        break;
    case -ENODEV:
        break;
    case -EACCES:
        /* Let's reflect an inaccessible host device by cc 3. */
        ret = -ENODEV;
        break;
    default:
       /*
        * All other return codes will trigger a program check,
        * or set cc to 1.
        */
       break;
    };

    return ret;
    return s390_ccw_cmd_request(sch);
}

/*
@@ -1233,7 +1213,7 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
 * read/writes) asynchronous later on if we start supporting more than
 * our current very simple devices.
 */
int do_subchannel_work_virtual(SubchDev *sch)
IOInstEnding do_subchannel_work_virtual(SubchDev *sch)
{

    SCSW *s = &sch->curr_status.scsw;
@@ -1245,44 +1225,35 @@ int do_subchannel_work_virtual(SubchDev *sch)
    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
        /* Triggered by both ssch and rsch. */
        sch_handle_start_func_virtual(sch);
    } else {
        /* Cannot happen. */
        return 0;
    }
    css_inject_io_interrupt(sch);
    return 0;
    /* inst must succeed if this func is called */
    return IOINST_CC_EXPECTED;
}

int do_subchannel_work_passthrough(SubchDev *sch)
IOInstEnding do_subchannel_work_passthrough(SubchDev *sch)
{
    int ret;
    SCSW *s = &sch->curr_status.scsw;

    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
        /* TODO: Clear handling */
        sch_handle_clear_func(sch);
        ret = 0;
    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
        /* TODO: Halt handling */
        sch_handle_halt_func(sch);
        ret = 0;
    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
        ret = sch_handle_start_func_passthrough(sch);
    } else {
        /* Cannot happen. */
        return -ENODEV;
        return sch_handle_start_func_passthrough(sch);
    }

    return ret;
    return IOINST_CC_EXPECTED;
}

static int do_subchannel_work(SubchDev *sch)
static IOInstEnding do_subchannel_work(SubchDev *sch)
{
    if (sch->do_subchannel_work) {
        return sch->do_subchannel_work(sch);
    } else {
        return -EINVAL;
    if (!sch->do_subchannel_work) {
        return IOINST_CC_STATUS_PRESENT;
    }
    g_assert(sch->curr_status.scsw.ctrl & SCSW_CTRL_MASK_FCTL);
    return sch->do_subchannel_work(sch);
}

static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
@@ -1376,28 +1347,24 @@ static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
    }
}

int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    uint16_t oldflags;
    int ret;
    SCHIB schib;

    if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_DNV)) {
        ret = 0;
        goto out;
        return IOINST_CC_EXPECTED;
    }

    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
        ret = -EINPROGRESS;
        goto out;
        return IOINST_CC_STATUS_PRESENT;
    }

    if (s->ctrl &
        (SCSW_FCTL_START_FUNC|SCSW_FCTL_HALT_FUNC|SCSW_FCTL_CLEAR_FUNC)) {
        ret = -EBUSY;
        goto out;
        return IOINST_CC_BUSY;
    }

    copy_schib_from_guest(&schib, orig_schib);
@@ -1424,27 +1391,20 @@ int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
        && (p->flags & PMCW_FLAGS_MASK_ENA) == 0) {
        sch->disable_cb(sch);
    }

    ret = 0;

out:
    return ret;
    return IOINST_CC_EXPECTED;
}

int css_do_xsch(SubchDev *sch)
IOInstEnding css_do_xsch(SubchDev *sch)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    int ret;

    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
        ret = -ENODEV;
        goto out;
        return IOINST_CC_NOT_OPERATIONAL;
    }

    if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
        ret = -EINPROGRESS;
        goto out;
        return IOINST_CC_STATUS_PRESENT;
    }

    if (!(s->ctrl & SCSW_CTRL_MASK_FCTL) ||
@@ -1452,8 +1412,7 @@ int css_do_xsch(SubchDev *sch)
        (!(s->ctrl &
           (SCSW_ACTL_RESUME_PEND | SCSW_ACTL_START_PEND | SCSW_ACTL_SUSP))) ||
        (s->ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
        ret = -EBUSY;
        goto out;
        return IOINST_CC_BUSY;
    }

    /* Cancel the current operation. */
@@ -1465,56 +1424,43 @@ int css_do_xsch(SubchDev *sch)
    sch->last_cmd_valid = false;
    s->dstat = 0;
    s->cstat = 0;
    ret = 0;

out:
    return ret;
    return IOINST_CC_EXPECTED;
}

int css_do_csch(SubchDev *sch)
IOInstEnding css_do_csch(SubchDev *sch)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    int ret;

    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
        ret = -ENODEV;
        goto out;
        return IOINST_CC_NOT_OPERATIONAL;
    }

    /* Trigger the clear function. */
    s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;

    do_subchannel_work(sch);
    ret = 0;

out:
    return ret;
    return do_subchannel_work(sch);
}

int css_do_hsch(SubchDev *sch)
IOInstEnding css_do_hsch(SubchDev *sch)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    int ret;

    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
        ret = -ENODEV;
        goto out;
        return IOINST_CC_NOT_OPERATIONAL;
    }

    if (((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_STATUS_PEND) ||
        (s->ctrl & (SCSW_STCTL_PRIMARY |
                    SCSW_STCTL_SECONDARY |
                    SCSW_STCTL_ALERT))) {
        ret = -EINPROGRESS;
        goto out;
        return IOINST_CC_STATUS_PRESENT;
    }

    if (s->ctrl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
        ret = -EBUSY;
        goto out;
        return IOINST_CC_BUSY;
    }

    /* Trigger the halt function. */
@@ -1527,11 +1473,7 @@ int css_do_hsch(SubchDev *sch)
    }
    s->ctrl |= SCSW_ACTL_HALT_PEND;

    do_subchannel_work(sch);
    ret = 0;

out:
    return ret;
    return do_subchannel_work(sch);
}

static void css_update_chnmon(SubchDev *sch)
@@ -1569,27 +1511,23 @@ static void css_update_chnmon(SubchDev *sch)
    }
}

int css_do_ssch(SubchDev *sch, ORB *orb)
IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    int ret;

    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
        ret = -ENODEV;
        goto out;
        return IOINST_CC_NOT_OPERATIONAL;
    }

    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
        ret = -EINPROGRESS;
        goto out;
        return IOINST_CC_STATUS_PRESENT;
    }

    if (s->ctrl & (SCSW_FCTL_START_FUNC |
                   SCSW_FCTL_HALT_FUNC |
                   SCSW_FCTL_CLEAR_FUNC)) {
        ret = -EBUSY;
        goto out;
        return IOINST_CC_BUSY;
    }

    /* If monitoring is active, update counter. */
@@ -1602,10 +1540,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
    s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
    s->flags &= ~SCSW_FLAGS_MASK_PNO;

    ret = do_subchannel_work(sch);

out:
    return ret;
    return do_subchannel_work(sch);
}

static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
@@ -1778,7 +1713,7 @@ void css_undo_stcrw(CRW *crw)
{
    CrwContainer *crw_cont;

    crw_cont = g_try_malloc0(sizeof(CrwContainer));
    crw_cont = g_try_new0(CrwContainer, 1);
    if (!crw_cont) {
        channel_subsys.crws_lost = true;
        return;
@@ -1852,27 +1787,23 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
    }
}

int css_do_rsch(SubchDev *sch)
IOInstEnding css_do_rsch(SubchDev *sch)
{
    SCSW *s = &sch->curr_status.scsw;
    PMCW *p = &sch->curr_status.pmcw;
    int ret;

    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
        ret = -ENODEV;
        goto out;
        return IOINST_CC_NOT_OPERATIONAL;
    }

    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
        ret = -EINPROGRESS;
        goto out;
        return IOINST_CC_STATUS_PRESENT;
    }

    if (((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
        (s->ctrl & SCSW_ACTL_RESUME_PEND) ||
        (!(s->ctrl & SCSW_ACTL_SUSP))) {
        ret = -EINVAL;
        goto out;
        return IOINST_CC_BUSY;
    }

    /* If monitoring is active, update counter. */
@@ -1881,11 +1812,7 @@ int css_do_rsch(SubchDev *sch)
    }

    s->ctrl |= SCSW_ACTL_RESUME_PEND;
    do_subchannel_work(sch);
    ret = 0;

out:
    return ret;
    return do_subchannel_work(sch);
}

int css_do_rchp(uint8_t cssid, uint8_t chpid)
@@ -2185,7 +2112,7 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
    css = channel_subsys.css[cssid];

    if (!css->sch_set[ssid]) {
        css->sch_set[ssid] = g_malloc0(sizeof(SubchSet));
        css->sch_set[ssid] = g_new0(SubchSet, 1);
    }
    s_set = css->sch_set[ssid];

@@ -2206,7 +2133,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,

    trace_css_crw(rsc, erc, rsid, chain ? "(chained)" : "");
    /* TODO: Maybe use a static crw pool? */
    crw_cont = g_try_malloc0(sizeof(CrwContainer));
    crw_cont = g_try_new0(CrwContainer, 1);
    if (!crw_cont) {
        channel_subsys.crws_lost = true;
        return;
@@ -2498,7 +2425,7 @@ SubchDev *css_create_sch(CssDevId bus_id, bool is_virtual, bool squash_mcss,
        }
    }

    sch = g_malloc0(sizeof(*sch));
    sch = g_new0(SubchDev, 1);
    sch->cssid = bus_id.cssid;
    sch->ssid = bus_id.ssid;
    sch->devno = bus_id.devid;
+29 −6
Original line number Diff line number Diff line
@@ -259,23 +259,46 @@ out:
    return;
}

/* copy up to dst_len bytes and fill the rest of dst with zeroes */
static void copy_mask(uint8_t *dst, uint8_t *src, uint16_t dst_len,
                      uint16_t src_len)
{
    int i;

    for (i = 0; i < dst_len; i++) {
        dst[i] = i < src_len ? src[i] : 0;
    }
}

static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb)
{
    WriteEventMask *we_mask = (WriteEventMask *) sccb;
    uint16_t mask_length = be16_to_cpu(we_mask->mask_length);
    uint32_t tmp_mask;

    /* Attention: We assume that Linux uses 4-byte masks, what it actually
       does. Architecture allows for masks of variable size, though */
    if (be16_to_cpu(we_mask->mask_length) != 4) {
    if (!mask_length || (mask_length > SCLP_EVENT_MASK_LEN_MAX)) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_MASK_LENGTH);
        goto out;
    }

    /*
     * Note: We currently only support masks up to 4 byte length;
     *       the remainder is filled up with zeroes. Linux uses
     *       a 4 byte mask length.
     */

    /* keep track of the guest's capability masks */
    ef->receive_mask = be32_to_cpu(we_mask->cp_receive_mask);
    copy_mask((uint8_t *)&tmp_mask, WEM_CP_RECEIVE_MASK(we_mask, mask_length),
              sizeof(tmp_mask), mask_length);
    ef->receive_mask = be32_to_cpu(tmp_mask);

    /* return the SCLP's capability masks to the guest */
    we_mask->send_mask = cpu_to_be32(get_host_send_mask(ef));
    we_mask->receive_mask = cpu_to_be32(get_host_receive_mask(ef));
    tmp_mask = cpu_to_be32(get_host_send_mask(ef));
    copy_mask(WEM_RECEIVE_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
              mask_length, sizeof(tmp_mask));
    tmp_mask = cpu_to_be32(get_host_receive_mask(ef));
    copy_mask(WEM_SEND_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
              mask_length, sizeof(tmp_mask));

    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);

Loading