Commit edf8bc98 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-s390-20170613' into staging



Queued s390 patches

# gpg: Signature made Tue 13 Jun 2017 21:22:41 BST
# gpg:                using RSA key 0xAD1270CC4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"
# Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC  16A4 AD12 70CC 4DD0 279B

* remotes/rth/tags/pull-s390-20170613:
  s390x/cpumodel: wire up cpu type + id for TCG
  target/s390x: rework PGM interrupt psw.addr handling
  target/s390x: correctly indicate PER nullification

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 73aa4692 076d4d39
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ typedef struct CPUS390XState {
    CPU_COMMON

    uint32_t cpu_num;
    uint32_t machine_type;
    uint64_t cpuid;

    uint64_t tod_offset;
    uint64_t tod_basetime;
@@ -460,11 +460,6 @@ static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
}

#ifndef CONFIG_USER_ONLY
/* In several cases of runtime exceptions, we havn't recorded the true
   instruction length.  Use these codes when raising exceptions in order
   to re-compute the length by examining the insn in memory.  */
#define ILEN_LATER       0x20
#define ILEN_LATER_INC   0x21
void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
#endif

@@ -1133,6 +1128,8 @@ uint32_t set_cc_nz_f128(float128 v);
int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
#endif
/* automatically detect the instruction length */
#define ILEN_AUTO                   0xff
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
                                     uintptr_t retaddr);
+6 −2
Original line number Diff line number Diff line
@@ -737,8 +737,6 @@ static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)

    if (kvm_enabled()) {
        kvm_s390_apply_cpu_model(model, errp);
    } else if (model) {
        /* FIXME TCG - use data for stdip/stfl */
    }

    if (!*errp) {
@@ -786,6 +784,12 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
    }

    apply_cpu_model(cpu->model, errp);

    cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model);
    if (tcg_enabled()) {
        /* basic mode, write the cpu address into the first 4 bit of the ID */
        cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.cpu_num);
    }
}

static void get_feature(Object *obj, Visitor *v, const char *name,
+35 −9
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
    if (raddr > ram_size) {
        DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
                (uint64_t)raddr, (uint64_t)ram_size);
        trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER_INC);
        trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO);
        return 1;
    }

@@ -331,16 +331,42 @@ static void do_program_interrupt(CPUS390XState *env)
    LowCore *lowcore;
    int ilen = env->int_pgm_ilen;

    switch (ilen) {
    case ILEN_LATER:
    if (ilen == ILEN_AUTO) {
        ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
    }
    assert(ilen == 2 || ilen == 4 || ilen == 6);

    switch (env->int_pgm_code) {
    case PGM_PER:
        if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
            break;
    case ILEN_LATER_INC:
        ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
        }
        /* FALL THROUGH */
    case PGM_OPERATION:
    case PGM_PRIVILEGED:
    case PGM_EXECUTE:
    case PGM_PROTECTION:
    case PGM_ADDRESSING:
    case PGM_SPECIFICATION:
    case PGM_DATA:
    case PGM_FIXPT_OVERFLOW:
    case PGM_FIXPT_DIVIDE:
    case PGM_DEC_OVERFLOW:
    case PGM_DEC_DIVIDE:
    case PGM_HFP_EXP_OVERFLOW:
    case PGM_HFP_EXP_UNDERFLOW:
    case PGM_HFP_SIGNIFICANCE:
    case PGM_HFP_DIVIDE:
    case PGM_TRANS_SPEC:
    case PGM_SPECIAL_OP:
    case PGM_OPERAND:
    case PGM_HFP_SQRT:
    case PGM_PC_TRANS_SPEC:
    case PGM_ALET_SPEC:
    case PGM_MONITOR:
        /* advance the PSW if our exception is not nullifying */
        env->psw.addr += ilen;
        break;
    default:
        assert(ilen == 2 || ilen == 4 || ilen == 6);
    }

    qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
