Skip to content

Implement hashst(p) and hashchk(p) instructions #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions linux-headers/asm-powerpc/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ struct kvm_ppc_cpu_char {
#define KVM_REG_PPC_SIER3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc3)
#define KVM_REG_PPC_DAWR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc4)
#define KVM_REG_PPC_DAWRX1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc5)
/* FIXME: KVM hasn't exposed these registers yet */
#define KVM_REG_PPC_HASHKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x00)
#define KVM_REG_PPC_HASHPKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x00)

/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
Expand Down
2 changes: 2 additions & 0 deletions target/ppc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_GIVOR14 (0x1BD)
#define SPR_TIR (0x1BE)
#define SPR_PTCR (0x1D0)
#define SPR_POWER_HASHKEYR (0x1D4)
#define SPR_POWER_HASHPKEYR (0x1D5)
#define SPR_BOOKE_SPEFSCR (0x200)
#define SPR_Exxx_BBEAR (0x201)
#define SPR_Exxx_BBTAR (0x202)
Expand Down
7 changes: 7 additions & 0 deletions target/ppc/cpu_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -6478,6 +6478,13 @@ static void init_proc_POWER10(CPUPPCState *env)
spr_read_generic, spr_write_generic,
KVM_REG_PPC_PSSCR, 0);

spr_register_kvm(env, SPR_POWER_HASHKEYR, "HASHPKEYR",
SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic,
KVM_REG_PPC_HASHKEYR, 0x0);
spr_register_kvm(env, SPR_POWER_HASHPKEYR, "HASHPKEYR",
SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic,
KVM_REG_PPC_HASHPKEYR, 0x0);

/* env variables */
env->dcache_line_size = 128;
env->icache_line_size = 128;
Expand Down
83 changes: 83 additions & 0 deletions target/ppc/excp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,89 @@ 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;
}
Comment on lines +2182 to +2185
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum... it's hard to tell if the pseudo-code is using PowerISA-indexing or everybody-else-indexing. The original paper uses "k[m-1]..k[0] = key words," so I'd expect k[0] to be the least significant halfword.

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];
}

/* TODO: check this implementation correctness; make it better */
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);
}

#define HELPER_HASH(op, key, store) \
void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
target_ulong rb) \
{ \
uint64_t chash = hash_digest(ra, rb, key), lhash; \
\
if (store) { \
cpu_stq_data_ra(env, ea, chash, GETPC()); \
} else { \
lhash = cpu_ldq_data_ra(env, ea, GETPC()); \
if (lhash != chash) { \
/* hashes don't match, trap */ \
raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, \
POWERPC_EXCP_TRAP, GETPC()); \
} \
} \
}

HELPER_HASH(HASHST, env->spr[SPR_POWER_HASHKEYR], true)
HELPER_HASH(HASHCHK, env->spr[SPR_POWER_HASHKEYR], false)
HELPER_HASH(HASHSTP, env->spr[SPR_POWER_HASHPKEYR], true)
HELPER_HASH(HASHCHKP, env->spr[SPR_POWER_HASHPKEYR], false)

#if !defined(CONFIG_USER_ONLY)

#ifdef CONFIG_TCG
Expand Down
4 changes: 4 additions & 0 deletions target/ppc/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ 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)
DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl)
DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(store_msr, void, env, tl)
DEF_HELPER_1(rfi, void, env)
Expand Down
10 changes: 10 additions & 0 deletions target/ppc/insn32.decode
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,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

Expand Down Expand Up @@ -281,6 +284,13 @@ 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
HASHSTP 011111 ..... ..... ..... 1010010010 . @X_DW
HASHCHKP 011111 ..... ..... ..... 1010110010 . @X_DW

### Float-Point Load Instructions

LFS 110000 ..... ..... ................ @D
Expand Down
17 changes: 17 additions & 0 deletions target/ppc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,18 @@ typedef struct opcode_t {

#define CHK_NONE

/* Helper for priv. check to be used in decodetree */
static bool do_check_sv(DisasContext *ctx)
{
#if !defined(CONFIG_USER_ONLY)
if (likely(ctx->pr != 0)) {
return false;
}
#endif
gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return true;
}

/*****************************************************************************/
/* PowerPC instructions table */

Expand Down Expand Up @@ -6547,6 +6559,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
Expand Down
33 changes: 33 additions & 0 deletions target/ppc/translate/fixedpoint-impl.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -492,3 +492,36 @@ static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
#endif
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 (unlikely(priv && do_check_sv(ctx))) {
/* if instruction is privileged but the context is in user space */
return true;
}

if (unlikely(a->ra == 0)) {
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)
TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)