s390x/tcg: factor out and fix DATA exception injection

The DXC is to be stored in the low core, and only in the FPC in case AFP
is enabled in CR0. Stub is not required in current code, but this way
we never run into problems.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180927130303.12236-3-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
David Hildenbrand 2018-09-27 15:02:56 +02:00 committed by Cornelia Huck
parent 52341ed61d
commit bbf6ea3bd9
7 changed files with 44 additions and 20 deletions

View File

@ -322,6 +322,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#define CR0_LOWPROT 0x0000000010000000ULL
#define CR0_SECONDARY 0x0000000004000000ULL
#define CR0_EDAT 0x0000000000800000ULL
#define CR0_AFP 0x0000000000040000ULL
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
#define CR0_CKC_SC 0x0000000000000800ULL

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
#include "exec/helper-proto.h"
#include "qemu/timer.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
@ -61,6 +62,28 @@ void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
cpu_loop_exit(cs);
}
void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
uintptr_t ra)
{
g_assert(dxc <= 0xff);
#if !defined(CONFIG_USER_ONLY)
/* Store the DXC into the lowcore */
stl_phys(CPU(s390_env_get_cpu(env))->as,
env->psa + offsetof(LowCore, data_exc_code), dxc);
#endif
/* Store the DXC into the FPC if AFP is enabled */
if (env->cregs[0] & CR0_AFP) {
env->fpc = deposit32(env->fpc, 8, 8, dxc);
}
tcg_s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, ra);
}
void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
{
tcg_s390_data_exception(env, dxc, GETPC());
}
#if defined(CONFIG_USER_ONLY)
void s390_cpu_do_interrupt(CPUState *cs)

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
#include "tcg_s390x.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "exec/helper-proto.h"
@ -40,14 +41,6 @@
? (mask / (from / to)) & to \
: (mask & from) * (to / from))
static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
{
/* Install the DXC code. */
env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
/* Trap. */
s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, retaddr);
}
/* Should be called after any operation that may raise IEEE exceptions. */
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
{
@ -75,7 +68,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
/* Send signals for enabled exceptions. */
s390_exc &= env->fpc >> 24;
if (s390_exc) {
ieee_exception(env, s390_exc, retaddr);
tcg_s390_data_exception(env, s390_exc, retaddr);
}
}
@ -773,6 +766,6 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t val)
is also 1, a simulated-iee-exception trap occurs. */
s390_exc = (signalling >> 16) & (source >> 24);
if (s390_exc) {
ieee_exception(env, s390_exc | 3, GETPC());
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
}
}

View File

@ -1,4 +1,5 @@
DEF_HELPER_2(exception, noreturn, env, i32)
DEF_HELPER_2(data_exception, noreturn, env, i32)
DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)

View File

@ -23,3 +23,8 @@ void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
{
g_assert_not_reached();
}
void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
uintptr_t ra)
{
g_assert_not_reached();
}

View File

@ -16,5 +16,7 @@
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque);
void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
int ilen, uintptr_t ra);
void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
uintptr_t ra);
#endif /* TCG_S390X_H */

View File

@ -314,18 +314,17 @@ static inline void gen_illegal_opcode(DisasContext *s)
gen_program_exception(s, PGM_OPERATION);
}
static inline void gen_data_exception(uint8_t dxc)
{
TCGv_i32 tmp = tcg_const_i32(dxc);
gen_helper_data_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
}
static inline void gen_trap(DisasContext *s)
{
TCGv_i32 t;
/* Set DXC to 0xff. */
t = tcg_temp_new_i32();
tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
tcg_gen_ori_i32(t, t, 0xff00);
tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
tcg_temp_free_i32(t);
gen_program_exception(s, PGM_DATA);
/* Set DXC to 0xff */
gen_data_exception(0xff);
}
#ifndef CONFIG_USER_ONLY