File Implement-emulated-system-registers.-Fixes-392146.patch of Package valgrind.9221
From a940156fc32b0c49e847aec0e4076161241cfa15 Mon Sep 17 00:00:00 2001
From: Matthias Brugger <mbrugger@suse.com>
Date: Wed, 6 Jun 2018 15:23:07 +0200
Subject: [PATCH] Implement emulated system registers. Fixes #392146.
Signed-off-by: Matthias Brugger <mbrugger@suse.com>
---
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