Skip to content

Commit

Permalink
target/s390x: Move trans_exc_code update to do_program_interrupt
Browse files Browse the repository at this point in the history
This solves a problem in which the store to LowCore during tlb_fill
triggers a clean-page TB invalidation for page0 during translation,
which results in an assertion failure for locked pages.

By delaying the store until after the exception has been raised,
we will have unwound the pages locked for translation and the
problem does not arise.  There are plenty of other updates to
LowCore while delivering an interrupt/exception; trans_exc_code
does not need to be special.

Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Jul 31, 2023
1 parent 38dd78c commit 8b94ec5
Showing 1 changed file with 28 additions and 12 deletions.
40 changes: 28 additions & 12 deletions target/s390x/tcg/excp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
return false;
}

if (excp != PGM_ADDRESSING) {
stq_phys(env_cpu(env)->as,
env->psa + offsetof(LowCore, trans_exc_code), tec);
}

/*
* For data accesses, ILEN will be filled in from the unwind info,
* within cpu_loop_exit_restore. For code accesses, retaddr == 0,
Expand All @@ -211,20 +206,33 @@ static void do_program_interrupt(CPUS390XState *env)
uint64_t mask, addr;
LowCore *lowcore;
int ilen = env->int_pgm_ilen;
bool set_trans_exc_code = false;
bool advance = false;

assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
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 */
advance = !(env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION);
break;
case PGM_ASCE_TYPE:
case PGM_REG_FIRST_TRANS:
case PGM_REG_SEC_TRANS:
case PGM_REG_THIRD_TRANS:
case PGM_SEGMENT_TRANS:
case PGM_PAGE_TRANS:
assert(env->int_pgm_code == env->tlb_fill_exc);
set_trans_exc_code = true;
break;
case PGM_PROTECTION:
assert(env->int_pgm_code == env->tlb_fill_exc);
set_trans_exc_code = true;
advance = true;
break;
case PGM_OPERATION:
case PGM_PRIVILEGED:
case PGM_EXECUTE:
case PGM_PROTECTION:
case PGM_ADDRESSING:
case PGM_SPECIFICATION:
case PGM_DATA:
Expand All @@ -243,11 +251,15 @@ static void do_program_interrupt(CPUS390XState *env)
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;
advance = true;
break;
}

/* advance the PSW if our exception is not nullifying */
if (advance) {
env->psw.addr += ilen;
}

qemu_log_mask(CPU_LOG_INT,
"%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
__func__, env->int_pgm_code, ilen, env->psw.mask,
Expand All @@ -263,6 +275,10 @@ static void do_program_interrupt(CPUS390XState *env)
env->per_perc_atmid = 0;
}

if (set_trans_exc_code) {
lowcore->trans_exc_code = cpu_to_be64(env->tlb_fill_tec);
}

lowcore->pgm_ilen = cpu_to_be16(ilen);
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
Expand Down

0 comments on commit 8b94ec5

Please sign in to comment.