]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 487418 - [arm64] Cleanup M{SR,RS} instructions (part 1)
authorPaul Floyd <pjfloyd@wanadoo.fr>
Fri, 8 May 2026 11:04:42 +0000 (13:04 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Fri, 8 May 2026 11:04:42 +0000 (13:04 +0200)
This is point 6 on the list.
1. Cache the DZP bit from mrs dczid_el0 in a new field arm64_data_zero_prohibited of VexArchInfo
2. Use the cached values from VexArchInfo for mrs dczid_el0 rather than a dirty helper
3. Add a check to dc zva that the above DZP wasn't set. If it is then print a message
and stop with a Ijk_SigILL.

VEX/priv/guest_arm64_defs.h
VEX/priv/guest_arm64_helpers.c
VEX/priv/guest_arm64_toIR.c
VEX/priv/main_main.c
VEX/pub/libvex.h
coregrind/m_cache.c

index 18b08b7ee163567d530c9bee0af45d88680ea175..e127ff63f46edf335cceced60dc1b93b307ef665 100644 (file)
@@ -116,8 +116,6 @@ extern ULong arm64g_calc_crc32cw ( ULong acc, ULong bits );
 extern ULong arm64g_calc_crc32cx ( ULong acc, ULong bits );
 
 /* --- DIRTY HELPERS --- */
-extern ULong arm64g_dirtyhelper_MRS_DCZID_EL0 ( void );
-
 extern ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void );
 
 extern ULong arm64g_dirtyhelper_MRS_CNTFRQ_EL0 ( void );
index 5068a1a6758556935c44126331706a15ddf7bf69..7bd99ec5fa26cda6aa8af2f51ce0ac28821b38fb 100644 (file)
@@ -776,20 +776,6 @@ ULong arm64g_calc_crc32cx ( ULong acc, ULong bits )
    return crc;
 }
 
-/* CALLED FROM GENERATED CODE */
-/* DIRTY HELPER (non-referentially-transparent) */
-/* Horrible hack.  On non-arm64 platforms, return 0. */
-ULong arm64g_dirtyhelper_MRS_DCZID_EL0 ( void )
-{
-#  if defined(__aarch64__) && !defined(__arm__)
-   ULong w = 0x5555555555555555ULL; /* overwritten */
-   __asm__ __volatile__("mrs %0, dczid_el0" : "=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. */
index 6e77b34c7ce6ae46d78457c20fe7a673c09dba37..0d95ad73ccade3302779f239896a2ed870d88daf 100644 (file)
@@ -7890,19 +7890,12 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
    */
    if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53B00E0) {
       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_DCZID_EL0",
-                         &arm64g_dirtyhelper_MRS_DCZID_EL0,
-                         args
-                      );
-      /* execute the dirty call, dumping the result in val. */
-      stmt( IRStmt_Dirty(d) );
+      ULong val_cached = (archinfo->arm64_data_zero_prohibited ? 0x10 : 0) |
+                         archinfo->arm64_cache_block_size;
+      IRTemp val = newTemp(Ity_I64);
+      assign(val, mkU64(val_cached));
       putIReg64orZR(tt, mkexpr(val));
-      DIP("mrs %s, dczid_el0 (FAKED)\n", nameIReg64orZR(tt));
+      DIP("mrs %s, dczid_el0 (cached)\n", nameIReg64orZR(tt));
       return True;
    }
    /* ---- Cases for CTR_EL0 ----
@@ -8009,6 +8002,14 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
    if ((INSN(31,0) & 0xFFFFFFE0) == 0xD50B7420) {
       /* Round the requested address, in rT, down to the start of the
          containing block. */
+      /* Unless DZP is true */
+      if (archinfo->arm64_data_zero_prohibited) {
+         vex_printf("ARM64 front end: DC ZVA instruction encountered with the DCZID_EL0 DZP flag set.\n");
+         putPC(mkU64( guest_PC_curr_instr));
+         dres->jk_StopHere = Ijk_SigILL;
+         dres->whatNext    = Dis_StopHere;
+         return True;
+      }
       UInt   tt      = INSN(4,0);
       ULong  clearszB = 1UL << (archinfo->arm64_cache_block_size + 2);
       IRTemp addr    = newTemp(Ity_I64);
index 5e3cb7ad80738ed18b75e2702e13eadaf05ad319..e90aef059d5a0f762a4f80b316651e5444a654b6 100644 (file)
@@ -1636,18 +1636,19 @@ const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
 {
    vex_bzero(vai, sizeof(*vai));
-   vai->hwcaps                  = 0;
-   vai->endness                 = VexEndness_INVALID;
-   vai->ppc_icache_line_szB     = 0;
-   vai->ppc_dcbz_szB            = 0;
-   vai->ppc_dcbzl_szB           = 0;
-   vai->arm64_dMinLine_lg2_szB  = 0;
-   vai->arm64_iMinLine_lg2_szB  = 0;
-   vai->arm64_cache_block_size  = 0;
+   vai->hwcaps                       = 0;
+   vai->endness                      = VexEndness_INVALID;
+   vai->ppc_icache_line_szB          = 0;
+   vai->ppc_dcbz_szB                 = 0;
+   vai->ppc_dcbzl_szB                = 0;
+   vai->arm64_dMinLine_lg2_szB       = 0;
+   vai->arm64_iMinLine_lg2_szB       = 0;
+   vai->arm64_cache_block_size       = 0;
+   vai->arm64_data_zero_prohibited   = 0;
    vai->arm64_requires_fallback_LLSC = False;
-   vai->hwcache_info.num_levels = 0;
-   vai->hwcache_info.num_caches = 0;
-   vai->hwcache_info.caches     = NULL;
+   vai->hwcache_info.num_levels      = 0;
+   vai->hwcache_info.num_caches      = 0;
+   vai->hwcache_info.caches          = NULL;
    vai->hwcache_info.icaches_maintain_coherence = True;  // whatever
 }
 
index c7de6273ac458ef461e3bf0900f0a7a57477c76f..a125c5bdba93b6ae42cf1ca32e869473d2977088 100644 (file)
@@ -372,6 +372,9 @@ typedef
       UInt arm64_dMinLine_lg2_szB;
       UInt arm64_iMinLine_lg2_szB;
       UChar arm64_cache_block_size;
+      /* ARM64 DCZID_EL0 bit 4 (DZP) means that
+       * use of DC ZVA is prohibited and should produce SIGILL */
+      Bool arm64_data_zero_prohibited;
       /* ARM64: does the host require us to use the fallback LLSC
          implementation? */
       Bool arm64_requires_fallback_LLSC;
index 2777f8c6f6f87ae95a9f39a7965daaf6fd11d424..c0ec59b199e985c7970fb1f9eb157a4091f92005 100644 (file)
@@ -547,10 +547,10 @@ get_cache_info(VexArchInfo *vai)
 #if defined(VGA_arm64)
    unsigned long val;
    asm volatile("mrs %0, dczid_el0" : "=r" (val));
-   val &= 0xf;
    // The ARM manual says that 4 bits are used but 9 is the maximum
-   vg_assert(val <= 9);
-   vai->arm64_cache_block_size = val;
+   vai->arm64_cache_block_size = val & 0xf;
+   vg_assert(vai->arm64_cache_block_size <= 9);
+   vai->arm64_data_zero_prohibited = !!(val & 0x10);
 #endif
    vai->hwcache_info.icaches_maintain_coherence = False;