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

openSUSE Build Service is sponsored by