[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 15/40] target/ppc: Fix SPE unavailable exception triggering
From: |
David Gibson |
Subject: |
[PULL 15/40] target/ppc: Fix SPE unavailable exception triggering |
Date: |
Tue, 18 Aug 2020 14:18:57 +1000 |
From: Matthieu Bucchianeri <matthieu.bucchianeri@leostella.com>
When emulating certain floating point instructions or vector instructions on
PowerPC machines, QEMU did not properly generate the SPE/Embedded Floating-
Point Unavailable interrupt. See the buglink further below for references to
the relevant NXP documentation.
This patch fixes the behavior of some evfs* instructions that were
incorrectly emitting the interrupt.
More importantly, this patch fixes the behavior of several efd* and ev*
instructions that were not generating the interrupt. Triggering the
interrupt for these instructions fixes lazy FPU/vector context switching on
some operating systems like Linux.
Without this patch, the result of some double-precision arithmetic could be
corrupted due to the lack of proper saving and restoring of the upper
32-bit part of the general-purpose registers.
Buglink: https://bugs.launchpad.net/qemu/+bug/1888918
Buglink: https://bugs.launchpad.net/qemu/+bug/1611394
Signed-off-by: Matthieu Bucchianeri <matthieu.bucchianeri@leostella.com>
Message-Id: <20200727175553.32276-1-matthieu.bucchianeri@leostella.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target/ppc/translate/spe-impl.inc.c | 97 +++++++++++++++++++----------
1 file changed, 64 insertions(+), 33 deletions(-)
diff --git a/target/ppc/translate/spe-impl.inc.c
b/target/ppc/translate/spe-impl.inc.c
index 42a0d1cffb..2e6e799a25 100644
--- a/target/ppc/translate/spe-impl.inc.c
+++ b/target/ppc/translate/spe-impl.inc.c
@@ -349,14 +349,24 @@ static inline void gen_evmergelohi(DisasContext *ctx)
}
static inline void gen_evsplati(DisasContext *ctx)
{
- uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
+ uint64_t imm;
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
+ imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
}
static inline void gen_evsplatfi(DisasContext *ctx)
{
- uint64_t imm = rA(ctx->opcode) << 27;
+ uint64_t imm;
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
+ imm = rA(ctx->opcode) << 27;
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
@@ -389,21 +399,37 @@ static inline void gen_evsel(DisasContext *ctx)
static void gen_evsel0(DisasContext *ctx)
{
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
gen_evsel(ctx);
}
static void gen_evsel1(DisasContext *ctx)
{
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
gen_evsel(ctx);
}
static void gen_evsel2(DisasContext *ctx)
{
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
gen_evsel(ctx);
}
static void gen_evsel3(DisasContext *ctx)
{
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
gen_evsel(ctx);
}
@@ -518,6 +544,11 @@ static inline void gen_evmwsmia(DisasContext *ctx)
{
TCGv_i64 tmp;
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
+
gen_evmwsmi(ctx); /* rD := rA * rB */
tmp = tcg_temp_new_i64();
@@ -534,6 +565,11 @@ static inline void gen_evmwsmiaa(DisasContext *ctx)
TCGv_i64 acc;
TCGv_i64 tmp;
+ if (unlikely(!ctx->spe_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_SPEU);
+ return;
+ }
+
gen_evmwsmi(ctx); /* rD := rA * rB */
acc = tcg_temp_new_i64();
@@ -892,8 +928,14 @@ static inline void gen_##name(DisasContext *ctx)
\
#define GEN_SPEFPUOP_CONV_32_64(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i64 t0 = tcg_temp_new_i64(); \
- TCGv_i32 t1 = tcg_temp_new_i32(); \
+ TCGv_i64 t0; \
+ TCGv_i32 t1; \
+ if (unlikely(!ctx->spe_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_SPEU); \
+ return; \
+ } \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i32(); \
gen_load_gpr64(t0, rB(ctx->opcode)); \
gen_helper_##name(t1, cpu_env, t0); \
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \
@@ -903,8 +945,14 @@ static inline void gen_##name(DisasContext *ctx)
\
#define GEN_SPEFPUOP_CONV_64_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i64 t0 = tcg_temp_new_i64(); \
- TCGv_i32 t1 = tcg_temp_new_i32(); \
+ TCGv_i64 t0; \
+ TCGv_i32 t1; \
+ if (unlikely(!ctx->spe_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_SPEU); \
+ return; \
+ } \
+ t0 = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
gen_helper_##name(t0, cpu_env, t1); \
gen_store_gpr64(rD(ctx->opcode), t0); \
@@ -914,7 +962,12 @@ static inline void gen_##name(DisasContext *ctx)
\
#define GEN_SPEFPUOP_CONV_64_64(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i64 t0 = tcg_temp_new_i64(); \
+ TCGv_i64 t0; \
+ if (unlikely(!ctx->spe_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_SPEU); \
+ return; \
+ } \
+ t0 = tcg_temp_new_i64(); \
gen_load_gpr64(t0, rB(ctx->opcode)); \
gen_helper_##name(t0, cpu_env, t0); \
gen_store_gpr64(rD(ctx->opcode), t0); \
@@ -923,13 +976,8 @@ static inline void gen_##name(DisasContext *ctx)
\
#define GEN_SPEFPUOP_ARITH2_32_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i32 t0, t1; \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i32(); \
+ TCGv_i32 t0 = tcg_temp_new_i32(); \
+ TCGv_i32 t1 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
gen_helper_##name(t0, cpu_env, t0, t1); \
@@ -958,13 +1006,8 @@ static inline void gen_##name(DisasContext *ctx)
\
#define GEN_SPEFPUOP_COMP_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i32 t0, t1; \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i32(); \
+ TCGv_i32 t0 = tcg_temp_new_i32(); \
+ TCGv_i32 t1 = tcg_temp_new_i32(); \
\
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
@@ -1074,28 +1117,16 @@ GEN_SPEFPUOP_ARITH2_32_32(efsmul);
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
static inline void gen_efsabs(DisasContext *ctx)
{
- if (unlikely(!ctx->spe_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_SPEU);
- return;
- }
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
(target_long)~0x80000000LL);
}
static inline void gen_efsnabs(DisasContext *ctx)
{
- if (unlikely(!ctx->spe_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_SPEU);
- return;
- }
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
0x80000000);
}
static inline void gen_efsneg(DisasContext *ctx)
{
- if (unlikely(!ctx->spe_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_SPEU);
- return;
- }
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
0x80000000);
}
--
2.26.2
- [PULL 09/40] spapr: Forbid nested KVM-HV in pre-power9 compat mode, (continued)
- [PULL 09/40] spapr: Forbid nested KVM-HV in pre-power9 compat mode, David Gibson, 2020/08/18
- [PULL 07/40] ppc/spapr: Fix 32 bit logical memory block size assumptions, David Gibson, 2020/08/18
- [PULL 05/40] target/ppc: convert vmuluwm to tcg_gen_gvec_mul, David Gibson, 2020/08/18
- [PULL 12/40] target/ppc: add vmulld to INDEX_op_mul_vec case, David Gibson, 2020/08/18
- [PULL 11/40] Update PowerPC AT_HWCAP2 definition, David Gibson, 2020/08/18
- [PULL 14/40] target/ppc: add vmulh{su}d instructions, David Gibson, 2020/08/18
- [PULL 16/40] docs: adding NUMA documentation for pseries, David Gibson, 2020/08/18
- [PULL 10/40] ppc/xive: Fix some typos in comments, David Gibson, 2020/08/18
- [PULL 13/40] target/ppc: add vmulh{su}w instructions, David Gibson, 2020/08/18
- [PULL 18/40] spapr: Clarify error and documentation for broken KVM XICS, David Gibson, 2020/08/18
- [PULL 15/40] target/ppc: Fix SPE unavailable exception triggering,
David Gibson <=
- [PULL 17/40] docs: Update POWER9 XIVE support for nested guests, David Gibson, 2020/08/18
- [PULL 19/40] spapr/xive: Fix xive->fd if kvm_create_device() fails, David Gibson, 2020/08/18
- [PULL 22/40] ppc/xive: Rework setup of XiveSource::esb_mmio, David Gibson, 2020/08/18
- [PULL 23/40] ppc/xive: Introduce dedicated kvm_irqchip_in_kernel() wrappers, David Gibson, 2020/08/18
- [PULL 20/40] spapr/xive: Simplify kvmppc_xive_disconnect(), David Gibson, 2020/08/18
- [PULL 21/40] target/ppc: Integrate icount to purr, vtb, and tbu40, David Gibson, 2020/08/18
- [PULL 24/40] spapr/xive: Convert KVM device fd checks to assert(), David Gibson, 2020/08/18
- [PULL 27/40] spapr/xive: Rework error handling of kvmppc_xive_source_reset(), David Gibson, 2020/08/18
- [PULL 26/40] spapr/xive: Rework error handling of kvmppc_xive_cpu_connect(), David Gibson, 2020/08/18
- [PULL 25/40] spapr: Simplify error handling in spapr_phb_realize(), David Gibson, 2020/08/18