From: Petr Pavlu Date: Tue, 11 Apr 2023 19:30:42 +0000 (+0000) Subject: riscv64: Add initial support: Valgrind modifications X-Git-Tag: VALGRIND_3_25_0~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32fc9cc751809c90deac9d40f1c755691de6ce12;p=thirdparty%2Fvalgrind.git riscv64: Add initial support: Valgrind modifications The following people contributed to the initial RISC-V support: Petr Pavlu Xeonacid laokz Chelsea E. Manning zhaomingxin Jojo R https://bugs.kde.org/show_bug.cgi?id=493507 --- diff --git a/.gitignore b/.gitignore index c5a2b0592..de2306df7 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ /auxprogs/getoff-mips32-linux /auxprogs/getoff-mips64-linux /auxprogs/getoff-nanomips-linux +/auxprogs/getoff-riscv64-linux /auxprogs/getoff-amd64-solaris /auxprogs/getoff-x86-solaris /auxprogs/getoff-*-freebsd @@ -1132,6 +1133,18 @@ /memcheck/tests/arm64-linux/Makefile.in /memcheck/tests/arm64-linux/scalar +# /memcheck/tests/riscv64-linux/ +/memcheck/tests/riscv64-linux/*.stderr.diff +/memcheck/tests/riscv64-linux/*.stderr.out +/memcheck/tests/riscv64-linux/*.stdout.diff +/memcheck/tests/riscv64-linux/*.stdout.out +/memcheck/tests/riscv64-linux/.deps +/memcheck/tests/riscv64-linux/Makefile +/memcheck/tests/riscv64-linux/Makefile.in +/memcheck/tests/riscv64-linux/context_float +/memcheck/tests/riscv64-linux/context_integer +/memcheck/tests/riscv64-linux/scalar + # /memcheck/tests/common/ /memcheck/tests/common/Makefile /memcheck/tests/common/Makefile.in @@ -2201,6 +2214,23 @@ /none/tests/s390x/vec2 /none/tests/s390x/vec2_float +# /none/tests/riscv64/ +/none/tests/riscv64/*.stderr.diff +/none/tests/riscv64/*.stderr.out +/none/tests/riscv64/*.stdout.diff +/none/tests/riscv64/*.stdout.out +/none/tests/riscv64/.deps +/none/tests/riscv64/Makefile +/none/tests/riscv64/Makefile.in +/none/tests/riscv64/allexec +/none/tests/riscv64/atomic +/none/tests/riscv64/compressed +/none/tests/riscv64/csr +/none/tests/riscv64/float32 +/none/tests/riscv64/float64 +/none/tests/riscv64/integer +/none/tests/riscv64/muldiv + # /none/tests/scripts/ /none/tests/scripts/*.dSYM /none/tests/scripts/*.so diff --git a/Makefile.all.am b/Makefile.all.am index e221198d6..d4f6b3fb7 100755 --- a/Makefile.all.am +++ b/Makefile.all.am @@ -292,6 +292,11 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \ $(AM_CFLAGS_PSO_BASE) AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g +AM_FLAG_M3264_RISCV64_LINUX = @FLAG_M64@ +AM_CFLAGS_RISCV64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) +AM_CFLAGS_PSO_RISCV64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) $(AM_CFLAGS_PSO_BASE) +AM_CCASFLAGS_RISCV64_LINUX = @FLAG_M64@ -g + AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@ AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \ $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@ @@ -353,6 +358,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ +PRELOAD_LDFLAGS_RISCV64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@ PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@ diff --git a/Makefile.am b/Makefile.am index d745e26bf..db8cfa382 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,6 +118,7 @@ EXTRA_DIST = \ README.android_emulator \ README.mips \ README.aarch64 \ + README.riscv64 \ README.solaris \ README.freebsd \ NEWS.old \ diff --git a/Makefile.tool.am b/Makefile.tool.am index c779596e7..7f18d2547 100644 --- a/Makefile.tool.am +++ b/Makefile.tool.am @@ -110,6 +110,9 @@ TOOL_LDFLAGS_MIPS64_LINUX = \ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ @FLAG_M64@ +TOOL_LDFLAGS_RISCV64_LINUX = \ + $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ + TOOL_LDFLAGS_X86_SOLARIS = \ $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@ @@ -181,6 +184,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \ LIBREPLACEMALLOC_MIPS64_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a +LIBREPLACEMALLOC_RISCV64_LINUX = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-riscv64-linux.a + LIBREPLACEMALLOC_X86_SOLARIS = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a @@ -258,6 +264,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \ $(LIBREPLACEMALLOC_MIPS64_LINUX) \ -Wl,--no-whole-archive +LIBREPLACEMALLOC_LDFLAGS_RISCV64_LINUX = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_RISCV64_LINUX) \ + -Wl,--no-whole-archive + LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \ -Wl,--whole-archive \ $(LIBREPLACEMALLOC_X86_SOLARIS) \ diff --git a/Makefile.vex.am b/Makefile.vex.am index c1244a69d..f75e9b4c6 100644 --- a/Makefile.vex.am +++ b/Makefile.vex.am @@ -26,6 +26,7 @@ pkginclude_HEADERS = \ pub/libvex_guest_s390x.h \ pub/libvex_guest_mips32.h \ pub/libvex_guest_mips64.h \ + pub/libvex_guest_riscv64.h \ pub/libvex_s390x_common.h \ pub/libvex_ir.h \ pub/libvex_trc_values.h \ @@ -49,6 +50,7 @@ noinst_HEADERS = \ priv/guest_mips_defs.h \ priv/mips_defs.h \ priv/guest_nanomips_defs.h \ + priv/guest_riscv64_defs.h \ priv/host_generic_regs.h \ priv/host_generic_simd64.h \ priv/host_generic_simd128.h \ @@ -65,7 +67,8 @@ noinst_HEADERS = \ priv/s390_defs.h \ priv/host_mips_defs.h \ priv/host_nanomips_defs.h \ - priv/common_nanomips_defs.h + priv/common_nanomips_defs.h \ + priv/host_riscv64_defs.h BUILT_SOURCES = pub/libvex_guest_offsets.h CLEANFILES = pub/libvex_guest_offsets.h @@ -94,7 +97,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \ pub/libvex_guest_arm64.h \ pub/libvex_guest_s390x.h \ pub/libvex_guest_mips32.h \ - pub/libvex_guest_mips64.h + pub/libvex_guest_mips64.h \ + pub/libvex_guest_riscv64.h rm -f auxprogs/genoffsets.s $(mkdir_p) auxprogs pub $(CC) $(CFLAGS_FOR_GENOFFSETS) \ @@ -152,6 +156,8 @@ LIBVEX_SOURCES_COMMON = \ priv/guest_mips_toIR.c \ priv/guest_nanomips_helpers.c \ priv/guest_nanomips_toIR.c \ + priv/guest_riscv64_helpers.c \ + priv/guest_riscv64_toIR.c \ priv/host_generic_regs.c \ priv/host_generic_simd64.c \ priv/host_generic_simd128.c \ @@ -176,7 +182,9 @@ LIBVEX_SOURCES_COMMON = \ priv/host_mips_defs.c \ priv/host_nanomips_defs.c \ priv/host_mips_isel.c \ - priv/host_nanomips_isel.c + priv/host_nanomips_isel.c \ + priv/host_riscv64_defs.c \ + priv/host_riscv64_isel.c LIBVEXMULTIARCH_SOURCES = priv/multiarch_main_main.c diff --git a/cachegrind/cg_arch.c b/cachegrind/cg_arch.c index 68314c9db..be2973405 100644 --- a/cachegrind/cg_arch.c +++ b/cachegrind/cg_arch.c @@ -484,6 +484,13 @@ configure_caches(cache_t *I1c, cache_t *D1c, cache_t *LLc, *D1c = (cache_t) { 65536, 2, 64 }; *LLc = (cache_t) { 262144, 8, 64 }; +#elif defined(VGA_riscv64) + + // Default cache configuration is SiFive FU740-C000 (HiFive Unmatched) + *I1c = (cache_t) { 32768, 4, 64 }; + *D1c = (cache_t) { 32768, 8, 64 }; + *LLc = (cache_t) { 2097152, 16, 64 }; + #else #error "Unknown arch" diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c index 927b7bf21..f7a261c6f 100644 --- a/cachegrind/cg_branchpred.c +++ b/cachegrind/cg_branchpred.c @@ -48,7 +48,7 @@ # define N_IADDR_LO_ZERO_BITS 2 #elif defined(VGA_x86) || defined(VGA_amd64) # define N_IADDR_LO_ZERO_BITS 0 -#elif defined(VGA_s390x) || defined(VGA_arm) +#elif defined(VGA_s390x) || defined(VGA_arm) || defined(VGA_riscv64) # define N_IADDR_LO_ZERO_BITS 1 #else # error "Unsupported architecture" diff --git a/configure.ac b/configure.ac index 9dec9f3b0..e6ae0501b 100755 --- a/configure.ac +++ b/configure.ac @@ -302,6 +302,11 @@ case "${host_cpu}" in ARCH_MAX="nanomips" ;; + riscv64) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="riscv64" + ;; + *) AC_MSG_RESULT([no (${host_cpu})]) AC_MSG_ERROR([Unsupported host architecture. Sorry]) @@ -874,6 +879,17 @@ case "$ARCH_MAX-$VGCONF_OS" in valt_load_address_sec_inner="0xUNSET" AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) ;; + riscv64-linux) + VGCONF_ARCH_PRI="riscv64" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="RISCV64_LINUX" + VGCONF_PLATFORM_SEC_CAPS="" + valt_load_address_pri_norml="0x58000000" + valt_load_address_pri_inner="0x38000000" + valt_load_address_sec_norml="0xUNSET" + valt_load_address_sec_inner="0xUNSET" + AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) + ;; x86-solaris) VGCONF_ARCH_PRI="x86" VGCONF_ARCH_SEC="" @@ -967,6 +983,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS64, test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ) AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_NANOMIPS, test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX ) +AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_RISCV64, + test x$VGCONF_PLATFORM_PRI_CAPS = xRISCV64_LINUX ) # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these # become defined. @@ -997,6 +1015,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS64_LINUX, test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX) AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX, test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX) +AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_RISCV64_LINUX, + test x$VGCONF_PLATFORM_PRI_CAPS = xRISCV64_LINUX) AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD) @@ -1030,7 +1050,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX, -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \ - -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX) + -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xRISCV64_LINUX) AM_CONDITIONAL(VGCONF_OS_IS_FREEBSD, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD \ @@ -5049,7 +5070,8 @@ elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_FREEBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \ - -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then + -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xRISCV64_LINUX ; then mflag_primary=$FLAG_M64 elif test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN ; then mflag_primary="$FLAG_M32 -arch i386" @@ -5657,6 +5679,7 @@ AC_CONFIG_FILES([ memcheck/tests/amd64-linux/Makefile memcheck/tests/arm64-linux/Makefile memcheck/tests/x86-linux/Makefile + memcheck/tests/riscv64-linux/Makefile memcheck/tests/amd64-solaris/Makefile memcheck/tests/x86-solaris/Makefile memcheck/tests/amd64-freebsd/Makefile @@ -5702,6 +5725,7 @@ AC_CONFIG_FILES([ none/tests/mips32/Makefile none/tests/mips64/Makefile none/tests/nanomips/Makefile + none/tests/riscv64/Makefile none/tests/linux/Makefile none/tests/darwin/Makefile none/tests/solaris/Makefile diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 5491fc672..700751dea 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -392,6 +392,7 @@ COREGRIND_SOURCES_COMMON = \ m_dispatch/dispatch-mips32-linux.S \ m_dispatch/dispatch-mips64-linux.S \ m_dispatch/dispatch-nanomips-linux.S \ + m_dispatch/dispatch-riscv64-linux.S \ m_dispatch/dispatch-x86-freebsd.S \ m_dispatch/dispatch-amd64-freebsd.S \ m_dispatch/dispatch-arm64-freebsd.S \ @@ -419,6 +420,7 @@ COREGRIND_SOURCES_COMMON = \ m_gdbserver/valgrind-low-mips32.c \ m_gdbserver/valgrind-low-mips64.c \ m_gdbserver/valgrind-low-nanomips.c \ + m_gdbserver/valgrind-low-riscv64.c \ m_gdbserver/version.c \ m_initimg/initimg-linux.c \ m_initimg/initimg-freebsd.c \ @@ -447,6 +449,7 @@ COREGRIND_SOURCES_COMMON = \ m_sigframe/sigframe-mips32-linux.c \ m_sigframe/sigframe-mips64-linux.c \ m_sigframe/sigframe-nanomips-linux.c \ + m_sigframe/sigframe-riscv64-linux.c \ m_sigframe/sigframe-x86-darwin.c \ m_sigframe/sigframe-amd64-darwin.c \ m_sigframe/sigframe-solaris.c \ @@ -461,6 +464,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syscall-mips32-linux.S \ m_syswrap/syscall-mips64-linux.S \ m_syswrap/syscall-nanomips-linux.S \ + m_syswrap/syscall-riscv64-linux.S \ m_syswrap/syscall-x86-freebsd.S \ m_syswrap/syscall-amd64-freebsd.S \ m_syswrap/syscall-arm64-freebsd.S \ @@ -488,6 +492,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syswrap-mips32-linux.c \ m_syswrap/syswrap-mips64-linux.c \ m_syswrap/syswrap-nanomips-linux.c \ + m_syswrap/syswrap-riscv64-linux.c \ m_syswrap/syswrap-x86-darwin.c \ m_syswrap/syswrap-amd64-darwin.c \ m_syswrap/syswrap-xen.c \ @@ -780,7 +785,15 @@ GDBSERVER_XML_FILES = \ m_gdbserver/mips64-linux-valgrind.xml \ m_gdbserver/mips64-fpu-valgrind-s1.xml \ m_gdbserver/mips64-fpu-valgrind-s2.xml \ - m_gdbserver/mips64-fpu.xml + m_gdbserver/mips64-fpu.xml \ + m_gdbserver/riscv64-cpu-valgrind-s1.xml \ + m_gdbserver/riscv64-cpu-valgrind-s2.xml \ + m_gdbserver/riscv64-cpu.xml \ + m_gdbserver/riscv64-linux.xml \ + m_gdbserver/riscv64-linux-valgrind.xml \ + m_gdbserver/riscv64-fpu-valgrind-s1.xml \ + m_gdbserver/riscv64-fpu-valgrind-s2.xml \ + m_gdbserver/riscv64-fpu.xml # so as to make sure these get copied into the install tree vglibdir = $(pkglibexecdir) diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c index 715fdab81..20e624003 100644 --- a/coregrind/launcher-linux.c +++ b/coregrind/launcher-linux.c @@ -51,16 +51,18 @@ #include #include +/* Provide own definitions for elf.h constants that might not be yet available + on some older systems. */ #ifndef EM_X86_64 -#define EM_X86_64 62 // elf.h doesn't define this on some older systems +#define EM_X86_64 62 #endif #ifndef EM_AARCH64 -#define EM_AARCH64 183 // ditto +#define EM_AARCH64 183 #endif #ifndef EM_PPC64 -#define EM_PPC64 21 // ditto +#define EM_PPC64 21 #endif #ifndef EM_NANOMIPS @@ -75,6 +77,10 @@ #define E_MIPS_ABI2 0x00000020 #endif +#ifndef EM_RISCV +#define EM_RISCV 243 +#endif + /* Report fatal errors */ __attribute__((noreturn)) static void barf ( const char *format, ... ) @@ -316,6 +322,10 @@ static const char *select_platform(const char *clientname) (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV || header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) { platform = "ppc64le-linux"; + } else if (header.ehdr64.e_machine == EM_RISCV && + (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV || + header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) { + platform = "riscv64-linux"; } } else if (header.c[EI_DATA] == ELFDATA2MSB) { # if !defined(VGPV_arm_linux_android) \ @@ -404,8 +414,8 @@ int main(int argc, char** argv, char** envp) the executable (eg because it's a shell script). VG_PLATFORM is the default_platform. Its value is defined in coregrind/Makefile.am and typically it is the primary build target. Unless the primary build - target is not built is not built in which case VG_PLATFORM is the - secondary build target. */ + target is not built in which case VG_PLATFORM is the secondary build + target. */ # if defined(VGO_linux) if ((0==strcmp(VG_PLATFORM,"x86-linux")) || (0==strcmp(VG_PLATFORM,"amd64-linux")) || @@ -417,7 +427,8 @@ int main(int argc, char** argv, char** envp) (0==strcmp(VG_PLATFORM,"s390x-linux")) || (0==strcmp(VG_PLATFORM,"mips32-linux")) || (0==strcmp(VG_PLATFORM,"mips64-linux")) || - (0==strcmp(VG_PLATFORM,"nanomips-linux"))) + (0==strcmp(VG_PLATFORM,"nanomips-linux")) || + (0==strcmp(VG_PLATFORM,"riscv64-linux"))) default_platform = VG_PLATFORM; # elif defined(VGO_solaris) if ((0==strcmp(VG_PLATFORM,"x86-solaris")) || diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index 68bc5b40c..14864d96c 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -157,7 +157,8 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot, # elif defined(VGP_amd64_linux) \ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \ - || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) + || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, prot, flags, fd, offset); # elif defined(VGP_x86_darwin) @@ -262,8 +263,9 @@ SysRes ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY)( SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode ) { -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) - /* ARM64 wants to use __NR_openat rather than __NR_open. */ +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) + /* More recent Linux platforms have only __NR_openat and no __NR_open. */ SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, flags, mode); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) @@ -291,7 +293,8 @@ void ML_(am_close) ( Int fd ) Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz) { SysRes res; -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, (UWord)buf, bufsiz); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) diff --git a/coregrind/m_cache.c b/coregrind/m_cache.c index d12941cd6..4abd26f0b 100644 --- a/coregrind/m_cache.c +++ b/coregrind/m_cache.c @@ -539,7 +539,8 @@ get_cache_info(VexArchInfo *vai) #elif defined(VGA_arm) || defined(VGA_ppc32) || \ defined(VGA_ppc64be) || defined(VGA_ppc64le) || \ defined(VGA_mips32) || defined(VGA_mips64) || \ - defined(VGA_arm64) || defined(VGA_nanomips) + defined(VGA_arm64) || defined(VGA_nanomips) || \ + defined(VGA_riscv64) static Bool get_cache_info(VexArchInfo *vai) { diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c index a4632d9e2..b57d26275 100644 --- a/coregrind/m_coredump/coredump-elf.c +++ b/coregrind/m_coredump/coredump-elf.c @@ -277,7 +277,7 @@ static void fill_prstatus(const ThreadState *tst, prs->pr_sid = VG_(getpgrp)(); #endif -#if defined(VGP_s390x_linux) +#if defined(VGP_s390x_linux) || defined(VGP_riscv64_linux) /* prs->pr_reg has struct type. Need to take address. */ regs = (struct vki_user_regs_struct *)&(prs->pr_reg); #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ @@ -489,6 +489,39 @@ static void fill_prstatus(const ThreadState *tst, regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status; regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC; # undef DO +#elif defined(VGP_riscv64_linux) + regs->pc = arch->vex.guest_pc; + regs->ra = arch->vex.guest_x1; + regs->sp = arch->vex.guest_x2; + regs->gp = arch->vex.guest_x3; + regs->tp = arch->vex.guest_x4; + regs->t0 = arch->vex.guest_x5; + regs->t1 = arch->vex.guest_x6; + regs->t2 = arch->vex.guest_x7; + regs->s0 = arch->vex.guest_x8; + regs->s1 = arch->vex.guest_x9; + regs->a0 = arch->vex.guest_x10; + regs->a1 = arch->vex.guest_x11; + regs->a2 = arch->vex.guest_x12; + regs->a3 = arch->vex.guest_x13; + regs->a4 = arch->vex.guest_x14; + regs->a5 = arch->vex.guest_x15; + regs->a6 = arch->vex.guest_x16; + regs->a7 = arch->vex.guest_x17; + regs->s2 = arch->vex.guest_x18; + regs->s3 = arch->vex.guest_x19; + regs->s4 = arch->vex.guest_x20; + regs->s5 = arch->vex.guest_x21; + regs->s6 = arch->vex.guest_x22; + regs->s7 = arch->vex.guest_x23; + regs->s8 = arch->vex.guest_x24; + regs->s9 = arch->vex.guest_x25; + regs->s10 = arch->vex.guest_x26; + regs->s11 = arch->vex.guest_x27; + regs->t3 = arch->vex.guest_x28; + regs->t4 = arch->vex.guest_x29; + regs->t5 = arch->vex.guest_x30; + regs->t6 = arch->vex.guest_x31; #elif defined(VGP_amd64_freebsd) regs->rflags = LibVEX_GuestAMD64_get_rflags( &arch->vex ); regs->rsp = arch->vex.guest_RSP; @@ -691,6 +724,41 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) # undef DO #elif defined(VGP_nanomips_linux) +#elif defined(VGP_riscv64_linux) + fpu->d.f[0] = arch->vex.guest_f0; + fpu->d.f[1] = arch->vex.guest_f1; + fpu->d.f[2] = arch->vex.guest_f2; + fpu->d.f[3] = arch->vex.guest_f3; + fpu->d.f[4] = arch->vex.guest_f4; + fpu->d.f[5] = arch->vex.guest_f5; + fpu->d.f[6] = arch->vex.guest_f6; + fpu->d.f[7] = arch->vex.guest_f7; + fpu->d.f[8] = arch->vex.guest_f8; + fpu->d.f[9] = arch->vex.guest_f9; + fpu->d.f[10] = arch->vex.guest_f10; + fpu->d.f[11] = arch->vex.guest_f11; + fpu->d.f[12] = arch->vex.guest_f12; + fpu->d.f[13] = arch->vex.guest_f13; + fpu->d.f[14] = arch->vex.guest_f14; + fpu->d.f[15] = arch->vex.guest_f15; + fpu->d.f[16] = arch->vex.guest_f16; + fpu->d.f[17] = arch->vex.guest_f17; + fpu->d.f[18] = arch->vex.guest_f18; + fpu->d.f[19] = arch->vex.guest_f19; + fpu->d.f[20] = arch->vex.guest_f20; + fpu->d.f[21] = arch->vex.guest_f21; + fpu->d.f[22] = arch->vex.guest_f22; + fpu->d.f[23] = arch->vex.guest_f23; + fpu->d.f[24] = arch->vex.guest_f24; + fpu->d.f[25] = arch->vex.guest_f25; + fpu->d.f[26] = arch->vex.guest_f26; + fpu->d.f[27] = arch->vex.guest_f27; + fpu->d.f[28] = arch->vex.guest_f28; + fpu->d.f[29] = arch->vex.guest_f29; + fpu->d.f[30] = arch->vex.guest_f30; + fpu->d.f[31] = arch->vex.guest_f31; + fpu->d.fcsr = arch->vex.guest_fcsr; + #elif defined(VGP_x86_freebsd) #elif defined(VGP_amd64_freebsd) diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c index 564b832e6..80dec21a6 100644 --- a/coregrind/m_debuginfo/d3basics.c +++ b/coregrind/m_debuginfo/d3basics.c @@ -555,6 +555,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs ) # elif defined(VGP_arm64_linux) || defined(VGP_arm64_freebsd) if (regno == 31) { *a = regs->sp; return True; } if (regno == 29) { *a = regs->fp; return True; } +# elif defined(VGP_riscv64_linux) + if (regno == 2) { *a = regs->sp; return True; } + if (regno == 8) { *a = regs->fp; return True; } # else # error "Unknown platform" # endif diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 11ab47354..97d0f35c0 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -1277,7 +1277,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ) is_rx_map = seg->hasR && seg->hasX; is_rw_map = seg->hasR && seg->hasW; # elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ - || defined(VGA_arm) || defined(VGA_arm64) + || defined(VGA_arm) || defined(VGA_arm64) || defined(VGA_riscv64) is_rx_map = seg->hasR && seg->hasX && !seg->hasW; is_rw_map = seg->hasR && seg->hasW && !seg->hasX; # elif defined(VGP_s390x_linux) @@ -3092,12 +3092,12 @@ UWord evalCfiExpr ( const XArray* exprs, Int ix, case Creg_IA_SP: return eec->uregs->sp; case Creg_IA_BP: return eec->uregs->fp; case Creg_MIPS_RA: return eec->uregs->ra; -# elif defined(VGA_ppc32) || defined(VGA_ppc64be) \ - || defined(VGA_ppc64le) # elif defined(VGP_arm64_linux) || defined(VGP_arm64_freebsd) case Creg_ARM64_SP: return eec->uregs->sp; case Creg_ARM64_X30: return eec->uregs->x30; case Creg_ARM64_X29: return eec->uregs->x29; +# elif defined(VGA_ppc32) || defined(VGA_ppc64be) \ + || defined(VGA_ppc64le) || defined(VGP_riscv64_linux) # else # error "Unsupported arch" # endif @@ -3378,7 +3378,13 @@ static Addr compute_cfa ( const D3UnwindRegs* uregs, case CFIC_ARM64_X29REL: cfa = cfsi_m->cfa_off + uregs->x29; break; - +# elif defined(VGP_riscv64_linux) + case CFIC_IA_SPREL: + cfa = cfsi_m->cfa_off + uregs->sp; + break; + case CFIC_IA_BPREL: + cfa = cfsi_m->cfa_off + uregs->fp; + break; # else # error "Unsupported arch" # endif @@ -3450,6 +3456,15 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp, return compute_cfa(&uregs, min_accessible, max_accessible, ce->di, ce->cfsi_m); } +#elif defined(VGA_riscv64) + { D3UnwindRegs uregs; + uregs.pc = ip; + uregs.sp = sp; + uregs.fp = fp; + uregs.ra = 0; + return compute_cfa(&uregs, + min_accessible, max_accessible, ce->di, ce->cfsi_m); + } # else return 0; /* indicates failure */ @@ -3501,6 +3516,8 @@ void VG_(ppUnwindInfo) (Addr from, Addr to) For arm64, the unwound registers are: X29(FP) X30(LR) SP PC. For s390, the unwound registers are: R11(FP) R14(LR) R15(SP) F0..F7 PC. + + For riscv64, the unwound registers are: X2(SP) X8(FP) PC */ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, Addr min_accessible, @@ -3526,6 +3543,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, ipHere = uregsHere->pc; # elif defined(VGP_arm64_freebsd) ipHere = uregsHere->pc; +# elif defined(VGP_riscv64_linux) + ipHere = uregsHere->pc; # else # error "Unknown arch" # endif @@ -3671,6 +3690,15 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off); COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off); COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off); +# elif defined(VGP_riscv64_linux) + /* Compute register values in the caller's frame. Notice that the previous + pc is equal to the previous ra and is calculated as such. The previous ra + is however set to 0 here as this helps to promptly fail cases where an + inner frame uses the CFIR_SAME rule for ra which is bogus. */ + COMPUTE(uregsPrev.pc, uregsHere->ra, cfsi_m->ra_how, cfsi_m->ra_off); + COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off); + COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off); + uregsPrev.ra = 0; # else # error "Unknown arch" # endif diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index 441b379d2..d8cba81c4 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -355,6 +355,19 @@ typedef } DiCfSI_m; #elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) +typedef + struct { + UChar cfa_how; /* a CFIC_ value */ + UChar ra_how; /* a CFIR_ value */ + UChar sp_how; /* a CFIR_ value */ + UChar fp_how; /* a CFIR_ value */ + Int cfa_off; + Int ra_off; + Int sp_off; + Int fp_off; + } + DiCfSI_m; +#elif defined(VGA_riscv64) typedef struct { UChar cfa_how; /* a CFIC_ value */ diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 0686e8d07..b08720182 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -2066,6 +2066,10 @@ void ML_(read_debuginfo_dwarf1) ( # define FP_REG 30 # define SP_REG 29 # define RA_REG_DEFAULT 31 +#elif defined(VGP_riscv64_linux) +# define FP_REG 8 +# define SP_REG 2 +# define RA_REG_DEFAULT 1 #else # error "Unknown platform" #endif @@ -2084,6 +2088,8 @@ void ML_(read_debuginfo_dwarf1) ( # define N_CFI_REGS 128 #elif defined(VGP_s390x_linux) # define N_CFI_REGS 66 +#elif defined(VGP_riscv64_linux) +# define N_CFI_REGS 128 #else # define N_CFI_REGS 20 #endif @@ -2310,6 +2316,10 @@ static void initUnwindContext ( /*OUT*/UnwindContext* ctx ) start out as RR_Same. */ ctx->state[j].reg[29/*FP*/].tag = RR_Same; ctx->state[j].reg[30/*LR*/].tag = RR_Same; +# elif defined(VGA_riscv64) + /* Registers fp and ra start out implicitly as RR_Same. */ + ctx->state[j].reg[FP_REG].tag = RR_Same; + ctx->state[j].reg[RA_REG_DEFAULT].tag = RR_Same; # endif } } @@ -2392,7 +2402,8 @@ static Bool summarise_context(/*OUT*/Addr* base, if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) { si_m->cfa_off = ctxs->cfa_off; # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ - || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) + || defined(VGA_mips32) || defined(VGA_nanomips) \ + || defined(VGA_mips64) || defined(VGA_riscv64) si_m->cfa_how = CFIC_IA_SPREL; # elif defined(VGA_arm) si_m->cfa_how = CFIC_ARM_R13REL; @@ -2406,7 +2417,8 @@ static Bool summarise_context(/*OUT*/Addr* base, if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) { si_m->cfa_off = ctxs->cfa_off; # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ - || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) + || defined(VGA_mips32) || defined(VGA_nanomips) \ + || defined(VGA_mips64) || defined(VGA_riscv64) si_m->cfa_how = CFIC_IA_BPREL; # elif defined(VGA_arm) si_m->cfa_how = CFIC_ARM_R12REL; @@ -2786,6 +2798,30 @@ static Bool summarise_context(/*OUT*/Addr* base, # elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) /* These don't use CFI based unwinding (is that really true?) */ +# elif defined(VGA_riscv64) + + /* --- entire tail of this fn specialised for riscv64 --- */ + + SUMMARISE_HOW(si_m->ra_how, si_m->ra_off, ctxs->reg[ctx->ra_reg]); + SUMMARISE_HOW(si_m->fp_how, si_m->fp_off, ctxs->reg[FP_REG]); + + /* on riscv64, it seems the old sp value before the call is always + the same as the CFA. Therefore ... */ + si_m->sp_how = CFIR_CFAREL; + si_m->sp_off = 0; + + /* bogus looking range? Note, we require that the difference is + representable in 32 bits. */ + if (loc_start >= ctx->loc) + { why = 4; goto failed; } + if (ctx->loc - loc_start > 10000000 /* let's say */) + { why = 5; goto failed; } + + *base = loc_start + ctx->initloc; + *len = (UInt)(ctx->loc - loc_start); + + return True; + # else # error "Unknown arch" # endif @@ -2884,7 +2920,7 @@ static Int copy_convert_CfiExpr_tree ( XArray* dstxa, if (dwreg == srcuc->ra_reg) return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_X30 ); # elif defined(VGA_ppc32) || defined(VGA_ppc64be) \ - || defined(VGA_ppc64le) + || defined(VGA_ppc64le) || defined(VGA_riscv64) # else # error "Unknown arch" # endif diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index 77ed4798b..1dadbc72c 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -1786,7 +1786,8 @@ static HChar* readlink_path (const HChar *path) while (tries > 0) { SysRes res; -#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, (UWord)buf, bufsiz); #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) @@ -2711,6 +2712,7 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di ) || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) \ || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \ || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \ || defined(VGP_arm64_freebsd) diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index ef6a40051..12ad68130 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -260,6 +260,11 @@ void ML_(ppDiCfSI) ( const XArray* /* of CfiExpr */ exprs, SHOW_HOW(si_m->x30_how, si_m->x30_off); VG_(printf)(" X29="); SHOW_HOW(si_m->x29_how, si_m->x29_off); +# elif defined(VGA_riscv64) + VG_(printf)(" SP="); + SHOW_HOW(si_m->sp_how, si_m->sp_off); + VG_(printf)(" FP="); + SHOW_HOW(si_m->fp_how, si_m->fp_off); # else # error "Unknown arch" # endif diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c index cad95bcbe..225e5a085 100644 --- a/coregrind/m_debuglog.c +++ b/coregrind/m_debuglog.c @@ -637,6 +637,34 @@ static UInt local_sys_getpid ( void ) return a0; } +#elif defined(VGP_riscv64_linux) + +static UInt local_sys_write_stderr ( const HChar* buf, Int n ) +{ + register RegWord a0 asm("a0") = 2; /* stderr */ + register RegWord a1 asm("a1") = (RegWord)buf; + register RegWord a2 asm("a2") = n; + register RegWord a7 asm("a7") = __NR_write; + __asm__ volatile ( + "ecall\n" + : "+r" (a0) + : "r" (a1), "r" (a2), "r" (a7) + ); + return a0 >= 0 ? (UInt)a0 : -1; +} + +static UInt local_sys_getpid ( void ) +{ + register RegWord a0 asm("a0"); + register RegWord a7 asm("a7") = __NR_getpid; + __asm__ volatile ( + "ecall\n" + : "=r" (a0) + : "r" (a7) + ); + return (UInt)a0; +} + #elif defined(VGP_x86_solaris) static UInt local_sys_write_stderr ( const HChar* buf, Int n ) { diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c index f9f32f4aa..4238c608c 100644 --- a/coregrind/m_gdbserver/target.c +++ b/coregrind/m_gdbserver/target.c @@ -867,6 +867,8 @@ void valgrind_initialize_target(void) mips64_init_architecture(&the_low_target); #elif defined(VGA_nanomips) nanomips_init_architecture(&the_low_target); +#elif defined(VGA_riscv64) + riscv64_init_architecture(&the_low_target); #else #error "architecture missing in target.c valgrind_initialize_target" #endif diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h index d8ae3c908..ef4e19089 100644 --- a/coregrind/m_gdbserver/valgrind_low.h +++ b/coregrind/m_gdbserver/valgrind_low.h @@ -109,5 +109,6 @@ extern void s390x_init_architecture (struct valgrind_target_ops *target); extern void mips32_init_architecture (struct valgrind_target_ops *target); extern void mips64_init_architecture (struct valgrind_target_ops *target); extern void nanomips_init_architecture (struct valgrind_target_ops *target); +extern void riscv64_init_architecture (struct valgrind_target_ops *target); #endif diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index feec1e5f1..483b7a3dd 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -910,9 +910,13 @@ Addr setup_client_stack( void* init_sp, && !defined(VGP_ppc64le_linux) \ && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) \ && !defined(VGP_nanomips_linux) \ - && !defined(VGP_s390x_linux) + && !defined(VGP_s390x_linux) \ + && !defined(VGP_riscv64_linux) case AT_SYSINFO_EHDR: { /* Trash this, because we don't reproduce it */ + /* riscv64-linux: Keep the VDSO mapping on this platform present. + It contains __vdso_rt_sigreturn() which the kernel sets the ra + register to point to on a signal delivery. */ const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr); vg_assert(ehdrseg); VG_(am_munmap_valgrind)(ehdrseg->start, ehdrseg->end - ehdrseg->start); @@ -1341,6 +1345,35 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) arch->vex.guest_PC = iifii.initial_client_IP; arch->vex.guest_r31 = iifii.initial_client_SP; +# elif defined(VGP_riscv64_linux) + vg_assert(0 == sizeof(VexGuestRISCV64State) % LibVEX_GUEST_STATE_ALIGN); + + /* Zero out the initial state. */ + LibVEX_GuestRISCV64_initialise(&arch->vex); + + /* Mark all registers as undefined ... */ + VG_(memset)(&arch->vex_shadow1, 0xFF, sizeof(VexGuestRISCV64State)); + VG_(memset)(&arch->vex_shadow2, 0x00, sizeof(VexGuestRISCV64State)); + /* ... except x2 (sp), pc and fcsr. */ + arch->vex_shadow1.guest_x2 = 0; + arch->vex_shadow1.guest_pc = 0; + arch->vex_shadow1.guest_fcsr = 0; + + /* Put essential stuff into the new state. */ + arch->vex.guest_x2 = iifii.initial_client_SP; + arch->vex.guest_pc = iifii.initial_client_IP; + /* Initialize fcsr in the same way as done by the Linux kernel: + accrued exception flags cleared; round to nearest, ties to even. */ + arch->vex.guest_fcsr = 0; + + /* Tell the tool about the registers we just wrote. */ + VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_STACK_PTR, 8); + VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8); + VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, + offsetof(VexGuestRISCV64State, guest_fcsr), 4); + +#define PRECISE_GUEST_REG_DEFINEDNESS_AT_STARTUP 1 + # else # error Unknown platform # endif diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index 257c26bc6..c6380d4e0 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -264,6 +264,25 @@ (srP)->misc.MIPS32.r31 = (UInt)ra; \ (srP)->misc.MIPS32.r28 = (UInt)gp; \ } +#elif defined(VGP_riscv64_linux) +# define GET_STARTREGS(srP) \ + { ULong pc, sp, fp, ra; \ + __asm__ __volatile__( \ + "jal %0, 0f;" \ + "0:\n" \ + "mv %1, sp;" \ + "mv %2, fp;" \ + "mv %3, ra;" \ + : "=r" (pc), \ + "=r" (sp), \ + "=r" (fp), \ + "=r" (ra) \ + ); \ + (srP)->r_pc = pc; \ + (srP)->r_sp = sp; \ + (srP)->misc.RISCV64.r_fp = fp; \ + (srP)->misc.RISCV64.r_ra = ra; \ + } #else # error Unknown platform #endif diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index fb93b4867..e132e7659 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -264,8 +264,9 @@ Bool VG_(resolve_filemode) ( Int fd, Int * result ) SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev ) { -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) - /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */ +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) + /* More recent Linux platforms have only __NR_mknodat and no __NR_mknod. */ SysRes res = VG_(do_syscall4)(__NR_mknodat, VKI_AT_FDCWD, (UWord)pathname, mode, dev); # elif defined(VGO_linux) || defined(VGO_darwin) @@ -290,8 +291,9 @@ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev ) SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode ) { -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) - /* ARM64 wants to use __NR_openat rather than __NR_open. */ +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) + /* More recent Linux platforms have only __NR_openat and no __NR_open. */ SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, flags, mode); # elif defined(VGO_linux) || defined(VGO_freebsd) @@ -384,7 +386,8 @@ Int VG_(pipe) ( Int fd[2] ) } else { return -1; } -# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0); return sr_isError(res) ? -1 : 0; # elif defined(VGO_linux) @@ -731,7 +734,8 @@ SysRes VG_(dup) ( Int oldfd ) SysRes VG_(dup2) ( Int oldfd, Int newfd ) { -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) /* We only have dup3, that means we have to mimic dup2. The only real difference is when oldfd == newfd. dup3 always returns an error, but dup2 returns only an @@ -777,7 +781,7 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name ) # if defined(VGO_solaris) || defined(VGP_arm64_linux) SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name, VKI_AT_FDCWD, (UWord)new_name); -# elif defined(VGP_nanomips_linux) +# elif defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name, VKI_AT_FDCWD, (UWord)new_name, 0); @@ -791,7 +795,8 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name ) Int VG_(unlink) ( const HChar* file_name ) { -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD, (UWord)file_name); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) @@ -870,8 +875,9 @@ const HChar *VG_(get_startup_wd) ( void ) SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout) { SysRes res; -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) - /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */ +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) + /* More recent Linux platforms have only __NR_ppoll and no __NR_poll. */ struct vki_timespec timeout_ts; if (timeout >= 0) { timeout_ts.tv_sec = timeout / 1000; @@ -915,7 +921,8 @@ SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz) { SysRes res; /* res = readlink( path, buf, bufsiz ); */ -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, (UWord)buf, bufsiz); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) @@ -994,7 +1001,8 @@ Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr ) UWord w = (irusr ? VKI_R_OK : 0) | (iwusr ? VKI_W_OK : 0) | (ixusr ? VKI_X_OK : 0); -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); @@ -1140,7 +1148,8 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) return res; # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ - || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) + || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); return res; # elif defined(VGP_amd64_freebsd) || defined(VGP_arm64_freebsd) @@ -1405,7 +1414,8 @@ Int VG_(socket) ( Int domain, Int type, Int protocol ) # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ - || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd) + || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); return sr_isError(res) ? -1 : sr_Res(res); @@ -1460,7 +1470,8 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ - || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd) + || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); return sr_isError(res) ? -1 : sr_Res(res); @@ -1507,7 +1518,8 @@ Int VG_(write_socket)( Int sd, const void *msg, Int count ) # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ - || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd) + || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, VKI_MSG_NOSIGNAL, 0,0); @@ -1544,8 +1556,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ - || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \ - || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) \ + || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall3)( __NR_getsockname, (UWord)sd, (UWord)name, (UWord)namelen ); @@ -1584,7 +1596,8 @@ Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ - || defined(VGP_nanomips_linux) || defined(VGO_freebsd) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) \ + || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall3)( __NR_getpeername, (UWord)sd, (UWord)name, (UWord)namelen ); @@ -1626,7 +1639,7 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ - || defined(VGO_freebsd) + || defined(VGP_riscv64_linux) || defined(VGO_freebsd) SysRes res; res = VG_(do_syscall5)( __NR_getsockopt, (UWord)sd, (UWord)level, (UWord)optname, @@ -1670,7 +1683,8 @@ Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval, # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ - || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) + || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) SysRes res; res = VG_(do_syscall5)( __NR_setsockopt, (UWord)sd, (UWord)level, (UWord)optname, diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c index 280ab1cff..c70f229e5 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -698,7 +698,8 @@ Int VG_(gettid)(void) * the /proc/self link is pointing... */ -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)"/proc/self", (UWord)pid, sizeof(pid)); @@ -753,7 +754,8 @@ Int VG_(getpid) ( void ) Int VG_(getpgrp) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) return sr_Res( VG_(do_syscall1)(__NR_getpgid, 0) ); # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) return sr_Res( VG_(do_syscall0)(__NR_getpgrp) ); @@ -850,7 +852,7 @@ Int VG_(getgroups)( Int size, UInt* list ) || defined(VGO_darwin) || defined(VGP_s390x_linux) \ || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) \ || defined(VGO_solaris) || defined(VGP_nanomips_linux) \ - || defined(VGO_freebsd) + || defined(VGP_riscv64_linux) || defined(VGO_freebsd) SysRes sres; sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list); if (sr_isError(sres)) @@ -951,7 +953,8 @@ Int VG_(fork) ( void ) fds[0] = fds[1] = -1; } -# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) +# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) SysRes res; res = VG_(do_syscall5)(__NR_clone, VKI_SIGCHLD, (UWord)NULL, (UWord)NULL, (UWord)NULL, (UWord)NULL); @@ -1426,10 +1429,22 @@ void VG_(invalidate_icache) ( void *ptr, SizeT nbytes ) (UWord) nbytes, (UWord) 3); vg_assert( !sr_isError(sres) ); -# elif defined(VGA_nanomips) - +# elif defined(VGA_nanomips) __builtin___clear_cache(ptr, (char*)ptr + nbytes); +# elif defined(VGP_riscv64_linux) + /* Make data stores to the area visible to all RISC-V harts. */ + __asm__ __volatile__("fence w,r"); + + /* Ask the kernel to execute fence.i on all harts to guarantee that an + instruction fetch on each hart will see any previous data stores visible + to the same hart. */ + Addr startaddr = (Addr)ptr; + Addr endaddr = startaddr + nbytes; + SysRes sres = VG_(do_syscall3)(__NR_riscv_flush_icache, startaddr, endaddr, + 0 /*flags*/); + vg_assert(!sr_isError(sres)); + # endif } diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 234efb312..dec4f2373 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -152,6 +152,11 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs, = VG_(threads)[tid].arch.vex.guest_r31; regs->misc.MIPS64.r28 = VG_(threads)[tid].arch.vex.guest_r28; +# elif defined(VGA_riscv64) + regs->r_pc = VG_(threads)[tid].arch.vex.guest_pc; + regs->r_sp = VG_(threads)[tid].arch.vex.guest_x2; + regs->misc.RISCV64.r_fp = VG_(threads)[tid].arch.vex.guest_x8; + regs->misc.RISCV64.r_ra = VG_(threads)[tid].arch.vex.guest_x1; # else # error "Unknown arch" # endif @@ -369,6 +374,39 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, (*f)(tid, "x28", vex->guest_X28); (*f)(tid, "x29", vex->guest_X29); (*f)(tid, "x30", vex->guest_X30); +#elif defined(VGA_riscv64) + (*f)(tid, "x0" , vex->guest_x0 ); + (*f)(tid, "x1" , vex->guest_x1 ); + (*f)(tid, "x2" , vex->guest_x2 ); + (*f)(tid, "x3" , vex->guest_x3 ); + (*f)(tid, "x4" , vex->guest_x4 ); + (*f)(tid, "x5" , vex->guest_x5 ); + (*f)(tid, "x6" , vex->guest_x6 ); + (*f)(tid, "x7" , vex->guest_x7 ); + (*f)(tid, "x8" , vex->guest_x8 ); + (*f)(tid, "x9" , vex->guest_x9 ); + (*f)(tid, "x10", vex->guest_x10); + (*f)(tid, "x11", vex->guest_x11); + (*f)(tid, "x12", vex->guest_x12); + (*f)(tid, "x13", vex->guest_x13); + (*f)(tid, "x14", vex->guest_x14); + (*f)(tid, "x15", vex->guest_x15); + (*f)(tid, "x16", vex->guest_x16); + (*f)(tid, "x17", vex->guest_x17); + (*f)(tid, "x18", vex->guest_x18); + (*f)(tid, "x19", vex->guest_x19); + (*f)(tid, "x20", vex->guest_x20); + (*f)(tid, "x21", vex->guest_x21); + (*f)(tid, "x22", vex->guest_x22); + (*f)(tid, "x23", vex->guest_x23); + (*f)(tid, "x24", vex->guest_x24); + (*f)(tid, "x25", vex->guest_x25); + (*f)(tid, "x26", vex->guest_x26); + (*f)(tid, "x27", vex->guest_x27); + (*f)(tid, "x28", vex->guest_x28); + (*f)(tid, "x29", vex->guest_x29); + (*f)(tid, "x30", vex->guest_x30); + (*f)(tid, "x31", vex->guest_x31); #else # error Unknown arch #endif @@ -2241,6 +2279,22 @@ Bool VG_(machine_get_hwcaps)( void ) return True; } + +#elif defined(VGA_riscv64) + { + va = VexArchRISCV64; + vai.endness = VexEndnessLE; + + /* Hardware baseline is RV64GC. */ + vai.hwcaps = 0; + + VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps); + + VG_(machine_get_cache_info)(&vai); + + return True; + } + #else # error "Unknown arch" #endif @@ -2381,6 +2435,10 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void ) # elif defined(VGA_mips64) return 8; +# elif defined(VGA_riscv64) + /* 64-bit integer and floating-point registers, no vector set. */ + return 8; + # else # error "Unknown arch" # endif @@ -2397,7 +2455,7 @@ void* VG_(fnptr_to_fnentry)( void* f ) || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \ - || defined(VGP_nanomips_linux) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) return f; # elif defined(VGP_ppc64be_linux) /* ppc64-linux uses the AIX scheme, in which f is a pointer to a diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 3f07e57a9..877e6b0b6 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -2554,6 +2554,11 @@ static void final_tidyup(ThreadId tid) VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, offsetof(VexGuestPPC64State, guest_GPR3), sizeof(VG_(threads)[tid].arch.vex.guest_GPR3)); +# elif defined(VGA_riscv64) + VG_(threads)[tid].arch.vex.guest_x10 = to_run; + VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, + offsetof(VexGuestRISCV64State, guest_x10), + sizeof(VG_(threads)[tid].arch.vex.guest_x10)); # elif defined(VGA_s390x) VG_(threads)[tid].arch.vex.guest_r2 = to_run; VG_TRACK(post_reg_write, Vg_CoreClientReq, tid, @@ -3087,6 +3092,33 @@ asm( ".set pop \n\t" ".previous \n\t" ); +#elif defined(VGP_riscv64_linux) +asm("\n" + "\t.text\n" + "\t.type _start,@function\n" + "\t.global _start\n" + "_start:\n" + /* establish the global pointer in gp */ + ".option push\n" + ".option norelax\n" + "\tla gp, __global_pointer$\n" + ".option pop\n" + /* set up the new stack in t0 */ + "\tla t0, vgPlain_interim_stack\n" + "\tli t1, "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n" + "\tadd t0, t0, t1\n" + "\tli t1, "VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)"\n" + "\tadd t0, t0, t1\n" + "\tli t1, 0xFFFFFF00\n" + "\tand t0, t0, t1\n" + /* install it, and collect the original one */ + "\tmv a0, sp\n" + "\tmv sp, t0\n" + /* call _start_in_C_linux, passing it the startup sp */ + "\tj _start_in_C_linux\n" + "\tunimp\n" + ".previous\n" +); #else # error "Unknown platform" #endif diff --git a/coregrind/m_options.c b/coregrind/m_options.c index ecbe9fc3a..16452f252 100644 --- a/coregrind/m_options.c +++ b/coregrind/m_options.c @@ -203,7 +203,8 @@ UInt VG_(clo_unw_stack_scan_frames) = 5; VgSmc VG_(clo_smc_check) = Vg_SmcAllNonFile; #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ || defined(VGA_arm) || defined(VGA_arm64) \ - || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) + || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \ + || defined(VGA_riscv64) VgSmc VG_(clo_smc_check) = Vg_SmcStack; #else # error "Unknown arch" diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index 6c360d59c..958f3e7c4 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -1253,6 +1253,7 @@ Bool VG_(is_soname_ld_so) (const HChar *soname) if (VG_STREQ(soname, VG_U_LD_LINUX_AARCH64_SO_1)) return True; if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3)) return True; if (VG_STREQ(soname, VG_U_LD_LINUX_MIPSN8_S0_1)) return True; + if (VG_STREQ(soname, VG_U_LD_LINUX_RISCV64_SO_1)) return True; # elif defined(VGO_freebsd) if (VG_STREQ(soname, VG_U_LD_ELF_SO_1)) return True; if (VG_STREQ(soname, VG_U_LD_ELF32_SO_1)) return True; @@ -1701,6 +1702,20 @@ void VG_(redir_initialise) ( void ) ); } +# elif defined(VGP_riscv64_linux) + if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { + add_hardwired_spec( + "ld-linux-riscv64-lp64d.so.1", "strlen", + (Addr)&VG_(riscv64_linux_REDIR_FOR_strlen), + complain_about_stripped_glibc_ldso + ); + add_hardwired_spec( + "ld-linux-riscv64-lp64d.so.1", "index", + (Addr)&VG_(riscv64_linux_REDIR_FOR_index), + complain_about_stripped_glibc_ldso + ); + } + # elif defined(VGP_x86_solaris) /* If we're using memcheck, use these intercepts right from the start, otherwise ld.so makes a lot of noise. */ diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index cc8d070b7..51ba34361 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -893,6 +893,10 @@ static void do_pre_run_checks ( volatile ThreadState* tst ) # if defined(VGA_mips32) || defined(VGA_mips64) /* no special requirements */ # endif + +# if defined(VGA_riscv64) + /* no special requirements */ +# endif } // NO_VGDB_POLL value ensures vgdb is not polled, while @@ -1007,6 +1011,8 @@ void run_thread_for_a_while ( /*OUT*/HWord* two_words, tst->arch.vex.guest_LLaddr = (RegWord)(-1); # elif defined(VGP_arm64_linux) || defined(VGP_arm64_freebsd) tst->arch.vex.guest_LLSC_SIZE = 0; +# elif defined(VGP_riscv64_linux) + tst->arch.vex.guest_LLSC_SIZE = 0; # endif if (0) { @@ -1851,6 +1857,9 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src ) #elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) # define VG_CLREQ_ARGS guest_r12 # define VG_CLREQ_RET guest_r11 +#elif defined(VGA_riscv64) +# define VG_CLREQ_ARGS guest_x14 +# define VG_CLREQ_RET guest_x13 #else # error Unknown arch #endif diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 66fbbfe72..53614d303 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -643,6 +643,19 @@ VgHashTable *ht_sigchld_ignore = NULL; (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \ } +#elif defined(VGP_riscv64_linux) +# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.sc_regs.pc) +# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.sc_regs.sp) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.sc_regs.a0 into a SysRes. */ \ + VG_(mk_SysRes_riscv64_linux)( (uc)->uc_mcontext.sc_regs.a0 ) +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (uc)->uc_mcontext.sc_regs.pc; \ + (srP)->r_sp = (uc)->uc_mcontext.sc_regs.sp; \ + (srP)->misc.RISCV64.r_fp = (uc)->uc_mcontext.sc_regs.s0; \ + (srP)->misc.RISCV64.r_ra = (uc)->uc_mcontext.sc_regs.ra; \ + } + #elif defined(VGP_x86_solaris) # define VG_UCONTEXT_INSTR_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_EIP]) # define VG_UCONTEXT_STACK_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_UESP]) @@ -670,6 +683,7 @@ VgHashTable *ht_sigchld_ignore = NULL; (srP)->r_sp = (uc)->uc_mcontext.gregs[VKI_REG_RSP]; \ (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.gregs[VKI_REG_RBP]; \ } + #else # error Unknown platform #endif @@ -914,8 +928,10 @@ void calculate_SKSS_from_SCSS ( SKSS* dst ) if (skss_handler != VKI_SIG_IGN && skss_handler != VKI_SIG_DFL) skss_flags |= VKI_SA_SIGINFO; +# if !defined(VGP_riscv64_linux) /* use our own restorer */ skss_flags |= VKI_SA_RESTORER; +# endif /* Create SKSS entry for this signal. */ if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP) @@ -1067,6 +1083,16 @@ extern void my_sigreturn(void); " li $t4, " #name "\n" \ " syscall[32]\n" \ ".previous\n" + +#elif defined(VGP_riscv64_linux) +/* Not used on riscv64. */ +# define _MY_SIGRETURN(name) \ + ".text\n" \ + ".globl my_sigreturn\n" \ + "my_sigreturn:\n" \ + " unimp\n" \ + ".previous\n" + #elif defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) /* Not used on Solaris. */ # define _MY_SIGRETURN(name) \ @@ -1132,9 +1158,10 @@ static void handle_SCSS_change ( Bool force_update ) ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; -# if !defined(VGP_ppc32_linux) && \ +# if !defined(VGP_ppc32_linux) && !defined(VGP_mips32_linux) && \ + !defined(VGP_riscv64_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ - !defined(VGP_mips32_linux) && !defined(VGO_solaris) && !defined(VGO_freebsd) + !defined(VGO_solaris) && !defined(VGO_freebsd) ksa.sa_restorer = my_sigreturn; # endif /* Re above ifdef (also the assertion below), PaulM says: @@ -1178,11 +1205,11 @@ static void handle_SCSS_change ( Bool force_update ) # endif vg_assert(ksa_old.sa_flags == skss_old.skss_per_sig[sig].skss_flags); -# if !defined(VGP_ppc32_linux) && \ +# if !defined(VGP_ppc32_linux) && !defined(VGP_mips32_linux) && \ + !defined(VGP_mips64_linux) && !defined(VGP_nanomips_linux) && \ + !defined(VGP_riscv64_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ - !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \ - !defined(VGP_nanomips_linux) && !defined(VGO_solaris) && \ - !defined(VGO_freebsd) + !defined(VGO_solaris) && !defined(VGO_freebsd) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); @@ -1302,8 +1329,8 @@ SysRes VG_(do_sys_sigaction) ( Int signo, old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler; old_act->sa_flags = scss.scss_per_sig[signo].scss_flags; old_act->sa_mask = scss.scss_per_sig[signo].scss_mask; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer; # endif } @@ -1315,8 +1342,8 @@ SysRes VG_(do_sys_sigaction) ( Int signo, scss.scss_per_sig[signo].scss_mask = new_act->sa_mask; scss.scss_per_sig[signo].scss_restorer = NULL; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer; # endif @@ -1675,8 +1702,8 @@ void VG_(kill_self)(Int sigNo) sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) sa.sa_restorer = 0; # endif VG_(sigemptyset)(&sa.sa_mask); @@ -3067,8 +3094,8 @@ void pp_ksigaction ( vki_sigaction_toK_t* sa ) VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", sa->ksa_handler, (UInt)sa->sa_flags, -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) sa->sa_restorer # else (void*)0 @@ -3090,8 +3117,8 @@ void VG_(set_default_handler)(Int signo) sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) sa.sa_restorer = 0; # endif VG_(sigemptyset)(&sa.sa_mask); @@ -3212,8 +3239,8 @@ void VG_(sigstartup_actions) ( void ) tsa.ksa_handler = (void *)sync_signalhandler; tsa.sa_flags = VKI_SA_SIGINFO; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) tsa.sa_restorer = 0; # endif VG_(sigfillset)(&tsa.sa_mask); @@ -3240,8 +3267,8 @@ void VG_(sigstartup_actions) ( void ) scss.scss_per_sig[i].scss_mask = sa.sa_mask; scss.scss_per_sig[i].scss_restorer = NULL; -# if !defined(VGO_darwin) && !defined(VGO_freebsd) && \ - !defined(VGO_solaris) +# if !defined(VGP_riscv64_linux) && !defined(VGO_darwin) && \ + !defined(VGO_freebsd) && !defined(VGO_solaris) scss.scss_per_sig[i].scss_restorer = sa.sa_restorer; # endif diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 630b5b875..cbeaab9db 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -1529,6 +1529,101 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, #endif +/* ------------------------ riscv64 ------------------------- */ + +#if defined(VGP_riscv64_linux) + +UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, + /*OUT*/Addr* ips, UInt max_n_ips, + /*OUT*/Addr* sps, /*OUT*/Addr* fps, + const UnwindStartRegs* startRegs, + Addr fp_max_orig ) +{ + Bool debug = False; + Int i; + Addr fp_max; + UInt n_found = 0; + const Int cmrf = VG_(clo_merge_recursive_frames); + + vg_assert(sizeof(Addr) == sizeof(UWord)); + vg_assert(sizeof(Addr) == sizeof(void*)); + + D3UnwindRegs uregs; + uregs.pc = startRegs->r_pc; + uregs.sp = startRegs->r_sp; + uregs.fp = startRegs->misc.RISCV64.r_fp; + uregs.ra = startRegs->misc.RISCV64.r_ra; + Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB; + + /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1], + stopping when the trail goes cold, which we guess to be + when FP is not a reasonable stack location. */ + + fp_max = fp_max_orig; + if (fp_max >= sizeof(Addr)) + fp_max -= sizeof(Addr); + + if (debug) + VG_(printf)("\nmax_n_ips=%u fp_min=0x%lx fp_max_orig=0x%lx, " + "fp_max=0x%lx pc=0x%lx sp=0x%lx fp=0x%lx ra=0x%lx\n", + max_n_ips, fp_min, fp_max_orig, fp_max, + uregs.pc, uregs.sp, uregs.fp, uregs.ra); + + if (sps) sps[0] = uregs.sp; + if (fps) fps[0] = uregs.fp; + ips[0] = uregs.pc; + i = 1; + + /* Loop unwinding the stack, using CFI. */ + while (True) { + if (debug) + VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n", + i, uregs.pc, uregs.sp, uregs.fp, uregs.ra); + if (i >= max_n_ips) + break; + + if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) { + if (sps) sps[i] = uregs.sp; + if (fps) fps[i] = uregs.fp; + ips[i++] = uregs.pc - 1; + if (debug) + VG_(printf)( + "USING CFI: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n", + uregs.pc, uregs.sp, uregs.fp, uregs.ra); + uregs.pc = uregs.pc - 1; + RECURSIVE_MERGE(cmrf,ips,i); + continue; + } + + /* A problem on the first frame? Lets assume it was a bad jump. + We will use the link register and the current stack and frame + pointers and see if we can use the CFI in the next round. */ + if (i == 1) { + uregs.pc = uregs.ra; + uregs.ra = 0; + + if (sps) sps[i] = uregs.sp; + if (fps) fps[i] = uregs.fp; + ips[i++] = uregs.pc - 1; + if (debug) + VG_(printf)( + "USING bad-jump: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n", + uregs.pc, uregs.sp, uregs.fp, uregs.ra); + uregs.pc = uregs.pc - 1; + RECURSIVE_MERGE(cmrf,ips,i); + continue; + } + + /* No luck. We have to give up. */ + break; + } + + n_found = i; + return n_found; +} + +#endif + /*------------------------------------------------------------*/ /*--- ---*/ /*--- END platform-dependent unwinder worker functions ---*/ diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c index 6ab20694d..8ff9c90bd 100644 --- a/coregrind/m_syscall.c +++ b/coregrind/m_syscall.c @@ -204,6 +204,17 @@ SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) { return res; } +SysRes VG_(mk_SysRes_riscv64_linux) ( Long val ) { + SysRes res; + res._isError = val >= -4095 && val <= -1; + if (res._isError) { + res._val = (ULong)(-val); + } else { + res._val = (ULong)val; + } + return res; +} + /* Generic constructors. */ SysRes VG_(mk_SysRes_Success) ( UWord res ) { SysRes r; @@ -1076,6 +1087,30 @@ asm ( ".previous \n\t" ); +#elif defined(VGP_riscv64_linux) +/* Calling convention is: args in a0-a5, sysno in a7, return value in a0. + Return value follows the usual convention that -4095 .. -1 (both inclusive) + is an error value. All other values are success values. + + Registers a0 to a5 remain unchanged, but syscall_no is in a6 and needs to be + moved to a7. +*/ +extern UWord do_syscall_WRK ( + UWord a1, UWord a2, UWord a3, + UWord a4, UWord a5, UWord a6, + UWord syscall_no + ); +asm( +".text\n" +".globl do_syscall_WRK\n" +"do_syscall_WRK:\n" +" mv a7, a6\n" +" li a6, 0\n" +" ecall\n" +" ret\n" +".previous\n" +); + #elif defined(VGP_x86_solaris) extern ULong @@ -1324,6 +1359,10 @@ SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3, do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, ®_a0); return VG_(mk_SysRes_nanomips_linux)(reg_a0); +# elif defined(VGP_riscv64_linux) + UWord val = do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno); + return VG_(mk_SysRes_riscv64_linux)(val); + # elif defined(VGP_x86_solaris) UInt val, val2, err = False; Bool restart; diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h index 1bdd9a94e..6e6356608 100644 --- a/coregrind/m_syswrap/priv_syswrap-linux.h +++ b/coregrind/m_syswrap/priv_syswrap-linux.h @@ -528,6 +528,13 @@ extern UInt do_syscall_clone_nanomips_linux ( Word (*fn) (void *), /* a0 - 4 */ Int* child_tid, /* a4 - 8 */ Int* parent_tid, /* a5 - 9 */ void* tls_ptr); /* a6 - 10 */ +extern UInt do_syscall_clone_riscv64_linux ( Word (*fn) (void *), + void* stack, + Int flags, + void* arg, + Int* child_tid, + Int* parent_tid, + void* tls_ptr); #endif // __PRIV_SYSWRAP_LINUX_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h index 6be22f8e7..cc00592ef 100644 --- a/coregrind/m_syswrap/priv_types_n_macros.h +++ b/coregrind/m_syswrap/priv_types_n_macros.h @@ -94,7 +94,7 @@ typedef || defined(VGP_ppc32_linux) \ || defined(VGP_arm_linux) || defined(VGP_s390x_linux) \ || defined(VGP_arm64_linux) \ - || defined(VGP_nanomips_linux) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) Int o_arg1; Int o_arg2; Int o_arg3; diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index c3f916a1e..175c94b4d 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -3756,7 +3756,7 @@ POST(sys_newfstat) #endif #if !defined(VGO_solaris) && !defined(VGP_arm64_linux) && \ - !defined(VGP_nanomips_linux) + !defined(VGP_nanomips_linux) && !defined(VGP_riscv64_linux) static vki_sigset_t fork_saved_mask; // In Linux, the sys_fork() function varies across architectures, but we @@ -3807,7 +3807,7 @@ PRE(sys_fork) VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); } } -#endif // !defined(VGO_solaris) && !defined(VGP_arm64_linux) +#endif PRE(sys_ftruncate) { diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 83af91344..d2259bdd8 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -310,6 +310,16 @@ static void run_a_thread_NORETURN ( Word tidW ) : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode) : "memory" , "$t4", "$a0" ); +#elif defined(VGP_riscv64_linux) + asm volatile ( + "sw %1, %0\n" /* set tst->status = VgTs_Empty */ + "li a7, %2\n" /* set a7 = __NR_exit */ + "ld a0, %3\n" /* set a0 = tst->os_state.exitcode */ + "ecall\n" /* exit(tst->os_state.exitcode) */ + : "=m" (tst->status) + : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode) + : "a7", "a0" + ); #else # error Unknown platform #endif @@ -535,6 +545,13 @@ static SysRes clone_new_thread ( Word (*fn)(void *), (ML_(start_thread_NORETURN), stack, flags, ctst, child_tidptr, parent_tidptr, NULL); res = VG_ (mk_SysRes_nanomips_linux) (ret); +#elif defined(VGP_riscv64_linux) + ULong a0; + ctst->arch.vex.guest_x10 = 0; + a0 = do_syscall_clone_riscv64_linux + (ML_(start_thread_NORETURN), stack, flags, ctst, + child_tidptr, parent_tidptr, NULL); + res = VG_(mk_SysRes_riscv64_linux)( a0 ); #else # error Unknown platform #endif @@ -597,6 +614,8 @@ static SysRes setup_child_tls (ThreadId ctid, Addr tlsaddr) #elif defined(VGP_mips32_linux) || defined(VGP_nanomips_linux) ctst->arch.vex.guest_ULR = tlsaddr; ctst->arch.vex.guest_r27 = tlsaddr; +#elif defined(VGP_riscv64_linux) + ctst->arch.vex.guest_x4 = tlsaddr; #else # error Unknown platform #endif @@ -755,7 +774,7 @@ static SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ - || defined(VGP_nanomips_linux) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) res = VG_(do_syscall5)( __NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, (UWord)NULL, (UWord)child_tidptr ); @@ -823,7 +842,7 @@ PRE(sys_clone) || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \ - || defined(VGP_nanomips_linux) + || defined(VGP_nanomips_linux) || defined(VGP_riscv64_linux) #define ARG_CHILD_TIDPTR ARG5 #define PRA_CHILD_TIDPTR PRA5 #define ARG_TLS ARG4 @@ -4413,9 +4432,13 @@ PRE(sys_sigaction) PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); +# if !defined(VGP_riscv64_linux) + /* Check the sa_restorer field. More recent Linux platforms completely + drop this member. */ if (ML_(safe_to_deref)(sa,sizeof(struct vki_old_sigaction)) && (sa->sa_flags & VKI_SA_RESTORER)) PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer)); +# endif } if (ARG3 != 0) { @@ -4531,9 +4554,11 @@ PRE(sys_rt_sigaction) PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); +# if !defined(VGP_riscv64_linux) if (ML_(safe_to_deref)(sa,sizeof(vki_sigaction_toK_t)) && (sa->sa_flags & VKI_SA_RESTORER)) PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer)); +# endif } if (ARG3 != 0) PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(vki_sigaction_fromK_t)); @@ -6909,7 +6934,8 @@ POST(sys_lookup_dcookie) #endif #if defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \ - || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) + || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \ + || defined(VGP_riscv64_linux) PRE(sys_lookup_dcookie) { *flags |= SfMayBlock; diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index be4ac0f08..1a7f038d4 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -868,6 +868,18 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, canonical->arg7 = 0; canonical->arg8 = 0; +#elif defined(VGP_riscv64_linux) + VexGuestRISCV64State* gst = (VexGuestRISCV64State*)gst_vanilla; + canonical->sysno = gst->guest_x17; /* a7 */ + canonical->arg1 = gst->guest_x10; /* a0 */ + canonical->arg2 = gst->guest_x11; /* a1 */ + canonical->arg3 = gst->guest_x12; /* a2 */ + canonical->arg4 = gst->guest_x13; /* a3 */ + canonical->arg5 = gst->guest_x14; /* a4 */ + canonical->arg6 = gst->guest_x15; /* a5 */ + canonical->arg7 = 0; + canonical->arg8 = 0; + #elif defined(VGP_x86_solaris) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; UWord *stack = (UWord *)gst->guest_ESP; @@ -1192,6 +1204,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, gst->guest_r10 = canonical->arg7; gst->guest_r11 = canonical->arg8; +#elif defined(VGP_riscv64_linux) + VexGuestRISCV64State* gst = (VexGuestRISCV64State*)gst_vanilla; + gst->guest_x17 = canonical->sysno; /* a7 */ + gst->guest_x10 = canonical->arg1; /* a0 */ + gst->guest_x11 = canonical->arg2; /* a1 */ + gst->guest_x12 = canonical->arg3; /* a2 */ + gst->guest_x13 = canonical->arg4; /* a3 */ + gst->guest_x14 = canonical->arg5; /* a4 */ + gst->guest_x15 = canonical->arg6; /* a5 */ + #elif defined(VGP_x86_solaris) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; UWord *stack = (UWord *)gst->guest_ESP; @@ -1391,6 +1413,11 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 ); canonical->what = SsComplete; +# elif defined(VGP_riscv64_linux) + VexGuestRISCV64State* gst = (VexGuestRISCV64State*)gst_vanilla; + canonical->sres = VG_(mk_SysRes_riscv64_linux)( gst->guest_x10 ); + canonical->what = SsComplete; + # elif defined(VGP_x86_solaris) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst); @@ -1702,6 +1729,20 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, OFFSET_mips32_r4, sizeof(UWord) ); +# elif defined(VGP_riscv64_linux) + VexGuestRISCV64State* gst = (VexGuestRISCV64State*)gst_vanilla; + vg_assert(canonical->what == SsComplete); + if (sr_isError(canonical->sres)) { + /* This isn't exactly right, in that really a Failure with res + not in the range 1 .. 4095 is unrepresentable in the + Linux-riscv64 scheme. Oh well. */ + gst->guest_x10 = - (Long)sr_Err(canonical->sres); + } else { + gst->guest_x10 = sr_Res(canonical->sres); + } + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_riscv64_x10, sizeof(UWord) ); + # elif defined(VGP_x86_solaris) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; SysRes sres = canonical->sres; @@ -1939,6 +1980,17 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->uu_arg7 = -1; /* impossible value */ layout->uu_arg8 = -1; /* impossible value */ +#elif defined(VGP_riscv64_linux) + layout->o_sysno = OFFSET_riscv64_x17; /* a7 */ + layout->o_arg1 = OFFSET_riscv64_x10; /* a0 */ + layout->o_arg2 = OFFSET_riscv64_x11; /* a1 */ + layout->o_arg3 = OFFSET_riscv64_x12; /* a2 */ + layout->o_arg4 = OFFSET_riscv64_x13; /* a3 */ + layout->o_arg5 = OFFSET_riscv64_x14; /* a4 */ + layout->o_arg6 = OFFSET_riscv64_x15; /* a5 */ + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ + #elif defined(VGP_x86_solaris) layout->o_sysno = OFFSET_x86_EAX; /* Syscall parameters are on the stack. */ @@ -3038,6 +3090,28 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) arch->vex.guest_PC -= 2; } } + +#elif defined(VGP_riscv64_linux) + arch->vex.guest_pc -= 4; // sizeof(ecall) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + ecall == 73 00 00 00 + */ + { + UChar *p = (UChar *)arch->vex.guest_pc; + + if (p[0] != 0x73 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00) + VG_(message)( + Vg_DebugMsg, + "?! restarting over syscall at %#llx %02x %02x %02x %02x\n", + arch->vex.guest_pc, p[0], p[1], p[2], p[3] + ); + + vg_assert(p[0] == 0x73 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00); + } + #elif defined(VGP_x86_solaris) arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall) diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index e897963be..c506070d6 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -1585,6 +1585,81 @@ VG_(trampoline_stuff_end): # undef UD2_1024 # undef UD2_PAGE +/*---------------- riscv64-linux ----------------*/ +#else +#if defined(VGP_riscv64_linux) + +# define UD2_4 .word 0 +# define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4 +# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 +# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 +# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 +# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 + + /* a leading page of unexecutable code */ + UD2_PAGE + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(riscv64_linux_SUBST_FOR_rt_sigreturn) +.type VG_(riscv64_linux_SUBST_FOR_rt_sigreturn), @function +VG_(riscv64_linux_SUBST_FOR_rt_sigreturn): + .cfi_startproc + .cfi_signal_frame + li a7, __NR_rt_sigreturn + ecall + .cfi_endproc +.size VG_(riscv64_linux_SUBST_FOR_rt_sigreturn), \ + .-VG_(riscv64_linux_SUBST_FOR_rt_sigreturn) + +.global VG_(riscv64_linux_REDIR_FOR_strlen) +.type VG_(riscv64_linux_REDIR_FOR_strlen), @function +VG_(riscv64_linux_REDIR_FOR_strlen): + mv a1, a0 /* copy the input string pointer to a1 */ + li a0, 0 /* set the output length to 0 */ + lbu a2, 0(a1) /* load the first character */ + beq a2, zero, 2f /* check if the end of string is reached */ +1: + addi a0, a0, 1 /* increment the output length by 1 */ + add a2, a1, a0 /* calculate address of the next character */ + lbu a2, 0(a2) /* load the next character */ + bne a2, zero, 1b /* check if the end of string is reached */ + ret +2: + ret +.size VG_(riscv64_linux_REDIR_FOR_strlen), .-VG_(riscv64_linux_REDIR_FOR_strlen) + +.global VG_(riscv64_linux_REDIR_FOR_index) +.type VG_(riscv64_linux_REDIR_FOR_index), @function +VG_(riscv64_linux_REDIR_FOR_index): + andi a1, a1, 0xff /* mask the input character value */ + j 2f /* jump into the test loop */ +1: + beq a2, zero, 3f /* check if the end of string is reached */ + addi a0, a0, 1 /* advance to the next character */ +2: + lbu a2, 0(a0) /* load the next character */ + bne a2, a1, 1b /* check if it matches the looked up character */ + ret +3: + li a0, 0 /* set the result to "not found" */ + ret +.size VG_(riscv64_linux_REDIR_FOR_index), .-VG_(riscv64_linux_REDIR_FOR_index) + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + + /* and a trailing page of unexecutable code */ + UD2_PAGE + +# undef UD2_4 +# undef UD2_16 +# undef UD2_64 +# undef UD2_256 +# undef UD2_1024 +# undef UD2_PAGE + /*---------------- x86-solaris ----------------*/ #else #if defined(VGP_x86_solaris) @@ -1785,6 +1860,7 @@ VG_(trampoline_stuff_end): #endif #endif #endif +#endif /* Let the linker know we don't need an executable stack */ MARK_STACK_NO_EXEC diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 5696dc4dc..5da88cac7 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -1750,6 +1750,10 @@ Bool VG_(translate) ( ThreadId tid, vex_archinfo.arm64_requires_fallback_LLSC; # endif +# if defined(VGP_riscv64_linux) + vex_abiinfo.guest__use_fallback_LLSC = True; +# endif + /* Set up closure args. */ closure.tid = tid; closure.nraddr = nraddr; diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h index abc5a066a..353e69ce8 100644 --- a/coregrind/pub_core_basics.h +++ b/coregrind/pub_core_basics.h @@ -55,8 +55,10 @@ typedef struct { - ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc */ - ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp */ + ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc, + riscv64: pc */ + ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp, + riscv64: x2 */ union { struct { UInt r_ebp; @@ -102,6 +104,10 @@ typedef ULong r31; /* Return address of the last subroutine call */ ULong r28; } MIPS64; + struct { + ULong r_fp; /* x8 */ + ULong r_ra; /* x1 */ + } RISCV64; } misc; } UnwindStartRegs; diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index 64fcd3428..08579e6f0 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -134,6 +134,10 @@ typedef Addr f4; Addr f5; Addr f6; Addr f7; } D3UnwindRegs; #elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) +typedef + struct { Addr pc; Addr sp; Addr fp; Addr ra; } + D3UnwindRegs; +#elif defined(VGA_riscv64) typedef struct { Addr pc; Addr sp; Addr fp; Addr ra; } D3UnwindRegs; diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h index a1afbe61c..555506a03 100644 --- a/coregrind/pub_core_machine.h +++ b/coregrind/pub_core_machine.h @@ -126,6 +126,11 @@ # define VG_ELF_MACHINE EM_NANOMIPS # define VG_ELF_CLASS ELFCLASS32 # undef VG_PLAT_USES_PPCTOC +#elif defined(VGP_riscv64_linux) +# define VG_ELF_DATA2XXX ELFDATA2LSB +# define VG_ELF_MACHINE EM_RISCV +# define VG_ELF_CLASS ELFCLASS64 +# undef VG_PLAT_USES_PPCTOC #else # error Unknown platform #endif @@ -163,6 +168,10 @@ # define VG_INSTR_PTR guest_PC # define VG_STACK_PTR guest_r29 # define VG_FRAME_PTR guest_r30 +#elif defined(VGA_riscv64) +# define VG_INSTR_PTR guest_pc +# define VG_STACK_PTR guest_x2 +# define VG_FRAME_PTR guest_x8 #else # error Unknown arch #endif diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h index 6f0cd293b..df9648cea 100644 --- a/coregrind/pub_core_mallocfree.h +++ b/coregrind/pub_core_mallocfree.h @@ -84,6 +84,7 @@ typedef Int ArenaId; defined(VGP_x86_darwin) || \ defined(VGP_amd64_darwin) || \ defined(VGP_arm64_linux) || \ + defined(VGP_riscv64_linux) || \ defined(VGP_amd64_solaris) # define VG_MIN_MALLOC_SZB 16 #else diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h index 5c42821c8..e1e066fcc 100644 --- a/coregrind/pub_core_syscall.h +++ b/coregrind/pub_core_syscall.h @@ -106,6 +106,7 @@ extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1, extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1, ULong a3 ); extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0); +extern SysRes VG_(mk_SysRes_riscv64_linux) ( Long a0 ); extern SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 ); extern SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 ); extern SysRes VG_(mk_SysRes_Error) ( UWord val ); diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index f92b6ab45..7e9e2d76b 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -176,6 +176,12 @@ extern Char* VG_(nanomips_linux_REDIR_FOR_index)( const Char*, Int ); extern UInt VG_(nanomips_linux_REDIR_FOR_strlen)( void* ); #endif +#if defined(VGP_riscv64_linux) +extern Addr VG_(riscv64_linux_SUBST_FOR_rt_sigreturn); +extern HChar* VG_(riscv64_linux_REDIR_FOR_index)( const HChar*, Int ); +extern SizeT VG_(riscv64_linux_REDIR_FOR_strlen)( const HChar* ); +#endif + #if defined(VGP_x86_solaris) extern SizeT VG_(x86_solaris_REDIR_FOR_strcmp)(const HChar *, const HChar *); extern SizeT VG_(x86_solaris_REDIR_FOR_strlen)(const HChar *); diff --git a/coregrind/pub_core_transtab.h b/coregrind/pub_core_transtab.h index 6cc11f658..cc70a2944 100644 --- a/coregrind/pub_core_transtab.h +++ b/coregrind/pub_core_transtab.h @@ -72,7 +72,8 @@ static inline UWord VG_TT_FAST_HASH ( Addr guest ) { return merged & VG_TT_FAST_MASK; } -#elif defined(VGA_s390x) || defined(VGA_arm) || defined(VGA_nanomips) +#elif defined(VGA_s390x) || defined(VGA_arm) || defined(VGA_nanomips) \ + || defined(VGA_riscv64) static inline UWord VG_TT_FAST_HASH ( Addr guest ) { // Instructions are 2-byte aligned. UWord merged = ((UWord)guest) >> 1; diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h index 8b585f17d..c14e24ebf 100644 --- a/coregrind/pub_core_transtab_asm.h +++ b/coregrind/pub_core_transtab_asm.h @@ -67,12 +67,9 @@ sets to ever be used. So instead the function is (address ^ (address >>u VG_TT_FAST_BITS))[VG_TT_FAST_BITS-1+2 : 0+2]'. - On arm32, the minimum instruction size is 2, so we discard only the least - significant bit of the address, hence: - (address ^ (address >>u VG_TT_FAST_BITS))[VG_TT_FAST_BITS-1+1 : 0+1]'. - - On s390x the rightmost bit of an instruction address is zero, so the arm32 - scheme is used. */ + On arm32/s390x/riscv64, the minimum instruction size is 2, so we discard only + the least significant bit of the address, hence: + (address ^ (address >>u VG_TT_FAST_BITS))[VG_TT_FAST_BITS-1+1 : 0+1]'. */ #define VG_TT_FAST_BITS 13 #define VG_TT_FAST_SETS (1 << VG_TT_FAST_BITS) @@ -83,7 +80,7 @@ #if defined(VGA_amd64) || defined(VGA_arm64) \ || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ || (defined(VGA_mips64) && defined(VGABI_64)) \ - || defined(VGA_s390x) + || defined(VGA_s390x) || defined(VGA_riscv64) // And all other 64-bit hosts # define VG_FAST_CACHE_SET_BITS 6 // These FCS_{g,h}{0,1,2,3} are the values of diff --git a/coregrind/vgdb-invoker-ptrace.c b/coregrind/vgdb-invoker-ptrace.c index 78a6a168c..3a6a455d0 100644 --- a/coregrind/vgdb-invoker-ptrace.c +++ b/coregrind/vgdb-invoker-ptrace.c @@ -40,6 +40,17 @@ #include #include +#if defined(VGA_riscv64) +/* Glibc on riscv64 does not provide a definition of user or user_regs_struct + in sys/user.h. Instead the definition of user_regs_struct is provided by the + kernel in asm/ptrace.h. Pull it and then define the expected user + structure. */ +#include +struct user { + struct user_regs_struct regs; +}; +#endif + #ifdef PTRACE_GETREGSET // TBD: better have a configure test instead ? #define HAVE_PTRACE_GETREGSET @@ -49,10 +60,10 @@ // So, better do not use PTRACE_GET/SETREGSET // Rather we use PTRACE_GETREGS or PTRACE_PEEKUSER. -// The only platform on which we must use PTRACE_GETREGSET is arm64. +// The only platform on which we must use PTRACE_GETREGSET is here. // The resulting vgdb cannot work in a bi-arch setup. // -1 means we will check that PTRACE_GETREGSET works. -# if defined(VGA_arm64) +# if defined(VGA_arm64) || defined(VGA_riscv64) #define USE_PTRACE_GETREGSET # endif #endif @@ -874,6 +885,8 @@ Bool invoker_invoke_gdbserver (pid_t pid) sp = p[29]; #elif defined(VGA_mips64) sp = user_mod.regs[29]; +#elif defined(VGA_riscv64) + sp = user_mod.regs.sp; #else I_die_here : (sp) architecture missing in vgdb-invoker-ptrace.c #endif @@ -961,6 +974,10 @@ Bool invoker_invoke_gdbserver (pid_t pid) #elif defined(VGA_mips64) assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe + +#elif defined(VGA_riscv64) + assert(0); + #else I_die_here : architecture missing in vgdb-invoker-ptrace.c #endif @@ -1068,6 +1085,10 @@ Bool invoker_invoke_gdbserver (pid_t pid) user_mod.regs[31] = bad_return; user_mod.regs[34] = shared64->invoke_gdbserver; user_mod.regs[25] = shared64->invoke_gdbserver; +#elif defined(VGA_riscv64) + user_mod.regs.a0 = check; + user_mod.regs.ra = bad_return; + user_mod.regs.pc = shared64->invoke_gdbserver; #else I_die_here: architecture missing in vgdb-invoker-ptrace.c #endif diff --git a/docs/Makefile.am b/docs/Makefile.am index 6859ee8a3..12d13db1d 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -63,6 +63,7 @@ EXTRA_DIST = \ internals/porting-to-ARM.txt \ internals/qemu-aarch64-linux-HOWTO.txt \ internals/qemu-mips64-linux-HOWTO.txt \ + internals/qemu-riscv64-linux-HOWTO.txt \ internals/register-uses.txt \ internals/s390-opcodes.csv \ internals/release-HOWTO.txt \ diff --git a/docs/xml/dist-docs.xml b/docs/xml/dist-docs.xml index 439cdcc5f..31b170885 100644 --- a/docs/xml/dist-docs.xml +++ b/docs/xml/dist-docs.xml @@ -122,6 +122,16 @@ + + README.riscv64 + + + + + README.solaris diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h index 3b71d749a..fa1506ed4 100644 --- a/drd/drd_bitmap.h +++ b/drd/drd_bitmap.h @@ -140,7 +140,7 @@ Addr make_address(const UWord a1, const UWord a0) #define BITS_PER_BITS_PER_UWORD 5 #elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ || defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \ - || defined(VGA_arm64) + || defined(VGA_arm64) || defined(VGA_riscv64) #define BITS_PER_BITS_PER_UWORD 6 #else #error Unknown platform. diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c index 80d326a0e..a6fb874bf 100644 --- a/drd/drd_load_store.c +++ b/drd/drd_load_store.c @@ -53,6 +53,8 @@ #define STACK_POINTER_OFFSET OFFSET_mips32_r29 #elif defined(VGA_mips64) #define STACK_POINTER_OFFSET OFFSET_mips64_r29 +#elif defined(VGA_riscv64) +#define STACK_POINTER_OFFSET OFFSET_riscv64_x2 #else #error Unknown architecture. #endif diff --git a/include/Makefile.am b/include/Makefile.am index 5d5162a46..3995d6de5 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -64,6 +64,7 @@ nobase_pkginclude_HEADERS = \ vki/vki-posixtypes-mips32-linux.h \ vki/vki-posixtypes-mips64-linux.h \ vki/vki-posixtypes-nanomips-linux.h \ + vki/vki-posixtypes-riscv64-linux.h \ vki/vki-amd64-linux.h \ vki/vki-arm64-linux.h \ vki/vki-ppc32-linux.h \ @@ -77,6 +78,7 @@ nobase_pkginclude_HEADERS = \ vki/vki-mips32-linux.h \ vki/vki-mips64-linux.h \ vki/vki-nanomips-linux.h \ + vki/vki-riscv64-linux.h \ vki/vki-scnums-amd64-linux.h \ vki/vki-scnums-arm64-linux.h \ vki/vki-scnums-ppc32-linux.h \ @@ -88,6 +90,7 @@ nobase_pkginclude_HEADERS = \ vki/vki-scnums-mips32-linux.h \ vki/vki-scnums-mips64-linux.h \ vki/vki-scnums-nanomips-linux.h \ + vki/vki-scnums-riscv64-linux.h \ vki/vki-scnums-darwin.h \ vki/vki-scnums-solaris.h \ vki/vki-scnums-shared-linux.h \ diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h index bf5a5ba7f..155454bff 100644 --- a/include/pub_tool_basics.h +++ b/include/pub_tool_basics.h @@ -437,7 +437,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) { #if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \ || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \ - && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le) + && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le) \ + || defined(VGA_riscv64) # define VG_LITTLEENDIAN 1 #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_s390x) \ || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \ @@ -485,7 +486,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) { || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ || defined(VGA_arm) || defined(VGA_s390x) \ || defined(VGA_mips32) || defined(VGA_mips64) \ - || defined(VGA_arm64) || defined(VGA_nanomips) + || defined(VGA_arm64) || defined(VGA_nanomips) \ + || defined(VGA_riscv64) # define VG_REGPARM(n) /* */ #else # error Unknown arch diff --git a/include/pub_tool_guest.h b/include/pub_tool_guest.h index 08a72efac..9e5c0c24a 100644 --- a/include/pub_tool_guest.h +++ b/include/pub_tool_guest.h @@ -62,6 +62,9 @@ #elif defined(VGA_mips64) # include "libvex_guest_mips64.h" typedef VexGuestMIPS64State VexGuestArchState; +#elif defined(VGA_riscv64) +# include "libvex_guest_riscv64.h" + typedef VexGuestRISCV64State VexGuestArchState; #else # error Unknown arch #endif diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index f46207257..933dc8e12 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -108,6 +108,12 @@ # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0 +#elif defined(VGP_riscv64_linux) +# define VG_MIN_INSTR_SZB 2 +# define VG_MAX_INSTR_SZB 4 +# define VG_CLREQ_SZB 20 +# define VG_STACK_REDZONE_SZB 0 + #else # error Unknown platform #endif diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h index f88d3b571..788db2129 100644 --- a/include/pub_tool_redir.h +++ b/include/pub_tool_redir.h @@ -321,6 +321,8 @@ #define VG_U_LD_LINUX_MIPSN8_S0_1 "ld-linux-mipsn8.so.1" +#define VG_U_LD_LINUX_RISCV64_SO_1 "ld-linux-riscv64-lp64d.so.1" + #endif /* --- Sonames for FreeBSD ELF linkers, plus unencoded versions. --- */ diff --git a/include/pub_tool_vkiscnums_asm.h b/include/pub_tool_vkiscnums_asm.h index f97a3af3a..e7aa87976 100644 --- a/include/pub_tool_vkiscnums_asm.h +++ b/include/pub_tool_vkiscnums_asm.h @@ -72,6 +72,10 @@ #elif defined(VGP_mips64_linux) # include "vki/vki-scnums-mips64-linux.h" +#elif defined(VGP_riscv64_linux) +# include "vki/vki-scnums-shared-linux.h" +# include "vki/vki-scnums-riscv64-linux.h" + #elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) || defined(VGP_arm64_freebsd) # include "vki/vki-scnums-freebsd.h" diff --git a/include/valgrind.h.in b/include/valgrind.h.in index bc18f40f7..f1710924a 100644 --- a/include/valgrind.h.in +++ b/include/valgrind.h.in @@ -126,6 +126,7 @@ #undef PLAT_mips32_linux #undef PLAT_mips64_linux #undef PLAT_nanomips_linux +#undef PLAT_riscv64_linux #undef PLAT_x86_solaris #undef PLAT_amd64_solaris @@ -172,6 +173,8 @@ # define PLAT_mips32_linux 1 #elif defined(__linux__) && defined(__nanomips__) # define PLAT_nanomips_linux 1 +#elif defined(__linux__) && defined(__riscv) && (__riscv_xlen == 64) +# define PLAT_riscv64_linux 1 #elif defined(__sun) && defined(__i386__) # define PLAT_x86_solaris 1 #elif defined(__sun) && defined(__x86_64__) @@ -1129,6 +1132,87 @@ typedef } while (0) #endif + +/* ----------------------- riscv64-linux ------------------------ */ + +#if defined(PLAT_riscv64_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + ".option push\n\t" \ + ".option norvc\n\t" \ + "srli zero, zero, 3\n\t" \ + "srli zero, zero, 13\n\t" \ + "srli zero, zero, 51\n\t" \ + "srli zero, zero, 61\n\t" + +#define __SPECIAL_INSTRUCTION_POSTAMBLE \ + ".option pop\n\t" \ + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile("mv a3, %1\n\t" /*default*/ \ + "mv a4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* a3 = client_request ( a4 ) */ \ + "or a0, a0, a0\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + "mv %0, a3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" ((unsigned long int)(_zzq_default)), \ + "r" (&_zzq_args[0]) \ + : "memory", "a3", "a4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* a3 = guest_NRADDR */ \ + "or a1, a1, a1\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + "mv %0, a3" \ + : "=r" (__addr) \ + : \ + : "memory", "a3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir t0 */ \ + "or a2, a2, a2\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or a3, a3, a3\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + : : : "memory" \ + ); \ + } while (0) + +#endif /* PLAT_riscv64_linux */ + /* Insert assembly code for other platforms here... */ #endif /* NVALGRIND */ @@ -6606,6 +6690,456 @@ typedef #endif /* PLAT_mips64_linux */ +/* ----------------------- riscv64-linux ----------------------- */ + +#if defined(PLAT_riscv64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "ra", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", \ + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", \ + "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", \ + "ft8", "ft9", "ft10", "ft11", \ + "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7" + +/* s11 is callee-saved, so we can use it to save and restore sp around + the hidden call. */ +#define VALGRIND_ALIGN_STACK \ + "mv s11, sp\n\t" \ + "andi sp, sp, 0xfffffffffffffff0\n\t" +#define VALGRIND_RESTORE_STACK \ + "mv sp, s11\n\t" + +/* These CALL_FN_ macros assume that on riscv64-linux, + sizeof(unsigned long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -16 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -16 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -32 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 88(%1) \n\t" \ + "sd t0, 16(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11, \ + arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -32 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 88(%1) \n\t" \ + "sd t0, 16(sp) \n\t" \ + "ld t0, 96(%1) \n\t" \ + "sd t0, 24(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_riscv64_linux */ + /* ------------------------------------------------------------------ */ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ /* */ @@ -7162,6 +7696,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) #undef PLAT_mips32_linux #undef PLAT_mips64_linux #undef PLAT_nanomips_linux +#undef PLAT_riscv64_linux #undef PLAT_x86_solaris #undef PLAT_amd64_solaris diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index d4e1908e1..0df1b4c4b 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -97,6 +97,8 @@ # include "vki-posixtypes-mips64-linux.h" #elif defined(VGA_nanomips) # include "vki-posixtypes-nanomips-linux.h" +#elif defined(VGA_riscv64) +# include "vki-posixtypes-riscv64-linux.h" #else # error Unknown platform #endif @@ -225,6 +227,8 @@ typedef unsigned int vki_uint; # include "vki-mips64-linux.h" #elif defined(VGA_nanomips) # include "vki-nanomips-linux.h" +#elif defined(VGA_riscv64) +# include "vki-riscv64-linux.h" #else # error Unknown platform #endif diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c index 176c8e5cb..34df0011a 100644 --- a/memcheck/mc_machine.c +++ b/memcheck/mc_machine.c @@ -1396,6 +1396,104 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB ) # undef GOF # undef SZB + /* ------------------- riscv64 ------------------- */ + +# elif defined(VGA_riscv64) + +# define GOF(_fieldname) \ + (offsetof(VexGuestRISCV64State,guest_##_fieldname)) +# define SZB(_fieldname) \ + (sizeof(((VexGuestRISCV64State*)0)->guest_##_fieldname)) + + Int o = offset; + Int sz = szB; + Bool is48 = sz == 8 || sz == 4; + + tl_assert(sz > 0); + tl_assert(host_is_little_endian()); + + if (o == GOF(x0) && is48) return -1; + if (o == GOF(x1) && is48) return o; + if (o == GOF(x2) && is48) return o; + if (o == GOF(x3) && is48) return o; + if (o == GOF(x4) && is48) return o; + if (o == GOF(x5) && is48) return o; + if (o == GOF(x6) && is48) return o; + if (o == GOF(x7) && is48) return o; + if (o == GOF(x8) && is48) return o; + if (o == GOF(x9) && is48) return o; + if (o == GOF(x10) && is48) return o; + if (o == GOF(x11) && is48) return o; + if (o == GOF(x12) && is48) return o; + if (o == GOF(x13) && is48) return o; + if (o == GOF(x14) && is48) return o; + if (o == GOF(x15) && is48) return o; + if (o == GOF(x16) && is48) return o; + if (o == GOF(x17) && is48) return o; + if (o == GOF(x18) && is48) return o; + if (o == GOF(x19) && is48) return o; + if (o == GOF(x20) && is48) return o; + if (o == GOF(x21) && is48) return o; + if (o == GOF(x22) && is48) return o; + if (o == GOF(x23) && is48) return o; + if (o == GOF(x24) && is48) return o; + if (o == GOF(x25) && is48) return o; + if (o == GOF(x26) && is48) return o; + if (o == GOF(x27) && is48) return o; + if (o == GOF(x28) && is48) return o; + if (o == GOF(x29) && is48) return o; + if (o == GOF(x30) && is48) return o; + if (o == GOF(x31) && is48) return o; + if (o == GOF(pc) && sz == 8) return -1; + + if (o >= GOF(f0) && o+sz <= GOF(f0) +SZB(f0)) return GOF(f0); + if (o >= GOF(f1) && o+sz <= GOF(f1) +SZB(f1)) return GOF(f1); + if (o >= GOF(f2) && o+sz <= GOF(f2) +SZB(f2)) return GOF(f2); + if (o >= GOF(f3) && o+sz <= GOF(f3) +SZB(f3)) return GOF(f3); + if (o >= GOF(f4) && o+sz <= GOF(f4) +SZB(f4)) return GOF(f4); + if (o >= GOF(f5) && o+sz <= GOF(f5) +SZB(f5)) return GOF(f5); + if (o >= GOF(f6) && o+sz <= GOF(f6) +SZB(f6)) return GOF(f6); + if (o >= GOF(f7) && o+sz <= GOF(f7) +SZB(f7)) return GOF(f7); + if (o >= GOF(f8) && o+sz <= GOF(f8) +SZB(f8)) return GOF(f8); + if (o >= GOF(f9) && o+sz <= GOF(f9) +SZB(f9)) return GOF(f9); + if (o >= GOF(f10) && o+sz <= GOF(f10)+SZB(f10)) return GOF(f10); + if (o >= GOF(f11) && o+sz <= GOF(f11)+SZB(f11)) return GOF(f11); + if (o >= GOF(f12) && o+sz <= GOF(f12)+SZB(f12)) return GOF(f12); + if (o >= GOF(f13) && o+sz <= GOF(f13)+SZB(f13)) return GOF(f13); + if (o >= GOF(f14) && o+sz <= GOF(f14)+SZB(f14)) return GOF(f14); + if (o >= GOF(f15) && o+sz <= GOF(f15)+SZB(f15)) return GOF(f15); + if (o >= GOF(f16) && o+sz <= GOF(f16)+SZB(f16)) return GOF(f16); + if (o >= GOF(f17) && o+sz <= GOF(f17)+SZB(f17)) return GOF(f17); + if (o >= GOF(f18) && o+sz <= GOF(f18)+SZB(f18)) return GOF(f18); + if (o >= GOF(f19) && o+sz <= GOF(f19)+SZB(f19)) return GOF(f19); + if (o >= GOF(f20) && o+sz <= GOF(f20)+SZB(f20)) return GOF(f20); + if (o >= GOF(f21) && o+sz <= GOF(f21)+SZB(f21)) return GOF(f21); + if (o >= GOF(f22) && o+sz <= GOF(f22)+SZB(f22)) return GOF(f22); + if (o >= GOF(f23) && o+sz <= GOF(f23)+SZB(f23)) return GOF(f23); + if (o >= GOF(f24) && o+sz <= GOF(f24)+SZB(f24)) return GOF(f24); + if (o >= GOF(f25) && o+sz <= GOF(f25)+SZB(f25)) return GOF(f25); + if (o >= GOF(f26) && o+sz <= GOF(f26)+SZB(f26)) return GOF(f26); + if (o >= GOF(f27) && o+sz <= GOF(f27)+SZB(f27)) return GOF(f27); + if (o >= GOF(f28) && o+sz <= GOF(f28)+SZB(f28)) return GOF(f28); + if (o >= GOF(f29) && o+sz <= GOF(f29)+SZB(f29)) return GOF(f29); + if (o >= GOF(f30) && o+sz <= GOF(f30)+SZB(f30)) return GOF(f30); + if (o >= GOF(f31) && o+sz <= GOF(f31)+SZB(f31)) return GOF(f31); + if (o == GOF(fcsr) && sz == 4) return o; + + if (o == GOF(EMNOTE) && sz == 4) return -1; + if (o == GOF(CMSTART) && sz == 8) return -1; + if (o == GOF(CMLEN) && sz == 8) return -1; + if (o == GOF(NRADDR) && sz == 4) return -1; + + if (o == GOF(LLSC_SIZE) && sz == 8) return -1; + if (o == GOF(LLSC_ADDR) && sz == 8) return o; + if (o == GOF(LLSC_DATA) && sz == 8) return o; + + VG_(printf)("MC_(get_otrack_shadow_offset)(riscv64)(off=%d,sz=%d)\n", + offset,szB); + tl_assert(0); +# undef GOF + # else # error "FIXME: not implemented for this architecture" # endif @@ -1517,6 +1615,13 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr ) VG_(printf)("\n"); tl_assert(0); + /* ------------------- riscv64 ------------------- */ +# elif defined(VGA_riscv64) + VG_(printf)("get_reg_array_equiv_int_type(riscv64): unhandled: "); + ppIRRegArray(arr); + VG_(printf)("\n"); + tl_assert(0); + # else # error "FIXME: not implemented for this architecture" # endif