qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 0/4] ppc queue
@ 2023-11-21  8:51 Cédric Le Goater
  2023-11-21  8:51 ` [PULL 1/4] ppc/pnv: Fix potential overflow in I2C model Cédric Le Goater
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Cédric Le Goater @ 2023-11-21  8:51 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: Daniel Henrique Barboza, Nicholas Piggin, Cédric Le Goater

The following changes since commit af9264da80073435fd78944bc5a46e695897d7e5:

  Merge tag '20231119-xtensa-1' of https://github.com/OSLL/qemu-xtensa into staging (2023-11-20 05:25:19 -0500)

are available in the Git repository at:

  https://github.com/legoater/qemu/ tags/pull-ppc-20231121

for you to fetch changes up to b664466d8f3c7b448fc7e9bd50d03a36538c6c27:

  ppc/pnv: Fix PNV I2C invalid status after reset (2023-11-21 08:39:58 +0100)

----------------------------------------------------------------
ppc queue:

* PNV I2C fixes
* VSX instruction fix when converting floating point to integer values

----------------------------------------------------------------
Cédric Le Goater (1):
      ppc/pnv: Fix potential overflow in I2C model

Glenn Miles (2):
      ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses
      ppc/pnv: Fix PNV I2C invalid status after reset

John Platts (1):
      target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros

 hw/ppc/pnv.c                    |   6 +-
 hw/ppc/pnv_i2c.c                |  52 +++----
 target/ppc/fpu_helper.c         |  12 +-
 tests/tcg/ppc64/vsx_f2i_nan.c   | 300 ++++++++++++++++++++++++++++++++++++++++
 tests/tcg/ppc64/Makefile.target |   5 +
 5 files changed, 343 insertions(+), 32 deletions(-)
 create mode 100644 tests/tcg/ppc64/vsx_f2i_nan.c


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PULL 1/4] ppc/pnv: Fix potential overflow in I2C model
  2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
@ 2023-11-21  8:51 ` Cédric Le Goater
  2023-11-21  8:51 ` [PULL 2/4] target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros Cédric Le Goater
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Cédric Le Goater @ 2023-11-21  8:51 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: Daniel Henrique Barboza, Nicholas Piggin, Cédric Le Goater,
	Glenn Miles, Philippe Mathieu-Daudé

Coverity warns that "i2c_bus_busy(i2c->busses[i]) << i" might overflow
because the expression is evaluated using 32-bit arithmetic and then
used in a context expecting a uint64_t.

While we are at it, introduce a PNV_I2C_MAX_BUSSES constant and check
the number of busses at realize time.

Fixes: Coverity CID 1523918
Cc: Glenn Miles <milesg@linux.vnet.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Glenn Miles <milesg@linux.vnet.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ppc/pnv_i2c.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c
index f75e59e70977..483d91d15a77 100644
--- a/hw/ppc/pnv_i2c.c
+++ b/hw/ppc/pnv_i2c.c
@@ -151,6 +151,7 @@
 #define I2C_RESET_S_SDA_REG             0x11
 
 #define PNV_I2C_FIFO_SIZE 8
+#define PNV_I2C_MAX_BUSSES 64
 
 static I2CBus *pnv_i2c_get_bus(PnvI2C *i2c)
 {
@@ -437,7 +438,7 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr,
     case I2C_PORT_BUSY_REG: /* compute busy bit for each port  */
         val = 0;
         for (i = 0; i < i2c->num_busses; i++) {
-            val |= i2c_bus_busy(i2c->busses[i]) << i;
+            val |= (uint64_t)i2c_bus_busy(i2c->busses[i]) << i;
         }
         break;
 
@@ -641,6 +642,11 @@ static void pnv_i2c_realize(DeviceState *dev, Error **errp)
 
     assert(i2c->chip);
 
+    if (i2c->num_busses > PNV_I2C_MAX_BUSSES) {
+        error_setg(errp, "Invalid number of busses: %u", i2c->num_busses);
+        return;
+    }
+
     pnv_xscom_region_init(&i2c->xscom_regs, OBJECT(i2c), &pnv_i2c_xscom_ops,
                           i2c, "xscom-i2c", PNV9_XSCOM_I2CM_SIZE);
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PULL 2/4] target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros
  2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
  2023-11-21  8:51 ` [PULL 1/4] ppc/pnv: Fix potential overflow in I2C model Cédric Le Goater
