Skip to content
Permalink
Browse files

rdrand/rdseed support

Signed-off-by: Dave Tian <dave.tian@fortanix.com>
  • Loading branch information...
Dave Tian
Dave Tian committed Jun 29, 2018
1 parent 16ccd19 commit 5986cc4a0c6bf2d41822df15e8f074437c32e391
@@ -192,6 +192,10 @@ extern void amd64g_dirtyhelper_OUT ( ULong portno, ULong data,
extern void amd64g_dirtyhelper_SxDT ( void* address,
ULong op /* 0 or 1 */ );

extern ULong amd64g_dirtyhelper_rdrand ( ULong sz/*4,8*/ );
extern ULong amd64g_dirtyhelper_rdseed ( ULong sz/*4,8*/ );


/* Helps with PCMP{I,E}STR{I,M}.
CALLED FROM GENERATED CODE: DIRTY HELPER(s). (But not really,
@@ -3689,6 +3689,73 @@ void amd64g_dirtyhelper_SxDT ( void *address, ULong op ) {
# endif
}

/* Dirty helper for rdrand instruction */
ULong amd64g_dirtyhelper_rdrand ( ULong sz/*4,8*/ ) {
# if defined(__x86_64__)
ULong res = 0;
UInt res32 = 0;

if ((sz != 4) && (sz != 8))
vpanic("amd64g_dirtyhelper_rdrand: invalid sz");

if (sz == 4)
__asm__ __volatile__("1: rdrand %%eax\n\t"
"jnc 1b\n\t"
"movl %%eax, %0\n\t"
: "=r"(res32)
:
: "eax");
else
__asm__ __volatile__("1: rdrand %%rax\n\t"
"jnc 1b\n\t"
"movq %%rax, %0\n\t"
: "=r"(res)
:
: "rax");

if (sz == 4)
res = (ULong)res32;

return res;
# else
return 0;
# endif
}

/* Dirty helper for rdseed instruction */
ULong amd64g_dirtyhelper_rdseed ( ULong sz/*4,8*/ ) {
# if defined(__x86_64__)
ULong res = 0;
UInt res32 = 0;

if ((sz != 4) && (sz != 8))
vpanic("amd64g_dirtyhelper_rdseed: invalid sz");

if (sz == 4)
__asm__ __volatile__("1: rdseed %%eax\n\t"
"jnc 1b\n\t"
"movl %%eax, %0\n\t"
: "=r"(res32)
:
: "eax");
else
__asm__ __volatile__("1: rdseed %%rax\n\t"
"jnc 1b\n\t"
"movq %%rax, %0\n\t"
: "=r"(res)
:
: "rax");

if (sz == 4)
res = (ULong)res32;

return res;
# else
return 0;
# endif
}


/*---------------------------------------------------------------*/
/*--- Helpers for MMX/SSE/SSE2. ---*/
/*---------------------------------------------------------------*/
@@ -1947,6 +1947,24 @@ void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, ULong base_op )
}


/* Set the carry flag (initially for rdrand/rdseed) */
static
void setCarryFlag ( void )
{
IRTemp oldflags = newTemp(Ity_I64);
IRTemp newflags = newTemp(Ity_I64);

assign( oldflags, mk_amd64g_calculate_rflags_all() );
assign( newflags, binop(Iop_Or64, mkexpr(oldflags), mkU64(1<<AMD64G_CC_SHIFT_C)));

/* Abuse the copy opc */
stmt( IRStmt_Put( OFFB_CC_OP, mkU64(AMD64G_CC_OP_COPY)) );
stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(newflags)) );
stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0)) );
stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0)) );
}


/* -------------- Condition codes. -------------- */

/* Condition codes, using the AMD encoding. */
}

