]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 392146 - aarch64: unhandled instruction 0xD5380001 (MRS rT, midr_el1)
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 11 May 2024 11:53:42 +0000 (13:53 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 11 May 2024 11:53:42 +0000 (13:53 +0200)
NEWS
VEX/priv/guest_arm64_defs.h
VEX/priv/guest_arm64_helpers.c
VEX/priv/guest_arm64_toIR.c

diff --git a/NEWS b/NEWS
index 631c13fa0375dbe4f47fa722038ea8c6c24b1995..82c5bac4ec3c33f551572dcc8f85d87014f6c75b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather
 than mailing the developers (or mailing lists) directly -- bugs that
 are not entered into bugzilla tend to get forgotten about or ignored.
 
+392146  aarch64: unhandled instruction 0xD5380001 (MRS rT, midr_el1)
 486180  [Valgrind][MIPS] 'VexGuestArchState' has no member named 'guest_IP_AT_SYSCALL'
 486293  memccpy false positives
 486569  linux inotify_init syscall wrapper missing POST entry in syscall_table
index 0aa9f783dbc3969c11ced7ca97ba2ac0ef19945a..55b849a7e945f77e600f924740b2adddb65b2667 100644 (file)
@@ -121,6 +121,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 );
 
index 6f2d41f7e1c1fa9f100762ff2fb77f8028903d36..c79631f6130c027bffadfb9ecc2ed0171cbe1f2c 100644 (file)
@@ -806,6 +806,121 @@ 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));
+
+   // In the mask below, nibbles are (higher nibbles all unsupported)
+   // 0 - RES0
+   // 1 - AES
+   // 2 - SHA1
+   // 3 - SHA2
+   // 4 - CRC32
+   // 5 - Atomic bits
+   // 6 - TME (unsupported)
+   // 7 - RDM
+   // 8 - SHA3 (unsupported)
+   // 9 - SM3 (unsupported)
+   // 10 - SM4 (unsupported)
+   // 11 - DP
+
+   //     10
+   //     109876543210
+   w &= 0xF000F0FFFFFF;
+   /* Degredate SHA2 from b0010 to b0001*/
+   if ( (w >> 12) & 0x2 ) {
+      w ^= ~(0x2 << 12);
+      w |= (0x1 << 12);
+   }
+
+   return w;
+#  else
+   return 0ULL;
+#  endif
+}
+
 
 void arm64g_dirtyhelper_PMULLQ ( /*OUT*/V128* res, ULong arg1, ULong arg2 )
 {
index 27d945d6328de1286c5d8b3454e2259d16b32da2..a6cffef814f9c25dfeb7196d5cc6e0c821fd581a 100644 (file)
@@ -7547,6 +7547,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