diff --git a/Implement-emulated-system-registers.-Fixes-392146.patch b/Implement-emulated-system-registers.-Fixes-392146.patch new file mode 100644 index 0000000..9d9f076 --- /dev/null +++ b/Implement-emulated-system-registers.-Fixes-392146.patch @@ -0,0 +1,379 @@ +From a940156fc32b0c49e847aec0e4076161241cfa15 Mon Sep 17 00:00:00 2001 +From: Matthias Brugger +Date: Wed, 6 Jun 2018 15:23:07 +0200 +Subject: [PATCH] Implement emulated system registers. Fixes #392146. + +Signed-off-by: Matthias Brugger +--- + VEX/priv/guest_arm64_defs.h | 9 ++ + VEX/priv/guest_arm64_helpers.c | 100 +++++++++++++++ + VEX/priv/guest_arm64_toIR.c | 222 +++++++++++++++++++++++++++++++++ + 3 files changed, 331 insertions(+) + +diff --git a/VEX/priv/guest_arm64_defs.h b/VEX/priv/guest_arm64_defs.h +index b28f326c2..ae01e6f3b 100644 +--- a/VEX/priv/guest_arm64_defs.h ++++ b/VEX/priv/guest_arm64_defs.h +@@ -126,6 +126,15 @@ extern ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void ); + + extern ULong arm64g_dirtyhelper_MRS_CNTFRQ_EL0 ( void ); + ++extern ULong arm64g_dirtyhelper_MRS_MIDR_EL1 ( void ); ++ ++extern ULong arm64g_dirtyhelper_MRS_ID_AA64PFR0_EL1 ( void ); ++ ++extern ULong arm64g_dirtyhelper_MRS_ID_AA64MMFR0_EL1 ( void ); ++extern ULong arm64g_dirtyhelper_MRS_ID_AA64MMFR1_EL1 ( void ); ++ ++extern ULong arm64g_dirtyhelper_MRS_ID_AA64ISAR0_EL1 ( void ); ++ + extern void arm64g_dirtyhelper_PMULLQ ( /*OUT*/V128* res, + ULong arg1, ULong arg2 ); + +diff --git a/VEX/priv/guest_arm64_helpers.c b/VEX/priv/guest_arm64_helpers.c +index 10065d547..c579c9e1b 100644 +--- a/VEX/priv/guest_arm64_helpers.c ++++ b/VEX/priv/guest_arm64_helpers.c +@@ -788,6 +788,106 @@ ULong arm64g_dirtyhelper_MRS_CNTFRQ_EL0 ( void ) + # endif + } + ++/* CALLED FROM GENERATED CODE */ ++/* DIRTY HELPER (non-referentially-transparent) */ ++/* Horrible hack. On non-arm64 platforms, return 0. */ ++ULong arm64g_dirtyhelper_MRS_MIDR_EL1 ( void ) ++{ ++# if defined(__aarch64__) && !defined(__arm__) ++ ULong w = 0x5555555555555555ULL; /* overwritten */ ++ __asm__ __volatile__("mrs %0, midr_el1" : "=r"(w)); ++ return w; ++# else ++ return 0ULL; ++# endif ++} ++ ++/* CALLED FROM GENERATED CODE */ ++/* DIRTY HELPER (non-referentially-transparent) */ ++/* Horrible hack. On non-arm64 platforms, return 0. */ ++ULong arm64g_dirtyhelper_MRS_ID_AA64PFR0_EL1 ( void ) ++{ ++# if defined(__aarch64__) && !defined(__arm__) ++ ULong w = 0x5555555555555555ULL; /* overwritten */ ++ __asm__ __volatile__("mrs %0, id_aa64pfr0_el1" : "=r"(w)); ++ ++ /* If half-precision fp is present we fall back to normal ++ half precision implementation because of missing support in the emulation. ++ If no AdvSIMD and FP are implemented, we preserve the value */ ++ w = (w >> 16); ++ w &= 0xff; ++ switch(w) { ++ case 0x11: ++ w = 0x0; ++ break; ++ case 0xff: ++ w = (0xFF<<16); ++ break; ++ default: ++ w = 0x0; ++ break; ++ } ++ ++ return w; ++# else ++ return 0ULL; ++# endif ++} ++ ++/* CALLED FROM GENERATED CODE */ ++/* DIRTY HELPER (non-referentially-transparent) */ ++/* Horrible hack. On non-arm64 platforms, return 0. */ ++ULong arm64g_dirtyhelper_MRS_ID_AA64MMFR0_EL1 ( void ) ++{ ++# if defined(__aarch64__) && !defined(__arm__) ++ ULong w = 0x5555555555555555ULL; /* overwritten */ ++ __asm__ __volatile__("mrs %0, id_aa64mmfr0_el1" : "=r"(w)); ++ return w; ++# else ++ return 0ULL; ++# endif ++} ++ ++/* CALLED FROM GENERATED CODE */ ++/* DIRTY HELPER (non-referentially-transparent) */ ++/* Horrible hack. On non-arm64 platforms, return 0. */ ++ULong arm64g_dirtyhelper_MRS_ID_AA64MMFR1_EL1 ( void ) ++{ ++# if defined(__aarch64__) && !defined(__arm__) ++ ULong w = 0x5555555555555555ULL; /* overwritten */ ++ __asm__ __volatile__("mrs %0, id_aa64mmfr1_el1" : "=r"(w)); ++ ++ /* Clear VH and HAFDBS bits */ ++ w &= ~(0xF0F); ++ return w; ++# else ++ return 0ULL; ++# endif ++} ++ ++/* CALLED FROM GENERATED CODE */ ++/* DIRTY HELPER (non-referentially-transparent) */ ++/* Horrible hack. On non-arm64 platforms, return 0. */ ++ULong arm64g_dirtyhelper_MRS_ID_AA64ISAR0_EL1 ( void ) ++{ ++# if defined(__aarch64__) && !defined(__arm__) ++ ULong w = 0x5555555555555555ULL; /* overwritten */ ++ __asm__ __volatile__("mrs %0, id_aa64isar0_el1" : "=r"(w)); ++ ++ /* Clear all but AES, SHA1 and SHA2 parts*/ ++ w &= ~0xFFFF; ++ /* Degredate SHA2 from b0010 to b0001*/ ++ if ( (w >> 12) & 0x2 ) { ++ w &= ~(0xF << 12); ++ w |= (0x1 << 12); ++ } ++ ++ return w; ++# else ++ return 0ULL; ++# endif ++} ++ + + void arm64g_dirtyhelper_PMULLQ ( /*OUT*/V128* res, ULong arg1, ULong arg2 ) + { +diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c +index e5af388e1..ed6c1ffa5 100644 +--- a/VEX/priv/guest_arm64_toIR.c ++++ b/VEX/priv/guest_arm64_toIR.c +@@ -6872,6 +6872,228 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn, + } + + /* ------------------ M{SR,RS} ------------------ */ ++ /* ---- Case for MIDR_EL1 (RO) ---- ++ Read the Main ID register from host. ++ 0xD53800 000 Rt MRS rT, midr_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380000 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ IRTemp val = newTemp(Ity_I64); ++ IRExpr** args = mkIRExprVec_0(); ++ IRDirty* d = unsafeIRDirty_1_N ( ++ val, ++ 0/*regparms*/, ++ "arm64g_dirtyhelper_MRS_MIDR_EL1", ++ &arm64g_dirtyhelper_MRS_MIDR_EL1, ++ args ++ ); ++ /* execute the dirty call, dumping the result in val. */ ++ stmt( IRStmt_Dirty(d) ); ++ putIReg64orZR(tt, mkexpr(val)); ++ DIP("mrs %s, midr_el1\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for MPIDR_EL1 (RO) ---- ++ Instead of returing a fake regiser, we use the same ++ value as does the kernel emulation. ++ 0xD53800 101 Rt MRS rT, mpidr_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53800A0 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64((1UL<<31))); ++ DIP("mrs %s, mpidr_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for REVDIR_EL1 (RO) ---- ++ Instead of emulating the regiser, we just return the same ++ value as does the kernel emulation. ++ 0xD53800 110 Rt MRS rT, revdir_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53800C0 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg32orZR(tt, mkU32(0x0)); ++ DIP("mrs %s, revdir_el1 (FAKED)\n", nameIReg32orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64PFR0_EL1 (RO) ---- ++ Instead of returing a fake regiser, we use the same ++ value as does the kernel emulation. We set deprecate half ++ precission floating-point to normal floating-point support. ++ We set all other values to zero. ++ 0xD53804 000 Rt MRS rT, id_aa64pfr0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380400 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ IRTemp val = newTemp(Ity_I64); ++ IRExpr** args = mkIRExprVec_0(); ++ IRDirty* d = unsafeIRDirty_1_N ( ++ val, ++ 0/*regparms*/, ++ "arm64g_dirtyhelper_MRS_ID_AA64PFR0_EL1", ++ &arm64g_dirtyhelper_MRS_ID_AA64PFR0_EL1, ++ args ++ ); ++ /* execute the dirty call, dumping the result in val. */ ++ stmt( IRStmt_Dirty(d) ); ++ ++ putIReg64orZR(tt, mkexpr(val)); ++ return True; ++ } ++ /* ---- Case for ID_AA64PFR1_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53804 001 Rt MRS rT, id_aa64pfr1_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380420 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64pfr1_el1 (FAKED)\n", nameIReg32orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64ZFR0_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53804 010 Rt MRS rT, id_aa64zfr0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380440 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64zfr0_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64DFR0_EL1 (RO) ---- ++ Just return the value indicating the implementation of the ++ ARMv8 debug architecture without any extensions. ++ 0xD53805 000 Rt MRS rT, id_aa64dfr0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380500 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x6)); ++ DIP("mrs %s, id_aa64dfr0_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64DFR1_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53805 001 Rt MRS rT, id_aa64dfr1_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380520 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64dfr1_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64AFR0_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53805 100 Rt MRS rT, id_aa64afr0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380580 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64afr0_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64AFR1_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53805 101 Rt MRS rT, id_aa64afr1_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53805A0 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64afr1_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64ISAR0_EL1 (RO) ---- ++ We only take care of SHA2, SHA1 and AES bits, as all the other ++ commands are not part of the emulation environment. ++ We degredate SHA2 from 0x2 to 0x1 as we don't support the commands. ++ 0xD53806 000 Rt MRS rT, id_aa64isar0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380600 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ IRTemp val = newTemp(Ity_I64); ++ IRExpr** args = mkIRExprVec_0(); ++ IRDirty* d = unsafeIRDirty_1_N ( ++ val, ++ 0/*regparms*/, ++ "arm64g_dirtyhelper_MRS_ID_AA64ISAR0_EL1", ++ &arm64g_dirtyhelper_MRS_ID_AA64ISAR0_EL1, ++ args ++ ); ++ /* execute the dirty call, dumping the result in val. */ ++ stmt( IRStmt_Dirty(d) ); ++ putIReg64orZR(tt, mkexpr(val)); ++ DIP("mrs %s, id_aa64isar0_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64ISAR1_EL1 (RO) ---- ++ We just return 0x0 here, as we don't support the opcodes of ++ new commands in the emulation environment. ++ 0xD53806 001 Rt MRS rT, id_aa64isar1_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380620 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64isar1_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64MMFR0_EL1 (RO) ---- ++ Instead of returing a fake regiser, we use the same ++ value as does the kernel emulation. ++ 0xD53807 000 Rt MRS rT, id_aa64mmfr0_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380700 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ IRTemp val = newTemp(Ity_I64); ++ IRExpr** args = mkIRExprVec_0(); ++ IRDirty* d = unsafeIRDirty_1_N ( ++ val, ++ 0/*regparms*/, ++ "arm64g_dirtyhelper_MRS_ID_AA64MMFR0_EL1", ++ &arm64g_dirtyhelper_MRS_ID_AA64MMFR0_EL1, ++ args ++ ); ++ /* execute the dirty call, dumping the result in val. */ ++ stmt( IRStmt_Dirty(d) ); ++ putIReg64orZR(tt, mkexpr(val)); ++ DIP("mrs %s, id_aa64mmfr0_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64MMFR1_EL1 (RO) ---- ++ Instead of returing a fake regiser, we use the same ++ value as does the kernel emulation. Set VHE and HAFDBS ++ to not implemented. ++ 0xD53807 001 Rt MRS rT, id_aa64mmfr1_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380720 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ IRTemp val = newTemp(Ity_I64); ++ IRExpr** args = mkIRExprVec_0(); ++ IRDirty* d = unsafeIRDirty_1_N ( ++ val, ++ 0/*regparms*/, ++ "arm64g_dirtyhelper_MRS_ID_AA64MMFR1_EL1", ++ &arm64g_dirtyhelper_MRS_ID_AA64MMFR1_EL1, ++ args ++ ); ++ /* execute the dirty call, dumping the result in val. */ ++ stmt( IRStmt_Dirty(d) ); ++ putIReg64orZR(tt, mkexpr(val)); ++ DIP("mrs %s, id_aa64mmfr1_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } ++ /* ---- Case for ID_AA64MMFR2_EL1 (RO) ---- ++ Return faked value of not implemented ARMv8.2 and ARMv8.3 ++ 0xD53807 010 Rt MRS rT, id_aa64mmfr2_el1 ++ */ ++ if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380740 /*MRS*/) { ++ UInt tt = INSN(4,0); ++ putIReg64orZR(tt, mkU64(0x0)); ++ DIP("mrs %s, id_aa64mmfr2_el1 (FAKED)\n", nameIReg64orZR(tt)); ++ return True; ++ } + /* ---- Cases for TPIDR_EL0 ---- + 0xD51BD0 010 Rt MSR tpidr_el0, rT + 0xD53BD0 010 Rt MRS rT, tpidr_el0 +-- +2.17.0 + diff --git a/valgrind.changes b/valgrind.changes index 8b03efb..2a88b2d 100644 --- a/valgrind.changes +++ b/valgrind.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Jun 8 08:07:03 UTC 2018 - mbrugger@suse.com + +- ad Implement-emulated-system-registers.-Fixes-392146.patch (bsc#1086543) + ------------------------------------------------------------------- Thu Feb 22 13:07:05 UTC 2018 - olaf@aepfle.de diff --git a/valgrind.spec b/valgrind.spec index da8ecc3..7f90bd4 100644 --- a/valgrind.spec +++ b/valgrind.spec @@ -1,7 +1,7 @@ # # spec file for package valgrind # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -28,7 +28,7 @@ Name: valgrind Version: 3.13.0 Release: 0 Summary: Memory Management Debugger -License: GPL-2.0+ +License: GPL-2.0-or-later Group: Development/Tools/Debuggers Url: http://valgrind.org/ Source0: ftp://sourceware.org/pub/valgrind/valgrind-%{version}.tar.bz2 @@ -38,6 +38,7 @@ Patch0: valgrind.xen.patch Patch1: jit-register-unregister.diff Patch2: armv6-support.diff Patch3: epoll-wait-fix.patch +Patch4: Implement-emulated-system-registers.-Fixes-392146.patch BuildRequires: automake BuildRequires: docbook-xsl-stylesheets BuildRequires: docbook_4 @@ -114,6 +115,7 @@ but it has been successfully used to optimize several KDE applications. ##%patch1 %patch2 %patch3 +%patch4 -p1 %build export FLAGS="%{optflags}"