From 791fe5ecf909d573bcbf353b677b9404f9da0ed4 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 27 May 2019 22:19:27 +0200 Subject: [PATCH] Expose rdrand and f16c through cpuid also if the host only has avx. The amd64 CPUID dirtyhelpers are mostly static since they emulate some existing CPU "family". The avx2 ("i7-4910MQ") CPUID variant however can "dynamicly" enable rdrand and/or f16c if the host supports them. Do the same for the avx_and_cx16 ("i5-2300") CPUID variant. https://bugs.kde.org/show_bug.cgi?id=408009 --- NEWS | 1 + VEX/priv/guest_amd64_defs.h | 4 +++- VEX/priv/guest_amd64_helpers.c | 14 +++++++++++--- VEX/priv/guest_amd64_toIR.c | 3 ++- coregrind/m_machine.c | 8 ++++---- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 753171f7a..004e67700 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,7 @@ where XXXXXX is the bug number as listed below. 407218 Add support for the copy_file_range syscall 407307 Intercept stpcpy also in ld.so for arm64 407764 drd cond_post_wait gets wrong (?) condition on s390x z13 system +408009 Expose rdrand and f16c even on avx if host cpu supports them n-i-bz Fix minor one time leaks in dhat. n-i-bz Add --run-cxx-freeres=no in outer args to avoid inner crashes. diff --git a/VEX/priv/guest_amd64_defs.h b/VEX/priv/guest_amd64_defs.h index 4f34b41cb..a5de527d2 100644 --- a/VEX/priv/guest_amd64_defs.h +++ b/VEX/priv/guest_amd64_defs.h @@ -165,7 +165,9 @@ extern void amd64g_dirtyhelper_storeF80le ( Addr/*addr*/, ULong/*data*/ ); extern void amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st ); extern void amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st ); extern void amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st ); -extern void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st ); +extern void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st, + ULong hasF16C, + ULong hasRDRAND ); extern void amd64g_dirtyhelper_CPUID_avx2 ( VexGuestAMD64State* st, ULong hasF16C, ULong hasRDRAND ); diff --git a/VEX/priv/guest_amd64_helpers.c b/VEX/priv/guest_amd64_helpers.c index e4cf7e203..182bae0bc 100644 --- a/VEX/priv/guest_amd64_helpers.c +++ b/VEX/priv/guest_amd64_helpers.c @@ -3141,8 +3141,11 @@ void amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st ) address sizes : 36 bits physical, 48 bits virtual power management: */ -void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st ) +void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st, + ULong hasF16C, ULong hasRDRAND ) { + vassert((hasF16C >> 1) == 0ULL); + vassert((hasRDRAND >> 1) == 0ULL); # define SET_ABCD(_a,_b,_c,_d) \ do { st->guest_RAX = (ULong)(_a); \ st->guest_RBX = (ULong)(_b); \ @@ -3157,9 +3160,14 @@ void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st ) case 0x00000000: SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69); break; - case 0x00000001: - SET_ABCD(0x000206a7, 0x00100800, 0x1f9ae3bf, 0xbfebfbff); + case 0x00000001: { + // As a baseline, advertise neither F16C (ecx:29) nor RDRAND (ecx:30), + // but patch in support for them as directed by the caller. + UInt ecx_extra + = (hasF16C ? (1U << 29) : 0) | (hasRDRAND ? (1U << 30) : 0); + SET_ABCD(0x000206a7, 0x00100800, (0x1f9ae3bf | ecx_extra), 0xbfebfbff); break; + } case 0x00000002: SET_ABCD(0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000); break; diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c index 56e992cd6..96dee3818 100644 --- a/VEX/priv/guest_amd64_toIR.c +++ b/VEX/priv/guest_amd64_toIR.c @@ -22007,7 +22007,8 @@ Long dis_ESC_0F ( vassert(fName); vassert(fAddr); IRExpr** args = NULL; - if (fAddr == &amd64g_dirtyhelper_CPUID_avx2) { + if (fAddr == &amd64g_dirtyhelper_CPUID_avx2 + || fAddr == &amd64g_dirtyhelper_CPUID_avx_and_cx16) { Bool hasF16C = (archinfo->hwcaps & VEX_HWCAPS_AMD64_F16C) != 0; Bool hasRDRAND = (archinfo->hwcaps & VEX_HWCAPS_AMD64_RDRAND) != 0; args = mkIRExprVec_3(IRExpr_GSPTR(), diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 3536e5715..56a28d108 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -1076,10 +1076,10 @@ Bool VG_(machine_get_hwcaps)( void ) have_avx2 = (ebx & (1<<5)) != 0; /* True => have AVX2 */ } - /* Sanity check for RDRAND and F16C. These don't actually *need* AVX2, but - it's convenient to restrict them to the AVX2 case since the simulated - CPUID we'll offer them on has AVX2 as a base. */ - if (!have_avx2) { + /* Sanity check for RDRAND and F16C. These don't actually *need* AVX, but + it's convenient to restrict them to the AVX case since the simulated + CPUID we'll offer them on has AVX as a base. */ + if (!have_avx) { have_f16c = False; have_rdrand = False; } -- 2.11.4.GIT