@ 2023-11-21  8:51 ` Cédric Le Goater
  2023-11-21  8:51 ` [PULL 3/4] ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses Cédric Le Goater
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Cédric Le Goater @ 2023-11-21  8:51 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: Daniel Henrique Barboza, Nicholas Piggin, John Platts,
	Richard Henderson, Cédric Le Goater

From: John Platts <john_platts@hotmail.com>

The patch below fixes a bug in the VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2
macros in target/ppc/fpu_helper.c where a non-NaN floating point value from the
source vector is incorrectly converted to 0, 0x80000000, or 0x8000000000000000
instead of the expected value if a preceding source floating point value from
the same source vector was a NaN.

The bug in the VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros in
target/ppc/fpu_helper.c was introduced with commit c3f24257e3c0.

This patch also adds a new vsx_f2i_nan test in tests/tcg/ppc64 that checks that
the VSX xvcvspsxws, xvcvspuxws, xvcvspsxds, xvcvspuxds, xvcvdpsxws, xvcvdpuxws,
xvcvdpsxds, and xvcvdpuxds instructions correctly convert non-NaN floating point
values to integer values if the source vector contains NaN floating point values.

Fixes: c3f24257e3c0 ("target/ppc: Clear fpstatus flags on helpers missing it")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1941
Signed-off-by: John Platts <john_platts@hotmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 target/ppc/fpu_helper.c         |  12 +-
 tests/tcg/ppc64/vsx_f2i_nan.c   | 300 ++++++++++++++++++++++++++++++++
 tests/tcg/ppc64/Makefile.target |   5 +
 3 files changed, 313 insertions(+), 4 deletions(-)
 create mode 100644 tests/tcg/ppc64/vsx_f2i_nan.c

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 03150a0f1082..4b3dcad5d132 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2880,20 +2880,22 @@ uint64_t helper_XSCVSPDPN(uint64_t xb)
 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan)         \
 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
 {                                                                            \
+    int all_flags = 0;                                                       \
     ppc_vsr_t t = { };                                                       \
     int i, flags;                                                            \
                                                                              \
-    helper_reset_fpstatus(env);                                              \
-                                                                             \
     for (i = 0; i < nels; i++) {                                             \
+        helper_reset_fpstatus(env);                                          \
         t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status);  \
         flags = env->fp_status.float_exception_flags;                        \
+        all_flags |= flags;                                                  \
         if (unlikely(flags & float_flag_invalid)) {                          \
             t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\
         }                                                                    \
     }                                                                        \
                                                                              \
     *xt = t;                                                                 \
+    env->fp_status.float_exception_flags = all_flags;                        \
     do_float_check_status(env, sfi, GETPC());                                \
 }
 
@@ -2945,15 +2947,16 @@ VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL);
 #define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan)                    \
 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
 {                                                                            \
+    int all_flags = 0;                                                       \
     ppc_vsr_t t = { };                                                       \
     int i, flags;                                                            \
                                                                              \
-    helper_reset_fpstatus(env);                                              \
-                                                                             \
     for (i = 0; i < nels; i++) {                                             \
+        helper_reset_fpstatus(env);                                          \
         t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i),          \
                                                        &env->fp_status);     \
         flags = env->fp_status.float_exception_flags;                        \
