All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: peter.maydell@linaro.org, groug@kaod.org
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
	Matthieu Bucchianeri <matthieu.bucchianeri@leostella.com>,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [PULL 15/40] target/ppc: Fix SPE unavailable exception triggering
Date: Tue, 18 Aug 2020 14:18:57 +1000	[thread overview]
Message-ID: <20200818041922.251708-16-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20200818041922.251708-1-david@gibson.dropbear.id.au>

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



  parent reply	other threads:[~2020-08-18  4:31 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-18  4:18 [PULL 00/40] ppc-for-5.2 queue 20200818 David Gibson
2020-08-18  4:18 ` [PULL 01/40] target/ppc: Fix TCG leak with the evmwsmiaa instruction David Gibson
2020-08-18  4:18 ` [PULL 02/40] target/ppc: Introduce Power ISA 3.1 flag David Gibson
2020-08-18  4:18 ` [PULL 03/40] target/ppc: Enable Power ISA 3.1 David Gibson
2020-08-18  4:18 ` [PULL 04/40] target/ppc: add byte-reverse br[dwh] instructions David Gibson
2020-08-18  4:18 ` [PULL 05/40] target/ppc: convert vmuluwm to tcg_gen_gvec_mul David Gibson
2020-08-18  4:18 ` [PULL 06/40] target/ppc: add vmulld instruction David Gibson
2020-08-18  4:18 ` [PULL 07/40] ppc/spapr: Fix 32 bit logical memory block size assumptions David Gibson
2020-08-18  4:18 ` [PULL 08/40] spapr: Use error_append_hint() in spapr_caps.c David Gibson
2020-08-18  4:18 ` [PULL 09/40] spapr: Forbid nested KVM-HV in pre-power9 compat mode David Gibson
2020-08-18  4:18 ` [PULL 10/40] ppc/xive: Fix some typos in comments David Gibson
2020-08-18  4:18 ` [PULL 11/40] Update PowerPC AT_HWCAP2 definition David Gibson
2020-08-18  4:18 ` [PULL 12/40] target/ppc: add vmulld to INDEX_op_mul_vec case David Gibson
2020-08-18  4:18 ` [PULL 13/40] target/ppc: add vmulh{su}w instructions David Gibson
2020-08-18  4:18 ` [PULL 14/40] target/ppc: add vmulh{su}d instructions David Gibson
2020-08-18  4:18 ` David Gibson [this message]
2020-08-18  4:18 ` [PULL 16/40] docs: adding NUMA documentation for pseries David Gibson
2020-08-18  4:18 ` [PULL 17/40] docs: Update POWER9 XIVE support for nested guests David Gibson
2020-08-18  4:19 ` [PULL 18/40] spapr: Clarify error and documentation for broken KVM XICS David Gibson
2020-08-18  4:19 ` [PULL 19/40] spapr/xive: Fix xive->fd if kvm_create_device() fails David Gibson
2020-08-18  4:19 ` [PULL 20/40] spapr/xive: Simplify kvmppc_xive_disconnect() David Gibson
2020-08-18  4:19 ` [PULL 21/40] target/ppc: Integrate icount to purr, vtb, and tbu40 David Gibson
2020-08-18  4:19 ` [PULL 22/40] ppc/xive: Rework setup of XiveSource::esb_mmio David Gibson
2020-08-18  4:19 ` [PULL 23/40] ppc/xive: Introduce dedicated kvm_irqchip_in_kernel() wrappers David Gibson
2020-08-18  4:19 ` [PULL 24/40] spapr/xive: Convert KVM device fd checks to assert() David Gibson
2020-08-18  4:19 ` [PULL 25/40] spapr: Simplify error handling in spapr_phb_realize() David Gibson
2020-08-18  4:19 ` [PULL 26/40] spapr/xive: Rework error handling of kvmppc_xive_cpu_connect() David Gibson
2020-08-18  4:19 ` [PULL 27/40] spapr/xive: Rework error handling of kvmppc_xive_source_reset() David Gibson
2020-08-18  4:19 ` [PULL 28/40] spapr/xive: Rework error handling of kvmppc_xive_mmap() David Gibson
2020-08-18  4:19 ` [PULL 29/40] spapr/xive: Rework error handling of kvmppc_xive_cpu_[gs]et_state() David Gibson
2020-08-18  4:19 ` [PULL 30/40] spapr/xive: Rework error handling of kvmppc_xive_[gs]et_queue_config() David Gibson
2020-08-18  4:19 ` [PULL 31/40] spapr/xive: Rework error handling in kvmppc_xive_get_queues() David Gibson
2020-08-18  4:19 ` [PULL 32/40] spapr/xive: Rework error handling of kvmppc_xive_set_source_config() David Gibson
2020-08-18  4:19 ` [PULL 33/40] spapr/kvm: Fix error handling in kvmppc_xive_pre_save() David Gibson
2020-08-18  4:19 ` [PULL 34/40] spapr/xive: Fix error handling in kvmppc_xive_post_load() David Gibson
2020-08-18  4:19 ` [PULL 35/40] ppc/xive: Fix error handling in vmstate_xive_tctx_*() callbacks David Gibson
2020-08-18  4:19 ` [PULL 36/40] spapr/xive: Simplify error handling in kvmppc_xive_connect() David Gibson
2020-08-18  4:19 ` [PULL 37/40] ppc/xive: Simplify error handling in xive_tctx_realize() David Gibson
2020-08-18  4:19 ` [PULL 38/40] spapr/xive: Simplify error handling of kvmppc_xive_cpu_synchronize_state() David Gibson
2020-08-18  4:19 ` [PULL 39/40] nvram: Exit QEMU if NVRAM cannot contain all -prom-env data David Gibson
2020-08-18  4:19 ` [PULL 40/40] spapr/xive: Use xive_source_esb_len() David Gibson
2020-08-23 13:54 ` [PULL 00/40] ppc-for-5.2 queue 20200818 Peter Maydell
2020-08-23 23:21   ` David Gibson
2020-08-24  8:36     ` Peter Maydell
2020-08-24 11:12 ` Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200818041922.251708-16-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=groug@kaod.org \
    --cc=matthieu.bucchianeri@leostella.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.