Queued s390 patches

-----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJZQEmRAAoJEK0ScMxN0Cebl2QH/2RdrNvNkSf4ggozhhHt1Eob
 f2EsC56eQsPz2+87gaPDumcWUFsxmvyUbZyKCoA0+90V7Ylb/Z9qLOdQdTCtQJtx
 y3xktII+52T8xTusqLuAfUQw8wG7eVblMzBurBPI16ptWWtrlecrvyWvlBMOard9
 pMFKUkhGfO3leWYUBsVujV71bHf+blnLQAgKIgmbD+Qlkao1YxcyS3WHyV7nNSDp
 L5HaR/i0aDG1niDE960GpOT+Ku8CA/UJSubfM8Vge3ollsupDf7798wJr+yqd3Mj
 inwiOWoCf7Vsz7x78lKaMxn1+Fj3BQLI4FUN3mB+9Gky6S3BGjNNsWhB0Z5yzK8=
 =KANG
 -----END PGP SIGNATURE-----

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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-06-15 13:45:15 +01:00
commit edf8bc9842
7 changed files with 66 additions and 46 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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:
ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
break;
case ILEN_LATER_INC:
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;
}
/* 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 */

View file

@ -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 */

View file

@ -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));

View file

@ -79,13 +79,13 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
return;
}
trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, tec);
trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, tec);
}
static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
uint32_t type, uint64_t asc, int rw, bool exc)
{
int ilen = ILEN_LATER;
int ilen = ILEN_AUTO;
uint64_t tec;
tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46;
@ -431,7 +431,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,
for (i = 0; i < nr_pages; i++) {
/* Low-address protection? */
if (lowprot && (addr < 512 || (addr >= 4096 && addr < 4096 + 512))) {
trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, 0);
trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, 0);
return -EACCES;
}
ret = mmu_translate(env, addr, is_write, asc, &pages[i], &pflags, true);

View file

@ -355,8 +355,7 @@ static void gen_program_exception(DisasContext *s, int code)
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
tcg_temp_free_i32(tmp);
/* Advance past instruction. */
s->pc = s->next_pc;
/* update the psw */
update_psw_addr(s);
/* Save off cc. */
@ -3877,14 +3876,9 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1 = tcg_temp_new_i64();
check_privileged(s);
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type));
tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32);
tcg_temp_free_i64(t1);
tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid));
tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
return NO_EXIT;
}