target/s390x: Implement Early Exception Recognition
Generate a specification exception if a reserved bit is set in the PSW mask or if the PSW address is out of bounds dictated by the addressing mode. Reported-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Reviewed-by: David Hildenbrand <david@redhat.com> Message-Id: <20230315020408.384766-3-iii@linux.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
377dc84e2d
commit
199c42a6a1
|
@ -41,6 +41,26 @@
|
||||||
#define CR0_RESET 0xE0UL
|
#define CR0_RESET 0xE0UL
|
||||||
#define CR14_RESET 0xC2000000UL;
|
#define CR14_RESET 0xC2000000UL;
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
static bool is_early_exception_psw(uint64_t mask, uint64_t addr)
|
||||||
|
{
|
||||||
|
if (mask & PSW_MASK_RESERVED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mask & (PSW_MASK_32 | PSW_MASK_64)) {
|
||||||
|
case 0:
|
||||||
|
return addr & ~0xffffffULL;
|
||||||
|
case PSW_MASK_32:
|
||||||
|
return addr & ~0x7fffffffULL;
|
||||||
|
case PSW_MASK_32 | PSW_MASK_64:
|
||||||
|
return false;
|
||||||
|
default: /* PSW_MASK_64 */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
|
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -57,6 +77,12 @@ void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
|
||||||
env->cc_op = (mask >> 44) & 3;
|
env->cc_op = (mask >> 44) & 3;
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
if (is_early_exception_psw(mask, addr)) {
|
||||||
|
env->int_pgm_ilen = 0;
|
||||||
|
trigger_pgm_exception(env, PGM_SPECIFICATION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((old_mask ^ mask) & PSW_MASK_PER) {
|
if ((old_mask ^ mask) & PSW_MASK_PER) {
|
||||||
s390_cpu_recompute_watchpoints(env_cpu(env));
|
s390_cpu_recompute_watchpoints(env_cpu(env));
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,7 @@ extern const VMStateDescription vmstate_s390_cpu;
|
||||||
#define PSW_MASK_32 0x0000000080000000ULL
|
#define PSW_MASK_32 0x0000000080000000ULL
|
||||||
#define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL
|
#define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL
|
||||||
#define PSW_MASK_SHORT_CTRL 0xffffffff80000000ULL
|
#define PSW_MASK_SHORT_CTRL 0xffffffff80000000ULL
|
||||||
|
#define PSW_MASK_RESERVED 0xb80800fe7fffffffULL
|
||||||
|
|
||||||
#undef PSW_ASC_PRIMARY
|
#undef PSW_ASC_PRIMARY
|
||||||
#undef PSW_ASC_ACCREG
|
#undef PSW_ASC_ACCREG
|
||||||
|
|
|
@ -212,7 +212,8 @@ static void do_program_interrupt(CPUS390XState *env)
|
||||||
LowCore *lowcore;
|
LowCore *lowcore;
|
||||||
int ilen = env->int_pgm_ilen;
|
int ilen = env->int_pgm_ilen;
|
||||||
|
|
||||||
assert(ilen == 2 || ilen == 4 || ilen == 6);
|
assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
|
||||||
|
ilen == 2 || ilen == 4 || ilen == 6);
|
||||||
|
|
||||||
switch (env->int_pgm_code) {
|
switch (env->int_pgm_code) {
|
||||||
case PGM_PER:
|
case PGM_PER:
|
||||||
|
|
|
@ -4068,9 +4068,23 @@ static DisasJumpType op_sske(DisasContext *s, DisasOps *o)
|
||||||
return DISAS_NEXT;
|
return DISAS_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_check_psw_mask(DisasContext *s)
|
||||||
|
{
|
||||||
|
TCGv_i64 reserved = tcg_temp_new_i64();
|
||||||
|
TCGLabel *ok = gen_new_label();
|
||||||
|
|
||||||
|
tcg_gen_andi_i64(reserved, psw_mask, PSW_MASK_RESERVED);
|
||||||
|
tcg_gen_brcondi_i64(TCG_COND_EQ, reserved, 0, ok);
|
||||||
|
gen_program_exception(s, PGM_SPECIFICATION);
|
||||||
|
gen_set_label(ok);
|
||||||
|
}
|
||||||
|
|
||||||
static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
|
static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
|
||||||
{
|
{
|
||||||
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
|
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
|
||||||
|
|
||||||
|
gen_check_psw_mask(s);
|
||||||
|
|
||||||
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
|
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
|
||||||
s->exit_to_mainloop = true;
|
s->exit_to_mainloop = true;
|
||||||
return DISAS_TOO_MANY;
|
return DISAS_TOO_MANY;
|
||||||
|
@ -4331,6 +4345,8 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
|
||||||
tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
|
tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_check_psw_mask(s);
|
||||||
|
|
||||||
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
|
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
|
||||||
s->exit_to_mainloop = true;
|
s->exit_to_mainloop = true;
|
||||||
return DISAS_TOO_MANY;
|
return DISAS_TOO_MANY;
|
||||||
|
|
Loading…
Reference in New Issue