@@ -737,6 +763,6 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
    if (retaddr) {
        cpu_restore_state(cs, retaddr);
    }
    program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER);
    program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
}
#endif /* CONFIG_USER_ONLY */
+1 −1
Original line number Diff line number Diff line
@@ -960,7 +960,7 @@
/* STORE CPU ADDRESS */
    C(0xb212, STAP,    S,     Z,   la2, 0, new, m1_16, stap, 0)
/* STORE CPU ID */
    C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
    C(0xb202, STIDP,   S,     Z,   la2, 0, new, 0, stidp, 0)
/* STORE CPU TIMER */
    C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
/* STORE FACILITY LIST */
+15 −16
Original line number Diff line number Diff line
@@ -54,19 +54,14 @@ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
                                     uintptr_t retaddr)
{
    CPUState *cs = CPU(s390_env_get_cpu(env));
    int t;

    cs->exception_index = EXCP_PGM;
    env->int_pgm_code = excp;
    env->int_pgm_ilen = ILEN_AUTO;

    /* Use the (ultimate) callers address to find the insn that trapped.  */
    cpu_restore_state(cs, retaddr);

    /* Advance past the insn.  */
    t = cpu_ldub_code(env, env->psw.addr);
    env->int_pgm_ilen = t = get_ilen(t);
    env->psw.addr += t;

    cpu_loop_exit(cs);
}

@@ -199,12 +194,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
    IplParameterBlock *iplb;

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

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

@@ -229,12 +224,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
        break;
    case 5:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
            return;
        }
        if (!address_space_access_valid(&address_space_memory, addr,
                                        sizeof(IplParameterBlock), false)) {
            program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
            program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO);
            return;
        }
        iplb = g_malloc0(sizeof(IplParameterBlock));
@@ -258,12 +253,12 @@ out:
        return;
    case 6:
        if ((r1 & 1) || (addr & 0x0fffULL)) {
            program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
            program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
            return;
        }
        if (!address_space_access_valid(&address_space_memory, addr,
                                        sizeof(IplParameterBlock), true)) {
            program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
            program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO);
            return;
        }
        iplb = s390_ipl_get_iplb();
@@ -307,7 +302,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
    }

    if (r) {
        program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
        program_interrupt(env, PGM_OPERATION, ILEN_AUTO);
    }
}

@@ -383,6 +378,7 @@ uint64_t HELPER(stpt)(CPUS390XState *env)
uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
                      uint64_t r0, uint64_t r1)
{
    S390CPU *cpu = s390_env_get_cpu(env);
    int cc = 0;
    int sel1, sel2;

@@ -402,12 +398,14 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
        if ((sel1 == 1) && (sel2 == 1)) {
            /* Basic Machine Configuration */
            struct sysib_111 sysib;
            char type[5] = {};

            memset(&sysib, 0, sizeof(sysib));
            ebcdic_put(sysib.manuf, "QEMU            ", 16);
            /* same as machine type number in STORE CPU ID */
            ebcdic_put(sysib.type, "QEMU", 4);
            /* same as model number in STORE CPU ID */
            /* same as machine type number in STORE CPU ID, but in EBCDIC */
            snprintf(type, ARRAY_SIZE(type), "%X", cpu->model->def->type);
            ebcdic_put(sysib.type, type, 4);
            /* model number (not stored in STORE CPU ID for z/Architecure) */
            ebcdic_put(sysib.model, "QEMU            ", 16);
            ebcdic_put(sysib.sequence, "QEMU            ", 16);
            ebcdic_put(sysib.plant, "QEMU", 4);
@@ -668,6 +666,7 @@ void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr)
        if (env->cregs[9] & PER_CR9_EVENT_NULLIFICATION) {
            CPUState *cs = CPU(s390_env_get_cpu(env));

            env->per_perc_atmid |= PER_CODE_EVENT_NULLIFICATION;
            env->int_pgm_code = PGM_PER;
            env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, addr));

Loading