+        all_flags |= flags;                                                  \
         if (unlikely(flags & float_flag_invalid)) {                          \
             t.VsrW(2 * i) = float_invalid_cvt(env, flags, t.VsrW(2 * i),     \
                                               rnan, 0, GETPC());             \
@@ -2962,6 +2965,7 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
     }                                                                        \
                                                                              \
     *xt = t;                                                                 \
+    env->fp_status.float_exception_flags = all_flags;                        \
     do_float_check_status(env, sfi, GETPC());                                \
 }
 
diff --git a/tests/tcg/ppc64/vsx_f2i_nan.c b/tests/tcg/ppc64/vsx_f2i_nan.c
new file mode 100644
index 000000000000..94b1a4eb02de
--- /dev/null
+++ b/tests/tcg/ppc64/vsx_f2i_nan.c
@@ -0,0 +1,300 @@
+#include <stdio.h>
+#include "qemu/compiler.h"
+
+typedef vector float vsx_float32_vec_t;
+typedef vector double vsx_float64_vec_t;
+typedef vector signed int vsx_int32_vec_t;
+typedef vector unsigned int vsx_uint32_vec_t;
+typedef vector signed long long vsx_int64_vec_t;
+typedef vector unsigned long long vsx_uint64_vec_t;
+
+#define DEFINE_VSX_F2I_FUNC(SRC_T, DEST_T, INSN)                       \
+static inline vsx_##DEST_T##_vec_t                                     \
+    vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(vsx_##SRC_T##_vec_t v) \
+{                                                                      \
+    vsx_##DEST_T##_vec_t result;                                       \
+    asm(#INSN " %x0, %x1" : "=wa" (result) : "wa" (v));                \
+    return result;                                                     \
+}
+
+DEFINE_VSX_F2I_FUNC(float32, int32, xvcvspsxws)
+DEFINE_VSX_F2I_FUNC(float32, uint32, xvcvspuxws)
+DEFINE_VSX_F2I_FUNC(float32, int64, xvcvspsxds)
+DEFINE_VSX_F2I_FUNC(float32, uint64, xvcvspuxds)
+DEFINE_VSX_F2I_FUNC(float64, int32, xvcvdpsxws)
+DEFINE_VSX_F2I_FUNC(float64, uint32, xvcvdpuxws)
+DEFINE_VSX_F2I_FUNC(float64, int64, xvcvdpsxds)
+DEFINE_VSX_F2I_FUNC(float64, uint64, xvcvdpuxds)
+
+static inline vsx_float32_vec_t vsx_float32_is_nan(vsx_float32_vec_t v)
+{
+    vsx_float32_vec_t abs_v;
+    vsx_float32_vec_t result_mask;
+    const vsx_uint32_vec_t f32_pos_inf_bits = {0x7F800000U, 0x7F800000U,
+                                               0x7F800000U, 0x7F800000U};
+
+    asm("xvabssp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
+    asm("vcmpgtuw %0, %1, %2"
+        : "=v" (result_mask)
+        : "v" (abs_v), "v" (f32_pos_inf_bits));
+    return result_mask;
+}
+
+static inline vsx_float64_vec_t vsx_float64_is_nan(vsx_float64_vec_t v)
+{
+    vsx_float64_vec_t abs_v;
+    vsx_float64_vec_t result_mask;
+    const vsx_uint64_vec_t f64_pos_inf_bits = {0x7FF0000000000000ULL,
+                                               0x7FF0000000000000ULL};
+
+    asm("xvabsdp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
+    asm("vcmpgtud %0, %1, %2"
+        : "=v" (result_mask)
+        : "v" (abs_v), "v" (f64_pos_inf_bits));
+    return result_mask;
+}
+
+#define DEFINE_VSX_BINARY_LOGICAL_OP_INSN(LANE_TYPE, OP_NAME, OP_INSN)    \
+static inline vsx_##LANE_TYPE##_vec_t vsx_##LANE_TYPE##_##OP_NAME(        \
+    vsx_##LANE_TYPE##_vec_t a, vsx_##LANE_TYPE##_vec_t b)                 \
+{                                                                         \
+    vsx_##LANE_TYPE##_vec_t result;                                       \
+    asm(#OP_INSN " %x0, %x1, %x2" : "=wa" (result) : "wa" (a), "wa" (b)); \
+    return result;                                                        \
+}
+
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_and, xxland)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_and, xxland)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_and, xxland)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_and, xxland)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_and, xxland)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_and, xxland)
+
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_andc, xxlandc)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_andc, xxlandc)
+
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_or, xxlor)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_or, xxlor)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_or, xxlor)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_or, xxlor)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_or, xxlor)
+DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_or, xxlor)
+
+static inline vsx_int32_vec_t vsx_mask_out_float32_vec_to_int32_vec(
+    vsx_int32_vec_t v)
+{
+    return v;
+}
+static inline vsx_uint32_vec_t vsx_mask_out_float32_vec_to_uint32_vec(
+    vsx_uint32_vec_t v)
+{
+    return v;
+}
+static inline vsx_int64_vec_t vsx_mask_out_float32_vec_to_int64_vec(
+    vsx_int64_vec_t v)
+{
+    return v;
+}
+static inline vsx_uint64_vec_t vsx_mask_out_float32_vec_to_uint64_vec(
+    vsx_uint64_vec_t v)
+{
+    return v;
+}
+
+static inline vsx_int32_vec_t vsx_mask_out_float64_vec_to_int32_vec(
+    vsx_int32_vec_t v)
+{
+#if HOST_BIG_ENDIAN
+    const vsx_int32_vec_t valid_lanes_mask = {-1, 0, -1, 0};
+#else
+    const vsx_int32_vec_t valid_lanes_mask = {0, -1, 0, -1};
+#endif
+
+    return vsx_int32_logical_and(v, valid_lanes_mask);
+}
+
+static inline vsx_uint32_vec_t vsx_mask_out_float64_vec_to_uint32_vec(
+    vsx_uint32_vec_t v)
+{
+    return (vsx_uint32_vec_t)vsx_mask_out_float64_vec_to_int32_vec(
+        (vsx_int32_vec_t)v);
+}
+
+static inline vsx_int64_vec_t vsx_mask_out_float64_vec_to_int64_vec(
+    vsx_int64_vec_t v)
+{
+    return v;
+}
+static inline vsx_uint64_vec_t vsx_mask_out_float64_vec_to_uint64_vec(
+    vsx_uint64_vec_t v)
+{
+    return v;
+}
+
+static inline void print_vsx_float32_vec_elements(FILE *stream,
+                                                  vsx_float32_vec_t vec)
+{
+    fprintf(stream, "%g, %g, %g, %g", (double)vec[0], (double)vec[1],
+            (double)vec[2], (double)vec[3]);
+}
+
+static inline void print_vsx_float64_vec_elements(FILE *stream,
+                                                  vsx_float64_vec_t vec)
+{
+    fprintf(stream, "%.17g, %.17g", vec[0], vec[1]);
+}
+
+static inline void print_vsx_int32_vec_elements(FILE *stream,
+                                                vsx_int32_vec_t vec)
+{
+    fprintf(stream, "%d, %d, %d, %d", vec[0], vec[1], vec[2], vec[3]);
+}
+
+static inline void print_vsx_uint32_vec_elements(FILE *stream,
+                                                 vsx_uint32_vec_t vec)
+{
+    fprintf(stream, "%u, %u, %u, %u", vec[0], vec[1], vec[2], vec[3]);
+}
+
+static inline void print_vsx_int64_vec_elements(FILE *stream,
+                                                vsx_int64_vec_t vec)
+{
+    fprintf(stream, "%lld, %lld", vec[0], vec[1]);
+}
+
+static inline void print_vsx_uint64_vec_elements(FILE *stream,
+                                                 vsx_uint64_vec_t vec)
+{
+    fprintf(stream, "%llu, %llu", vec[0], vec[1]);
+}
+
+#define DEFINE_VSX_ALL_EQ_FUNC(LANE_TYPE, CMP_INSN)                   \
+static inline int vsx_##LANE_TYPE##_all_eq(vsx_##LANE_TYPE##_vec_t a, \
+                                           vsx_##LANE_TYPE##_vec_t b) \
+{                                                                     \
+    unsigned result;                                                  \
+    vsx_##LANE_TYPE##_vec_t is_eq_mask_vec;                           \
+    asm(#CMP_INSN ". %0, %2, %3\n\t"                                  \
+        "mfocrf %1, 2"                                                \
+        : "=v" (is_eq_mask_vec), "=r" (result)                        \
+        : "v" (a), "v" (b)                                            \
+        : "cr6");                                                     \
+    return (int)((result >> 7) & 1u);                                 \
+}
+
+DEFINE_VSX_ALL_EQ_FUNC(int32, vcmpequw)
+DEFINE_VSX_ALL_EQ_FUNC(uint32, vcmpequw)
+DEFINE_VSX_ALL_EQ_FUNC(int64, vcmpequd)
+DEFINE_VSX_ALL_EQ_FUNC(uint64, vcmpequd)
+
+#define DEFINE_VSX_F2I_TEST_FUNC(SRC_T, DEST_T)                          \
+static inline int test_vsx_conv_##SRC_T##_vec_to_##DEST_T##_vec(         \
+    vsx_##SRC_T##_vec_t src_v)                                           \
+{                                                                        \
+    const vsx_##SRC_T##_vec_t is_nan_mask = vsx_##SRC_T##_is_nan(src_v); \
+    const vsx_##SRC_T##_vec_t nan_src_v =                                \
+        vsx_##SRC_T##_logical_and(src_v, is_nan_mask);                   \
+    const vsx_##SRC_T##_vec_t non_nan_src_v =                            \
+        vsx_##SRC_T##_logical_andc(src_v, is_nan_mask);                  \
+                                                                         \
+    const vsx_##DEST_T##_vec_t expected_result =                         \
+        vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec(                    \
+            vsx_##DEST_T##_logical_or(                                   \
+                vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(nan_src_v),  \
+                vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(             \
+                    non_nan_src_v)));                                    \
+    const vsx_##DEST_T##_vec_t actual_result =                           \
+        vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec(                    \
+            vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(src_v));         \
+    const int test_result =                                              \
+        vsx_##DEST_T##_all_eq(expected_result, actual_result);           \
+                                                                         \
+    if (unlikely(test_result == 0)) {                                    \
+        fputs("FAIL: Conversion of " #SRC_T " vector to " #DEST_T        \
+              " vector failed\n", stdout);                               \
+        fputs("Source values: ", stdout);                                \
+        print_vsx_##SRC_T##_vec_elements(stdout, src_v);                 \
+        fputs("\nExpected result: ", stdout);                            \
+        print_vsx_##DEST_T##_vec_elements(stdout, expected_result);      \
+        fputs("\nActual result: ", stdout);                              \
+        print_vsx_##DEST_T##_vec_elements(stdout, actual_result);        \
+        fputs("\n\n", stdout);                                           \
+    }                                                                    \
+                                                                         \
+    return test_result;                                                  \
+}
+
+
+DEFINE_VSX_F2I_TEST_FUNC(float32, int32)
+DEFINE_VSX_F2I_TEST_FUNC(float32, uint32)
+DEFINE_VSX_F2I_TEST_FUNC(float32, int64)
+DEFINE_VSX_F2I_TEST_FUNC(float32, uint64)
+DEFINE_VSX_F2I_TEST_FUNC(float64, int32)
+DEFINE_VSX_F2I_TEST_FUNC(float64, uint32)
+DEFINE_VSX_F2I_TEST_FUNC(float64, int64)
+DEFINE_VSX_F2I_TEST_FUNC(float64, uint64)
+
+static inline vsx_int32_vec_t vsx_int32_vec_from_mask(int mask)
+{
+    const vsx_int32_vec_t bits_to_test = {1, 2, 4, 8};
+    const vsx_int32_vec_t vec_mask = {mask, mask, mask, mask};
+    vsx_int32_vec_t result;
+
+    asm("vcmpequw %0, %1, %2"
+        : "=v" (result)
+        : "v" (vsx_int32_logical_and(vec_mask, bits_to_test)),
+          "v" (bits_to_test));
+    return result;
+}
+
+static inline vsx_int64_vec_t vsx_int64_vec_from_mask(int mask)
+{
+    const vsx_int64_vec_t bits_to_test = {1, 2};
+    const vsx_int64_vec_t vec_mask = {mask, mask};
+    vsx_int64_vec_t result;
+
+    asm("vcmpequd %0, %1, %2"
+        : "=v" (result)
+        : "v" (vsx_int64_logical_and(vec_mask, bits_to_test)),
+          "v" (bits_to_test));
+    return result;
+}
+
+int main(void)
+{
+    const vsx_float32_vec_t f32_iota1 = {1.0f, 2.0f, 3.0f, 4.0f};
+    const vsx_float64_vec_t f64_iota1 = {1.0, 2.0};
+
+    int num_of_tests_failed = 0;
+
+    for (int i = 0; i < 16; i++) {
+        const vsx_int32_vec_t nan_mask = vsx_int32_vec_from_mask(i);
+        const vsx_float32_vec_t f32_v =
+            vsx_float32_logical_or(f32_iota1, (vsx_float32_vec_t)nan_mask);
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float32_vec_to_int32_vec(f32_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float32_vec_to_int64_vec(f32_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float32_vec_to_uint32_vec(f32_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float32_vec_to_uint64_vec(f32_v));
+    }
+
+    for (int i = 0; i < 4; i++) {
+        const vsx_int64_vec_t nan_mask = vsx_int64_vec_from_mask(i);
+        const vsx_float64_vec_t f64_v =
+            vsx_float64_logical_or(f64_iota1, (vsx_float64_vec_t)nan_mask);
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float64_vec_to_int32_vec(f64_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float64_vec_to_int64_vec(f64_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float64_vec_to_uint32_vec(f64_v));
+        num_of_tests_failed +=
+            (int)(!test_vsx_conv_float64_vec_to_uint64_vec(f64_v));
+    }
+
+    printf("%d tests failed\n", num_of_tests_failed);
+    return (int)(num_of_tests_failed != 0);
+}
diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target
index 1d08076756e2..ca8b92946458 100644
--- a/tests/tcg/ppc64/Makefile.target
+++ b/tests/tcg/ppc64/Makefile.target
@@ -16,6 +16,11 @@ PPC64_TESTS=bcdsub non_signalling_xscv
 endif
 $(PPC64_TESTS): CFLAGS += -mpower8-vector
 
+ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),)
+PPC64_TESTS += vsx_f2i_nan
+endif
+vsx_f2i_nan: CFLAGS += -mpower8-vector -I$(SRC_PATH)/include
+
 PPC64_TESTS += mtfsf
 PPC64_TESTS += mffsce
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PULL 3/4] ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses
  2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
  2023-11-21  8:51 ` [PULL 1/4] ppc/pnv: Fix potential overflow in I2C model Cédric Le Goater
  2023-11-21  8:51 ` [PULL 2/4] target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros Cédric Le Goater
