Commit 478d360c authored by Pavel Zbitskiy's avatar Pavel Zbitskiy Committed by Cornelia Huck
Browse files

target/s390x: fix IPM polluting irrelevant bits



Suppose psw.mask=0x0000000080000000, cc=2, r1=0 and we do "ipm 1".
This command must touch only bits 32-39, so the expected output
is r1=0x20000000. However, currently qemu yields r1=0x20008000,
because irrelevant parts of PSW leak into r1 during program mask
transfer.

Signed-off-by: default avatarPavel Zbitskiy <pavel.zbitskiy@gmail.com>
Message-Id: <20180821025104.19604-5-pavel.zbitskiy@gmail.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Signed-off-by: default avatarCornelia Huck <cohuck@redhat.com>
parent dc95b31d
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -2444,20 +2444,17 @@ static DisasJumpType op_insi(DisasContext *s, DisasOps *o)

static DisasJumpType op_ipm(DisasContext *s, DisasOps *o)
{
    TCGv_i64 t1;
    TCGv_i64 t1, t2;

    gen_op_calc_cc(s);
    tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);

    t1 = tcg_temp_new_i64();
    tcg_gen_shli_i64(t1, psw_mask, 20);
    tcg_gen_shri_i64(t1, t1, 36);
    tcg_gen_or_i64(o->out, o->out, t1);

    tcg_gen_extu_i32_i64(t1, cc_op);
    tcg_gen_shli_i64(t1, t1, 28);
    tcg_gen_or_i64(o->out, o->out, t1);
    tcg_gen_extract_i64(t1, psw_mask, 40, 4);
    t2 = tcg_temp_new_i64();
    tcg_gen_extu_i32_i64(t2, cc_op);
    tcg_gen_deposit_i64(t1, t1, t2, 4, 60);
    tcg_gen_deposit_i64(o->out, o->out, t1, 24, 8);
    tcg_temp_free_i64(t1);
    tcg_temp_free_i64(t2);
    return DISAS_NEXT;
}

+1 −0
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@ VPATH+=$(SRC_PATH)/tests/tcg/s390x
CFLAGS+=-march=zEC12 -m64
TESTS+=hello-s390x
TESTS+=csst
TESTS+=ipm

tests/tcg/s390x/ipm.c

0 → 100644
+22 −0
Original line number Diff line number Diff line
#include <stdint.h>
#include <unistd.h>

int main(void)
{
    uint32_t op1 = 0x55555555;
    uint32_t op2 = 0x44444444;
    uint64_t cc = 0xffffffffffffffffull;

    asm volatile(
        "    clc 0(4,%[op1]),0(%[op2])\n"
        "    ipm %[cc]\n"
        : [cc] "+r" (cc)
        : [op1] "r" (&op1),
          [op2] "r" (&op2)
        : "cc");
    if (cc != 0xffffffff20ffffffull) {
        write(1, "bad cc\n", 7);
        return 1;
    }
    return 0;
}