diff mbox series

[v4,2/3] target/ppc: Implement hashst and hashchk

Message ID 20220715205439.161110-3-victor.colombo@eldorado.org.br (mailing list archive)
State New, archived
Headers show
Series Implement Power ISA 3.1B hash insns | expand

Commit Message

Víctor Colombo July 15, 2022, 8:54 p.m. UTC
Implementation for instructions hashst and hashchk, which were added
in Power ISA 3.1B.

It was decided to implement the hash algorithm from ground up in this
patch exactly as described in Power ISA.

Signed-off-by: Víctor Colombo <victor.colombo@eldorado.org.br>
---
 target/ppc/excp_helper.c                   | 82 ++++++++++++++++++++++
 target/ppc/helper.h                        |  2 +
 target/ppc/insn32.decode                   |  8 +++
 target/ppc/translate.c                     |  5 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 32 +++++++++
 5 files changed, 129 insertions(+)

Comments

Lucas Mateus Martins Araujo e Castro July 18, 2022, 6:23 p.m. UTC | #1
On 15/07/2022 17:54, Víctor Colombo wrote:
> Implementation for instructions hashst and hashchk, which were added
> in Power ISA 3.1B.
>
> It was decided to implement the hash algorithm from ground up in this
> patch exactly as described in Power ISA.
>
> Signed-off-by: Víctor Colombo<victor.colombo@eldorado.org.br>
> ---
>   target/ppc/excp_helper.c                   | 82 ++++++++++++++++++++++
>   target/ppc/helper.h                        |  2 +
>   target/ppc/insn32.decode                   |  8 +++
>   target/ppc/translate.c                     |  5 ++
>   target/ppc/translate/fixedpoint-impl.c.inc | 32 +++++++++
>   5 files changed, 129 insertions(+)
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index cb752b184a..fa5a737e22 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -2174,6 +2174,88 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
>   #endif
>   #endif
>
> +static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
> +{
> +    const uint16_t c = 0xfffc;
> +    const uint64_t z0 = 0xfa2561cdf44ac398ULL;
> +    uint16_t z = 0, temp;
> +    uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
> +
> +    for (int i = 3; i >= 0; i--) {
> +        k[i] = key & 0xffff;
> +        key >>= 16;
> +    }
> +    xleft[0] = x & 0xffff;
> +    xright[0] = (x >> 16) & 0xffff;
> +
> +    for (int i = 0; i < 28; i++) {
> +        z = (z0 >> (63 - i)) & 1;
> +        temp = ror16(k[i + 3], 3) ^ k[i + 1];
> +        k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
> +    }
> +
> +    for (int i = 0; i < 8; i++) {
> +        eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
> +        eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
> +        eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
> +        eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
> +    }
> +
> +    for (int i = 0; i < 32; i++) {
> +        fxleft[i] = (rol16(xleft[i], 1) &
> +            rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
> +        xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
> +        xright[i + 1] = xleft[i];
> +    }
> +
> +    return (((uint32_t)xright[32]) << 16) | xleft[32];
> +}
> +
> +static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
> +{
> +    uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
> +    uint64_t stage1_h, stage1_l;
> +
> +    for (int i = 0; i < 4; i++) {
> +        stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
> +        stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
> +        stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
> +        stage0_l |= (ra & 0xff) << (8 * 2 * i);
> +        rb >>= 8;
> +        ra >>= 8;
> +    }
> +
> +    stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
> +    stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
> +    stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
> +    stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
> +
> +    return stage1_h ^ stage1_l;
> +}
> +
> +#include "qemu/guest-random.h"
> +
> +#define HELPER_HASH(op, key, store)                                           \
> +void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra,          \
> +                 target_ulong rb)                                             \
> +{                                                                             \
> +    uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;         \
> +                                                                              \
> +    if (store) {                                                              \
> +        cpu_stq_data_ra(env, ea, calculated_hash, GETPC());                   \
> +    } else {                                                                  \
> +        loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());                      \
> +        if (loaded_hash != calculated_hash) {                                 \
> +            /* hashes don't match, trap */                                    \
> +            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,                 \
> +                POWERPC_EXCP_TRAP, GETPC());                                  \
> +        }                                                                     \
> +    }                                                                         \
> +}
Maybe this macro could be 2 separate helpers so it's easier to debug.

