From: Bruno Haible Date: Sun, 12 Nov 2023 17:22:50 +0000 (+0100) Subject: jit/cache: New module. X-Git-Tag: v1.0~595 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=f48984f04a9649727f1d0b0f4fd25e88924f9c42;p=gnulib.git jit/cache: New module. * lib/jit/cache.h: New file. * m4/valgrind-helper.m4: New file. * modules/jit/cache: New file. --- diff --git a/ChangeLog b/ChangeLog index c2a59f8f88..c7fa04a173 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2023-11-12 Bruno Haible + + jit/cache: New module. + * lib/jit/cache.h: New file. + * m4/valgrind-helper.m4: New file. + * modules/jit/cache: New file. + 2023-11-11 Bruno Haible ssfmalloc: Take advantage of CHERI bounds-checking. diff --git a/lib/jit/cache.h b/lib/jit/cache.h new file mode 100644 index 0000000000..ce470399e5 --- /dev/null +++ b/lib/jit/cache.h @@ -0,0 +1,140 @@ +/* JIT compiler - Flushing the instruction cache. + + Copyright (C) 1995-2023 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2020. */ + +#if ENABLE_VALGRIND_SUPPORT +# include +#endif +#if defined _WIN32 && !defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif +#if defined __APPLE__ && defined __MACH__ +# include +#endif +#if defined _AIX +# include +#endif +#if defined __sgi +# include +#endif + +/* Clears the instruction cache for addresses + start <= address < end. + We need this because some CPUs have separate data cache and instruction + cache. The freshly built trampoline is visible to the data cache, but + maybe not to the instruction cache. This is hairy. */ +static inline void +clear_cache (void *start, void *end) +{ +#if ENABLE_VALGRIND_SUPPORT + /* Documentation: + */ + VALGRIND_DISCARD_TRANSLATIONS (start, (char *) end - (char *) start); +#endif +#if (defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86) + /* On this architecture, data cache and instruction cache are not separate. + Therefore, nothing to do. + For details, see + */ + +/* Use the operating system provided function, when available. */ +#elif defined _WIN32 && !defined __CYGWIN__ + /* Native Windows. + FlushInstructionCache + */ + HANDLE process = GetCurrentProcess (); + while (!FlushInstructionCache (process, start, (char *) end - (char *) start)) + ; +#elif defined __APPLE__ && defined __MACH__ + /* macOS */ + sys_icache_invalidate (start, (char *) end - (char *) start); +#elif defined _AIX + /* AIX. */ + _sync_cache_range (start, (char *) end - (char *) start); +#elif defined __sgi + /* IRIX. */ + cacheflush (start, (char *) end - (char *) start, ICACHE); +#elif defined __sun + /* Solaris. */ + extern void sync_instruction_memory (char *, size_t); + sync_instruction_memory (start, (char *) end - (char *) start); + +/* No operating system provided function. Dispatch according to the CPU. */ +#elif (defined __GNUC__ || defined __clang__) && defined __powerpc__ + /* XXX Is this enough, or do we also need the 'clf' instruction? */ + uintptr_t addr = (uintptr_t) start & ~(intptr_t)3; + uintptr_t end_addr = (uintptr_t) end; + do + { + asm volatile ("icbi 0,%0; dcbf 0,%0" : : "r" (addr)); + addr += 4; + } + while (addr < end_addr); + asm volatile ("sync; isync"); +#elif (defined __GNUC__ || defined __clang__) && defined __sparc + /* Use inline assembly. */ + /* The 'flush' instruction was earlier called 'iflush'. */ + uintptr_t addr = (uintptr_t) start & ~(intptr_t)7; + uintptr_t end_addr = (uintptr_t) end; + do + { + asm volatile ("flush %0+0" : : "r" (addr)); + addr += 8; + } + while (addr < end_addr); +#elif (defined __GNUC__ || defined __clang__) && defined __m68k__ && defined __linux__ + /* Use inline assembly to call the 'cacheflush' system call. + sys_cacheflush (addr, scope, cache, len) + d1 d2 d3 d4 + */ + register uintptr_t addr __asm__ ("%d1") = (uintptr_t) start; + register uintptr_t len __asm__ ("%d4") = (uintptr_t) end - addr; + __asm__ __volatile__ ( + "move%.l %#123,%/d0" /* __NR_cacheflush */ + "\n\t" "move%.l %#1,%/d2" /* FLUSH_SCOPE_LINE */ + "\n\t" "move%.l %#3,%/d3" /* FLUSH_CACHE_BOTH */ + "\n\t" "trap %#0" + : + : "d" (addr), "d" (len) + : "%d0", "%d2", "%d3" + ); +#elif (__GNUC__ + (__GNUC_MINOR__ >= 3) > 4) \ + || ((__clang_major__ + (__clang_minor__ >= 4) > 3) \ + && (defined __aarch64__ /* arm64 */ || defined __arm__)) + /* GCC >= 4.3 has a GCC built-in. + + But it's sometimes not correctly implemented. + clang >= 3.4 has it as well, at least on ARM and ARM64. */ + /* On ARM, cache flushing can only be done through a system call. + GCC implements it for Linux with EABI, through an "swi 0" with code + 0xf0002. For other systems, it may be an "swi 0x9f0002", + an "swi 0xf00000", or similar. */ + /* On ARM64, cache flushing is done through special instructions, + and the length of the cache lines must be determined at runtime. + See gcc/libgcc/config/aarch64/sync-cache.c. */ + __builtin___clear_cache (start, end); +#elif HAVE___CLEAR_CACHE + /* Older versions of GCC have this libgcc function, but only on some + platforms. */ + extern void __clear_cache (char *, char *); + __clear_cache (start, end); +#else +# error "Don't know how to implement clear_cache on this platform." +#endif +} diff --git a/m4/valgrind-helper.m4 b/m4/valgrind-helper.m4 new file mode 100644 index 0000000000..b3d70a7ad9 --- /dev/null +++ b/m4/valgrind-helper.m4 @@ -0,0 +1,22 @@ +# valgrind-helper.m4 serial 1 +dnl Copyright (C) 2023 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Enables support for running the generated binaries under valgrind if +# - the valgrind header files are installed, and +# - the user desires so. +AC_DEFUN_ONCE([gl_VALGRIND_HELPER], +[ + AC_ARG_WITH([valgrind], + [AS_HELP_STRING([[--with-valgrind]], + [enable support for running the binaries under valgrind])], + [if test "$withval" != no; then + support_valgrind=1 + else + support_valgrind=0 + fi + ]) + AC_DEFINE_UNQUOTED([ENABLE_VALGRIND_SUPPORT], [$support_valgrind]) +]) diff --git a/modules/jit/cache b/modules/jit/cache new file mode 100644 index 0000000000..f7af2be314 --- /dev/null +++ b/modules/jit/cache @@ -0,0 +1,24 @@ +Description: +JIT compiler - Flushing the instruction cache. + +Files: +lib/jit/cache.h +m4/valgrind-helper.m4 + +Depends-on: + +configure.ac: +gl_VALGRIND_HELPER +AC_REQUIRE([AC_C_INLINE]) +AC_CHECK_FUNCS([__clear_cache]) + +Makefile.am: + +Include: +"jit/cache.h" + +License: +LGPLv2+ + +Maintainer: +Bruno Haible