@ 2023-11-21  8:51 ` Cédric Le Goater
  2023-11-21  8:51 ` [PULL 4/4] ppc/pnv: Fix PNV I2C invalid status after reset Cédric Le Goater
  2023-11-21 15:12 ` [PULL 0/4] ppc queue Stefan Hajnoczi
  4 siblings, 0 replies; 6+ messages in thread
From: Cédric Le Goater @ 2023-11-21  8:51 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: Daniel Henrique Barboza, Nicholas Piggin, Glenn Miles,
	Cédric Le Goater

From: Glenn Miles <milesg@linux.vnet.ibm.com>

The PNV I2C engines for power9 and power10 were being assigned a base
XSCOM address that was off by one I2C engine's address range such
that engine 0 had engine 1's address and so on.  The xscom address
assignment was being based on the device tree engine numbering, which
starts at 1.  Rather than changing the device tree numbering to start
with 0, the addressing was changed to be based on the existing device
tree numbers minus one.

Fixes: 1ceda19c28a1 ("ppc/pnv: Connect PNV I2C controller to powernv10)
Signed-off-by: Glenn Miles <milesg@linux.vnet.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ppc/pnv.c     | 6 ++++--
 hw/ppc/pnv_i2c.c | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 9c2972733784..0297871bdd5d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1623,7 +1623,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
             return;
         }
         pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE +
-                               chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE,
+                                (chip9->i2c[i].engine - 1) *
+                                        PNV9_XSCOM_I2CM_SIZE,
                                 &chip9->i2c[i].xscom_regs);
         qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0,
                               qdev_get_gpio_in(DEVICE(&chip9->psi),
@@ -1871,7 +1872,8 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
             return;
         }
         pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
-                                chip10->i2c[i].engine * PNV10_XSCOM_I2CM_SIZE,
+                                (chip10->i2c[i].engine - 1) *
+                                        PNV10_XSCOM_I2CM_SIZE,
                                 &chip10->i2c[i].xscom_regs);
         qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
                               qdev_get_gpio_in(DEVICE(&chip10->psi),
diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c
index 483d91d15a77..384442f898bf 100644
--- a/hw/ppc/pnv_i2c.c
+++ b/hw/ppc/pnv_i2c.c
@@ -594,7 +594,7 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt,
     int i2c_offset;
     const char i2c_compat[] = "ibm,power8-i2cm\0ibm,power9-i2cm";
     uint32_t i2c_pcba = PNV9_XSCOM_I2CM_BASE +
-        i2c->engine * PNV9_XSCOM_I2CM_SIZE;
+        (i2c->engine - 1) * PNV9_XSCOM_I2CM_SIZE;
     uint32_t reg[2] = {
         cpu_to_be32(i2c_pcba),
         cpu_to_be32(PNV9_XSCOM_I2CM_SIZE)
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PULL 4/4] ppc/pnv: Fix PNV I2C invalid status after reset
  2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
                   ` (2 preceding siblings ...)
  2023-11-21  8:51 ` [PULL 3/4] ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses Cédric Le Goater
@ 2023-11-21  8:51 ` Cédric Le Goater
  2023-11-21 15:12 ` [PULL 0/4] ppc queue Stefan Hajnoczi
  4 siblings, 0 replies; 6+ messages in thread
From: Cédric Le Goater @ 2023-11-21  8:51 UTC (permalink / raw)
  To: qemu-ppc, qemu-devel
  Cc: Daniel Henrique Barboza, Nicholas Piggin, Glenn Miles,
	Cédric Le Goater

From: Glenn Miles <milesg@linux.vnet.ibm.com>

The PNV I2C Controller was clearing the status register
after a reset without repopulating the "upper threshold
for I2C ports", "Command Complete" and the SCL/SDA input
level fields.

Fixed this for resets caused by a system reset as well
as from writing to the "Immediate Reset" register.

Fixes: 263b81ee15af ("ppc/pnv: Add an I2C controller model")
Signed-off-by: Glenn Miles <milesg@linux.vnet.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ppc/pnv_i2c.c | 42 ++++++++++++++++++------------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c
index 384442f898bf..656a48eebe51 100644
--- a/hw/ppc/pnv_i2c.c
+++ b/hw/ppc/pnv_i2c.c
@@ -463,6 +463,23 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr,
     return val;
 }
 
+static void pnv_i2c_reset(void *dev)
+{
+    PnvI2C *i2c = PNV_I2C(dev);
+
+    memset(i2c->regs, 0, sizeof(i2c->regs));
+
+    i2c->regs[I2C_STAT_REG] =
+        SETFIELD(I2C_STAT_UPPER_THRS, 0ull, i2c->num_busses - 1) |
+        I2C_STAT_CMD_COMP | I2C_STAT_SCL_INPUT_LEVEL |
+        I2C_STAT_SDA_INPUT_LEVEL;
+    i2c->regs[I2C_EXTD_STAT_REG] =
+        SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) |
+        SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */
+
+    fifo8_reset(&i2c->fifo);
+}
+
 static void pnv_i2c_xscom_write(void *opaque, hwaddr addr,
                                 uint64_t val, unsigned size)
 {
@@ -500,16 +517,7 @@ static void pnv_i2c_xscom_write(void *opaque, hwaddr addr,
         break;
 
     case I2C_RESET_I2C_REG:
-        i2c->regs[I2C_MODE_REG] = 0;
-        i2c->regs[I2C_CMD_REG] = 0;
-        i2c->regs[I2C_WATERMARK_REG] = 0;
-        i2c->regs[I2C_INTR_MASK_REG] = 0;
-        i2c->regs[I2C_INTR_COND_REG] = 0;
-        i2c->regs[I2C_INTR_RAW_COND_REG] = 0;
-        i2c->regs[I2C_STAT_REG] = 0;
-        i2c->regs[I2C_RESIDUAL_LEN_REG] = 0;
-        i2c->regs[I2C_EXTD_STAT_REG] &=
-            (I2C_EXTD_STAT_FIFO_SIZE | I2C_EXTD_STAT_I2C_VERSION);
+        pnv_i2c_reset(i2c);
         break;
 
     case I2C_RESET_ERRORS:
@@ -621,20 +629,6 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt,
     return 0;
 }
 
-static void pnv_i2c_reset(void *dev)
-{
-    PnvI2C *i2c = PNV_I2C(dev);
-
-    memset(i2c->regs, 0, sizeof(i2c->regs));
-
-    i2c->regs[I2C_STAT_REG] = I2C_STAT_CMD_COMP;
-    i2c->regs[I2C_EXTD_STAT_REG] =
-        SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) |
-        SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */
-
-    fifo8_reset(&i2c->fifo);
-}
-
 static void pnv_i2c_realize(DeviceState *dev, Error **errp)
 {
     PnvI2C *i2c = PNV_I2C(dev);
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PULL 0/4] ppc queue
  2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
                   ` (3 preceding siblings ...)
  2023-11-21  8:51 ` [PULL 4/4] ppc/pnv: Fix PNV I2C invalid status after reset Cédric Le Goater
@ 2023-11-21 15:12 ` Stefan Hajnoczi
  4 siblings, 0 replies; 6+ messages in thread
From: Stefan Hajnoczi @ 2023-11-21 15:12 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: qemu-ppc, qemu-devel, Daniel Henrique Barboza, Nicholas Piggin,
	Cédric Le Goater

[-- Attachment #1: Type: text/plain, Size: 115 bytes --]

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-11-21 15:14 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-21  8:51 [PULL 0/4] ppc queue Cédric Le Goater
2023-11-21  8:51 ` [PULL 1/4] ppc/pnv: Fix potential overflow in I2C model Cédric Le Goater
2023-11-21  8:51 ` [PULL 2/4] target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros Cédric Le Goater
2023-11-21  8:51 ` [PULL 3/4] ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses Cédric Le Goater
2023-11-21  8:51 ` [PULL 4/4] ppc/pnv: Fix PNV I2C invalid status after reset Cédric Le Goater
2023-11-21 15:12 ` [PULL 0/4] ppc queue Stefan Hajnoczi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).