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:
parent
52341ed61d
commit
bbf6ea3bd9
@ -322,6 +322,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
|
|||||||
#define CR0_LOWPROT 0x0000000010000000ULL
|
#define CR0_LOWPROT 0x0000000010000000ULL
|
||||||
#define CR0_SECONDARY 0x0000000004000000ULL
|
#define CR0_SECONDARY 0x0000000004000000ULL
|
||||||
#define CR0_EDAT 0x0000000000800000ULL
|
#define CR0_EDAT 0x0000000000800000ULL
|
||||||
|
#define CR0_AFP 0x0000000000040000ULL
|
||||||
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
|
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
|
||||||
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
|
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
|
||||||
#define CR0_CKC_SC 0x0000000000000800ULL
|
#define CR0_CKC_SC 0x0000000000000800ULL
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "exec/helper-proto.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/cpu_ldst.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);
|
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)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
void s390_cpu_do_interrupt(CPUState *cs)
|
void s390_cpu_do_interrupt(CPUState *cs)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "tcg_s390x.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
@ -40,14 +41,6 @@
|
|||||||
? (mask / (from / to)) & to \
|
? (mask / (from / to)) & to \
|
||||||
: (mask & from) * (to / from))
|
: (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. */
|
/* Should be called after any operation that may raise IEEE exceptions. */
|
||||||
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
|
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. */
|
/* Send signals for enabled exceptions. */
|
||||||
s390_exc &= env->fpc >> 24;
|
s390_exc &= env->fpc >> 24;
|
||||||
if (s390_exc) {
|
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. */
|
is also 1, a simulated-iee-exception trap occurs. */
|
||||||
s390_exc = (signalling >> 16) & (source >> 24);
|
s390_exc = (signalling >> 16) & (source >> 24);
|
||||||
if (s390_exc) {
|
if (s390_exc) {
|
||||||
ieee_exception(env, s390_exc | 3, GETPC());
|
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
DEF_HELPER_2(exception, noreturn, env, i32)
|
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(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(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
|
||||||
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
|
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
|
||||||
|
@ -23,3 +23,8 @@ void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
|
|||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
|
||||||
|
uintptr_t ra)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
@ -16,5 +16,7 @@
|
|||||||
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque);
|
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque);
|
||||||
void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
|
void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
|
||||||
int ilen, uintptr_t ra);
|
int ilen, uintptr_t ra);
|
||||||
|
void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
|
||||||
|
uintptr_t ra);
|
||||||
|
|
||||||
#endif /* TCG_S390X_H */
|
#endif /* TCG_S390X_H */
|
||||||
|
@ -314,18 +314,17 @@ static inline void gen_illegal_opcode(DisasContext *s)
|
|||||||
gen_program_exception(s, PGM_OPERATION);
|
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)
|
static inline void gen_trap(DisasContext *s)
|
||||||
{
|
{
|
||||||
TCGv_i32 t;
|
/* Set DXC to 0xff */
|
||||||
|
gen_data_exception(0xff);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
Loading…
Reference in New Issue
Block a user