case 0xC7: { /* CMPXCHG8B Ev, CMPXCHG16B Ev */
/* Unfortunately, this could also be rdrand/rdseed */
modrm = getUChar(delta);
if (((modrm>>6) & 0x3) == 0x3) {
/* rdrand/rdseed */
ULong size = (pfx & PFX_REXW) ? 8 : 4;
UInt reg = (modrm & 0x3);
IRTemp val = newTemp(Ity_I64);
IRExpr **args = mkIRExprVec_1(mkU64(size));
IRDirty *d = NULL;

if ((((modrm>>3) & 0x7) == 0x6) && (archinfo->hwcaps & VEX_HWCAPS_AMD64_RDRAND)) {
/* Handle rdrand */
d = unsafeIRDirty_1_N (val,
0,
"amd64g_dirtyhelper_rdrand",
&amd64g_dirtyhelper_rdrand,
args);
stmt( IRStmt_Dirty(d) );

/* Update the guest reg */
if (size == 4)
putIReg32(reg, unop(Iop_64to32, mkexpr(val)));
else
putIReg64(reg, mkexpr(val));

/* Update the guest carry flag */
setCarryFlag();
DIP("rdrand\n");
}
else if ((((modrm>>3) & 0x7) == 0x7) && (archinfo->hwcaps & VEX_HWCAPS_AMD64_RDSEED)) {
/* Handle rdseed */
d = unsafeIRDirty_1_N (val,
0,
"amd64g_dirtyhelper_rdseed",
&amd64g_dirtyhelper_rdseed,
args);
stmt( IRStmt_Dirty(d) );

/* Update the guest reg */
if (size == 4)
putIReg32(reg, unop(Iop_64to32, mkexpr(val)));
else
putIReg64(reg, mkexpr(val));

/* Update the guest carry flag */
setCarryFlag();
DIP("rdseed\n");
} else
goto decode_failure;

delta++;
return delta;
}

/* CMPXCHG */
IRType elemTy = sz==4 ? Ity_I32 : Ity_I64;
IRTemp expdHi = newTemp(elemTy);
IRTemp expdLo = newTemp(elemTy);
if (sz != 4 && sz != 8) goto decode_failure;
if (sz == 8 && !(archinfo->hwcaps & VEX_HWCAPS_AMD64_CX16))
goto decode_failure;
modrm = getUChar(delta);
if (epartIsReg(modrm)) goto decode_failure;
if (gregLO3ofRM(modrm) != 1) goto decode_failure;
if (haveF2orF3(pfx)) {
@@ -4958,7 +4958,9 @@ HInstrArray* iselSB_AMD64 ( const IRSB* bb,
| VEX_HWCAPS_AMD64_AVX
| VEX_HWCAPS_AMD64_RDTSCP
| VEX_HWCAPS_AMD64_BMI
| VEX_HWCAPS_AMD64_AVX2)));
| VEX_HWCAPS_AMD64_AVX2
| VEX_HWCAPS_AMD64_RDRAND
| VEX_HWCAPS_AMD64_RDSEED)));

/* Check that the host's endianness is as expected. */
vassert(archinfo_host->endness == VexEndnessLE);
@@ -98,6 +98,8 @@ typedef
#define VEX_HWCAPS_AMD64_RDTSCP (1<<9) /* RDTSCP instruction */
#define VEX_HWCAPS_AMD64_BMI (1<<10) /* BMI1 instructions */
#define VEX_HWCAPS_AMD64_AVX2 (1<<11) /* AVX2 instructions */
#define VEX_HWCAPS_AMD64_RDRAND (1<<12) /* rdrand instructions */
#define VEX_HWCAPS_AMD64_RDSEED (1<<13) /* rdseed instructions */

/* ppc32: baseline capability is integer only */
#define VEX_HWCAPS_PPC32_F (1<<8) /* basic (non-optional) FP */
@@ -946,6 +946,7 @@ Bool VG_(machine_get_hwcaps)( void )
{ Bool have_sse3, have_cx8, have_cx16;
Bool have_lzcnt, have_avx, have_bmi, have_avx2;
Bool have_rdtscp;
Bool have_rdrand, have_rdseed;
UInt eax, ebx, ecx, edx, max_basic, max_extended;
ULong xgetbv_0 = 0;
HChar vstr[13];
@@ -1051,6 +1052,13 @@ Bool VG_(machine_get_hwcaps)( void )
have_avx2 = (ebx & (1<<5)) != 0; /* True => have AVX2 */
}

/* Check for rdrand */
VG_(cpuid)(0x01, 0, &eax, &ebx, &ecx, &edx);
have_rdrand = (ecx & (1<<30)) != 0;
/* Check for rdseed */
VG_(cpuid)(0x07, 0, &eax, &ebx, &ecx, &edx);
have_rdseed = (ebx & (1<<18)) != 0;

va = VexArchAMD64;
vai.endness = VexEndnessLE;
vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
@@ -1059,7 +1067,9 @@ Bool VG_(machine_get_hwcaps)( void )
| (have_avx ? VEX_HWCAPS_AMD64_AVX : 0)
| (have_bmi ? VEX_HWCAPS_AMD64_BMI : 0)
| (have_avx2 ? VEX_HWCAPS_AMD64_AVX2 : 0)
| (have_rdtscp ? VEX_HWCAPS_AMD64_RDTSCP : 0);
| (have_rdtscp ? VEX_HWCAPS_AMD64_RDTSCP : 0)
| (have_rdrand ? VEX_HWCAPS_AMD64_RDRAND : 0)
| (have_rdseed ? VEX_HWCAPS_AMD64_RDSEED : 0);

VG_(machine_get_cache_info)(&vai);

0 comments on commit 5986cc4

Please sign in to comment.
You can’t perform that action at this time.