Reviewed-by: Lucas Mateus Castro <lucas.araujo@eldorado.org.br>

> +
> +HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true)
> +HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false)
> +
>   #if !defined(CONFIG_USER_ONLY)
>
>   #ifdef CONFIG_TCG
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 159b352f6e..5817af632b 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -4,6 +4,8 @@ DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
>   #if defined(TARGET_PPC64)
>   DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
>   #endif
> +DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
> +DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
>   #if !defined(CONFIG_USER_ONLY)
>   DEF_HELPER_2(store_msr, void, env, tl)
>   DEF_HELPER_1(rfi, void, env)
> diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
> index eb41efc100..544514565c 100644
> --- a/target/ppc/insn32.decode
> +++ b/target/ppc/insn32.decode
> @@ -172,6 +172,9 @@
>   @X_TSX          ...... ..... ra:5 rb:5 .......... .             &X rt=%x_rt_tsx
>   @X_TSXP         ...... ..... ra:5 rb:5 .......... .             &X rt=%rt_tsxp
>
> +%x_dw           0:1 21:5 !function=dw_compose_ea
> +@X_DW           ...... ..... ra:5 rb:5 .......... .             &X rt=%x_dw
> +
>   &X_frtp_vrb     frtp vrb
>   @X_frtp_vrb     ...... ....0 ..... vrb:5 .......... .           &X_frtp_vrb frtp=%x_frtp
>
> @@ -323,6 +326,11 @@ CNTTZDM         011111 ..... ..... ..... 1000111011 -   @X
>   PDEPD           011111 ..... ..... ..... 0010011100 -   @X
>   PEXTD           011111 ..... ..... ..... 0010111100 -   @X
>
> +# Fixed-Point Hash Instructions
> +
> +HASHST          011111 ..... ..... ..... 1011010010 .   @X_DW
> +HASHCHK         011111 ..... ..... ..... 1011110010 .   @X_DW
> +
>   ## BCD Assist
>
>   ADDG6S          011111 ..... ..... ..... - 001001010 -  @X
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 5a18ee577f..3bdd3e6e3e 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -6394,6 +6394,11 @@ static int times_16(DisasContext *ctx, int x)
>       return x * 16;
>   }
>
> +static int64_t dw_compose_ea(DisasContext *ctx, int x)
> +{
> +    return deposit64(0xfffffffffffffe00, 3, 6, x);
> +}
> +
>   /*
>    * Helpers for trans_* functions to check for specific insns flags.
>    * Use token pasting to ensure that we use the proper flag with the
> diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
> index db14d3bebc..41c06de8a2 100644
> --- a/target/ppc/translate/fixedpoint-impl.c.inc
> +++ b/target/ppc/translate/fixedpoint-impl.c.inc
> @@ -540,3 +540,35 @@ static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
>       gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
>       return true;
>   }
> +
> +static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
> +    void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
> +{
> +    TCGv ea;
> +
> +    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
> +        /* if version is before v3.1, this operation is a nop */
> +        return true;
> +    }
> +
> +    if (priv) {
> +        /* if instruction is privileged but the context is in user space */
> +        REQUIRE_SV(ctx);
> +    }
> +
> +    if (unlikely(a->ra == 0)) {
> +        /* if RA=0, the instruction form is invalid */
> +        gen_invalid(ctx);
> +        return true;
> +    }
> +
> +    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
> +    helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
> +
> +    tcg_temp_free(ea);
> +
> +    return true;
> +}
> +
> +TRANS(HASHST, do_hash, false, gen_helper_HASHST)
> +TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
> --
> 2.25.1
>
>
diff mbox series

Patch

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index cb752b184a..fa5a737e22 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2174,6 +2174,88 @@  void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
 #endif
 #endif
 
+static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
+{
+    const uint16_t c = 0xfffc;
+    const uint64_t z0 = 0xfa2561cdf44ac398ULL;
+    uint16_t z = 0, temp;
+    uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
+
+    for (int i = 3; i >= 0; i--) {
+        k[i] = key & 0xffff;
+        key >>= 16;
+    }
+    xleft[0] = x & 0xffff;
+    xright[0] = (x >> 16) & 0xffff;
+
+    for (int i = 0; i < 28; i++) {
+        z = (z0 >> (63 - i)) & 1;
+        temp = ror16(k[i + 3], 3) ^ k[i + 1];
+        k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
+    }
+
+    for (int i = 0; i < 8; i++) {
+        eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
+        eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
+        eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
+        eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
+    }
+
+    for (int i = 0; i < 32; i++) {
+        fxleft[i] = (rol16(xleft[i], 1) &
+            rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
+        xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
+        xright[i + 1] = xleft[i];
+    }
+
+    return (((uint32_t)xright[32]) << 16) | xleft[32];
+}
+
+static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
+{
+    uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
+    uint64_t stage1_h, stage1_l;
+
+    for (int i = 0; i < 4; i++) {
+        stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
+        stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
+        stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
+        stage0_l |= (ra & 0xff) << (8 * 2 * i);
+        rb >>= 8;
+        ra >>= 8;
+    }
+
+    stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
+    stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
+    stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
+    stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
+
+    return stage1_h ^ stage1_l;
+}
+
+#include "qemu/guest-random.h"
+
+#define HELPER_HASH(op, key, store)                                           \
+void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra,          \
+                 target_ulong rb)                                             \
+{                                                                             \
+    uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;         \
+                                                                              \
+    if (store) {                                                              \
+        cpu_stq_data_ra(env, ea, calculated_hash, GETPC());                   \
+    } else {                                                                  \
+        loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());                      \
+        if (loaded_hash != calculated_hash) {                                 \
+            /* hashes don't match, trap */                                    \
+            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,                 \
+                POWERPC_EXCP_TRAP, GETPC());                                  \
+        }                                                                     \
+    }                                                                         \
+}
+
+HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true)
+HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false)
+
 #if !defined(CONFIG_USER_ONLY)
 
 #ifdef CONFIG_TCG
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 159b352f6e..5817af632b 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -4,6 +4,8 @@  DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #endif
+DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
+DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_2(store_msr, void, env, tl)
 DEF_HELPER_1(rfi, void, env)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index eb41efc100..544514565c 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -172,6 +172,9 @@ 
 @X_TSX          ...... ..... ra:5 rb:5 .......... .             &X rt=%x_rt_tsx
 @X_TSXP         ...... ..... ra:5 rb:5 .......... .             &X rt=%rt_tsxp
 
+%x_dw           0:1 21:5 !function=dw_compose_ea
+@X_DW           ...... ..... ra:5 rb:5 .......... .             &X rt=%x_dw
+
 &X_frtp_vrb     frtp vrb
 @X_frtp_vrb     ...... ....0 ..... vrb:5 .......... .           &X_frtp_vrb frtp=%x_frtp
 
@@ -323,6 +326,11 @@  CNTTZDM         011111 ..... ..... ..... 1000111011 -   @X
 PDEPD           011111 ..... ..... ..... 0010011100 -   @X
 PEXTD           011111 ..... ..... ..... 0010111100 -   @X
 
+# Fixed-Point Hash Instructions
+
+HASHST          011111 ..... ..... ..... 1011010010 .   @X_DW
+HASHCHK         011111 ..... ..... ..... 1011110010 .   @X_DW
+
 ## BCD Assist
 
 ADDG6S          011111 ..... ..... ..... - 001001010 -  @X
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 5a18ee577f..3bdd3e6e3e 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6394,6 +6394,11 @@  static int times_16(DisasContext *ctx, int x)
     return x * 16;
 }
 
+static int64_t dw_compose_ea(DisasContext *ctx, int x)
+{
+    return deposit64(0xfffffffffffffe00, 3, 6, x);
+}
+
 /*
  * Helpers for trans_* functions to check for specific insns flags.
  * Use token pasting to ensure that we use the proper flag with the
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
index db14d3bebc..41c06de8a2 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -540,3 +540,35 @@  static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
     gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
     return true;
 }
+
+static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
+    void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
+{
+    TCGv ea;
+
+    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
+        /* if version is before v3.1, this operation is a nop */
+        return true;
+    }
+
+    if (priv) {
+        /* if instruction is privileged but the context is in user space */
+        REQUIRE_SV(ctx);
+    }
+
+    if (unlikely(a->ra == 0)) {
+        /* if RA=0, the instruction form is invalid */
+        gen_invalid(ctx);
+        return true;
+    }
+
+    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
+    helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
+
+    tcg_temp_free(ea);
+
+    return true;
+}
+
+TRANS(HASHST, do_hash, false, gen_helper_HASHST)
+TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)