]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
riscv64: Add initial support: Valgrind modifications
authorPetr Pavlu <petr.pavlu@dagobah.cz>
Tue, 11 Apr 2023 19:30:42 +0000 (19:30 +0000)
committerMark Wielaard <mark@klomp.org>
Tue, 25 Feb 2025 16:04:36 +0000 (17:04 +0100)
The following people contributed to the initial RISC-V support:
Petr Pavlu <petr.pavlu@dagobah.cz>
Xeonacid <h.dwwwwww@gmail.com>
laokz <laokz@foxmail.com>
Chelsea E. Manning <me@xychelsea.is>
zhaomingxin <zhaomingxin.zmx@alibaba-inc.com>
Jojo R <rjiejie@linux.alibaba.com>

https://bugs.kde.org/show_bug.cgi?id=493507

63 files changed:
.gitignore
Makefile.all.am
Makefile.am
Makefile.tool.am
Makefile.vex.am
cachegrind/cg_arch.c
cachegrind/cg_branchpred.c
configure.ac
coregrind/Makefile.am
coregrind/launcher-linux.c
coregrind/m_aspacemgr/aspacemgr-common.c
coregrind/m_cache.c
coregrind/m_coredump/coredump-elf.c
coregrind/m_debuginfo/d3basics.c
coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_storage.h
coregrind/m_debuginfo/readdwarf.c
coregrind/m_debuginfo/readelf.c
coregrind/m_debuginfo/storage.c
coregrind/m_debuglog.c
coregrind/m_gdbserver/target.c
coregrind/m_gdbserver/valgrind_low.h
coregrind/m_initimg/initimg-linux.c
coregrind/m_libcassert.c
coregrind/m_libcfile.c
coregrind/m_libcproc.c
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_options.c
coregrind/m_redir.c
coregrind/m_scheduler/scheduler.c
coregrind/m_signals.c
coregrind/m_stacktrace.c
coregrind/m_syscall.c
coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/priv_types_n_macros.h
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-main.c
coregrind/m_trampoline.S
coregrind/m_translate.c
coregrind/pub_core_basics.h
coregrind/pub_core_debuginfo.h
coregrind/pub_core_machine.h
coregrind/pub_core_mallocfree.h
coregrind/pub_core_syscall.h
coregrind/pub_core_trampoline.h
coregrind/pub_core_transtab.h
coregrind/pub_core_transtab_asm.h
coregrind/vgdb-invoker-ptrace.c
docs/Makefile.am
docs/xml/dist-docs.xml
drd/drd_bitmap.h
drd/drd_load_store.c
include/Makefile.am
include/pub_tool_basics.h
include/pub_tool_guest.h
include/pub_tool_machine.h
include/pub_tool_redir.h
include/pub_tool_vkiscnums_asm.h
include/valgrind.h.in
include/vki/vki-linux.h
memcheck/mc_machine.c

index c5a2b0592c259aa689a12b656c9172a4a5c0627f..de2306df78755adab7ed05760d96e6eab60d5b0a 100644 (file)
@@ -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
 /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
 /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
index e221198d6ca2f8801e4b61f798371236d7c9cc56..d4f6b3fb798581ac80d107f52a950d1d55a86edc 100755 (executable)
@@ -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@
 
index d745e26bf4795af83a8a3038c961c5dc8de0184b..db8cfa382c122e5674d5783b8c9d9519b83681dd 100644 (file)
@@ -118,6 +118,7 @@ EXTRA_DIST = \
        README.android_emulator \
        README.mips \
        README.aarch64 \
+       README.riscv64 \
        README.solaris \
        README.freebsd \
        NEWS.old \
index c779596e714df802187cd35bd9494c32515b84c2..7f18d25476eb1d233f04277e2a6c300dc36e5ce3 100644 (file)
@@ -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) \
index c1244a69d25c7a14d2fff05603e2a32cfa68748e..f75e9b4c691c21136dd8a4a54de88f02fbb19915 100644 (file)
@@ -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
 
index 68314c9dbebd9274e08230dc119d752433dcf6b8..be2973405aaa8418dcaa8a01d4b96772891abe4e 100644 (file)
@@ -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"
index 927b7bf21cb307d3cc5e89c51a03219ac2fac9d6..f7a261c6fe42fa5f87d24652a86bfc1f670321d4 100644 (file)
@@ -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"
index 9dec9f3b00f64c09f7a50c4f356a8047f8e9b8b7..e6ae0501bd5e4fb2c931244d96839b25cc538697 100755 (executable)
@@ -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_<platform>.  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
index 5491fc672609feb1ff289a06a2bdb52f307ff7f8..700751dea455b3691ca3b1f51a728f82ac0c9890 100644 (file)
@@ -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)
index 715fdab818800e54cb6b193a8bcd2cc65cdcd60b..20e624003affb95d72943ed098026efaa968754a 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+/* 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
 #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")) ||
index 68bc5b40c9f0bc4b66928977c625ab6319903678..14864d96c3635ff63b96253dd2e90cb9621c669c 100644 (file)
@@ -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)
index d12941cd68477b9443174616068ea3da529be360..4abd26f0b2ca06d2517192fa86271b80f263f78d 100644 (file)
@@ -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)
 {
index a4632d9e285919e7e86972387e2e57fc7a81400d..b57d26275b1ab1b090162b5089aadb6a6620585f 100644 (file)
@@ -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)
index 564b832e63a036a2bf140f546ca68c4392afd45d..80dec21a6598bac30065378986a0e2bcb4cc2aa4 100644 (file)
@@ -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
index 11ab47354211c931a12bc9c4afb5b43ba567fedd..97d0f35c059bd118d5869bd31583ccf3bd3b7995 100644 (file)
@@ -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
index 441b379d2ea0926f338371b250f5f6e9c9a0a300..d8cba81c48ad94b44c8662fcda8fac92ee50f0c6 100644 (file)
@@ -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 */
index 0686e8d078a7123a0de8dd6eb3b89605976439fd..b08720182e59b7ccd52a09620e9c3337b4e7f113 100644 (file)
@@ -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
index 77ed4798b0276c5fce331fa6595ed3da05fd3637..1dadbc72c5a53c6d140ce0f6f237adbfc54a4517 100644 (file)
@@ -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)
index ef6a400510b6c75d884ab8e7d4f7f73c83285bc9..12ad681304c00b28eafee788dbe1e65d091f5ea3 100644 (file)
@@ -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
index cad95bcbe203c2f2bd70df86bc62784ef592980c..225e5a0854b46939535a45143eb5eecb62116951 100644 (file)
@@ -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 )
 {
index f9f32f4aa5b7f3d17a9a914975b4204c08b0b322..4238c608cba7884661ce69640109dea565af41ac 100644 (file)
@@ -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
index d8ae3c908616b6f25b7828998e99d172e4c3eed3..ef4e1908974695473f211a668893212e03c5060f 100644 (file)
@@ -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
index feec1e5f118def67892bf93dcf08319c04b9b894..483b7a3ddd11e2ddc92c5180df82547ea24a1e7c 100644 (file)
@@ -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
index 257c26bc631342d295efba2180a4819ed9b2498c..c6380d4e0bab1155cd54bcfd0905f131b958f38d 100644 (file)
         (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
index fb93b4867c1f5dc9e7e4d8a2e683bb93c659b89a..e132e765973f53eb0a2572f01b60800be4fae1d5 100644 (file)
@@ -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, 
index 280ab1cff29e728e0e217b679aca4fb1e176749d..c70f229e5d0f82110a777cc6cbe7db863667eb70 100644 (file)
@@ -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
 }
 
index 234efb312d2c4a7c863ff8ad6b059354ade86a7a..dec4f2373e35fd96ae7aa141b6c51e81b2def556 100644 (file)
@@ -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
index 3f07e57a91703bbad756bdbd703e8c4db00c2056..877e6b0b68776e0643b287a4174955e2fc5a2f0b 100644 (file)
@@ -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
index ecbe9fc3adc86d4171debb55198c72dcafb5dd8f..16452f252565f5d0f359b5ccc36f8cd861848268 100644 (file)
@@ -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"
index 6c360d59ce698465d031716033852c24d0fcee7e..958f3e7c46228e483535ea4671aa0db88a8de9be 100644 (file)
@@ -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. */
index cc8d070b793092b6799cdbb9c8c65c410e29e49a..51ba34361645365aa483fb609b30bff884869b77 100644 (file)
@@ -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
index 66fbbfe721bb782fc2a3fc9c46efeed0af0c38d2..53614d303c3417f71daa804fe7cba4506c1b90f9 100644 (file)
@@ -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
 
index 630b5b87524c236106b805be643d1a65a5f70a11..cbeaab9db1ded09c7330e054d6f15013b99768d5 100644 (file)
@@ -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     ---*/
index 6ab20694d696ac506400a33035e1259002ba6099..8ff9c90bdc5c9682a85af30c9c64d04a81f4ffb7 100644 (file)
@@ -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, &reg_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;
index 1bdd9a94ec19598c253b57e068ab0b237189a969..6e6356608f9cfa0595bf31aaa9de2f5bc3b82dc6 100644 (file)
@@ -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
 
 /*--------------------------------------------------------------------*/
index 6be22f8e762ab2e98bc7df1a44e085571884ad2e..cc00592ef29472b861c1c49b1cc56da2f6988abb 100644 (file)
@@ -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;
index c3f916a1ed790e1808b77cdf99c85500bc8d7cda..175c94b4d7a07337e56e1ff30478b0ee80cad78f 100644 (file)
@@ -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)
 {
index 83af91344ee5812d0e3f3515e495bd0299526e35..d2259bdd8cfa75d086c2912afe426dcae8a18ffe 100644 (file)
@@ -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;
index be4ac0f08143aeb0d257e40a434f73684239061d..1a7f038d483dff0641a41bf3a60c8cfbe32c9e1d 100644 (file)
@@ -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)
 
index e897963be21a46ae2c8b674cd9d67ed4bb4b82c4..c506070d6ac7f22216ac22be8937654e94d04780 100644 (file)
@@ -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
index 5696dc4dca643ccd1172a88f8549d7b758a1a275..5da88cac7c09109c768056b8cda0ace961908402 100644 (file)
@@ -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;
index abc5a066a3e3de68b80673e2f9e3d4d0fe8127a5..353e69ce8461033c2253bca5b46dd6bf647a6aa3 100644 (file)
 
 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;
index 64fcd3428a8d1b8425186b504d8c36a4aeed425e..08579e6f066c38ff4e76967136530e1d1a2f7793 100644 (file)
@@ -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;
index a1afbe61c086ba3c7e389ff4e05a518248510f36..555506a03b9319cea932c0dd0427cff53edce9bc 100644 (file)
 #  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
 #  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
index 6f0cd293bf0a881672f08cbc120e9460465d3435..df9648cea47b1ee429be15498c72f07be1c49618 100644 (file)
@@ -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
index 5c42821c8ac0d477ff3c541d7453ac17c9ded917..e1e066fccfe36cfbc0f4a1f4acfff0a28e38b6d4 100644 (file)
@@ -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 );
index f92b6ab450b2802433ba5a8dd2e11aace23fed3e..7e9e2d76be8daa59f9fc04cbaa8f5e88a68c85a4 100644 (file)
@@ -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 *);
index 6cc11f65806cfeadce2654437ae7b08ce6152fcd..cc70a2944901f820ab51864e52dc7330cf2feb22 100644 (file)
@@ -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;
index 8b585f17d2ec47e7b28dd1101502b0e260ac134e..c14e24ebf030e87b5d7a81fff453b6e0033e30e0 100644 (file)
    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
index 78a6a168c187a1b55b5dc64ddf484fc8904907f6..3a6a455d035963e48f16499fefc77814f35f6efb 100644 (file)
 #include <sys/user.h>
 #include <sys/wait.h>
 
+#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 <asm/ptrace.h>
+struct user {
+   struct user_regs_struct regs;
+};
+#endif
+
 #ifdef PTRACE_GETREGSET
 // TBD: better have a configure test instead ?
 #define HAVE_PTRACE_GETREGSET
 // 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
index 6859ee8a34d1df2d9c822a7bc065f6f89b85e212..12d13db1da358dbcdce9ed7e70798876cdd3a395 100644 (file)
@@ -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 \
index 439cdcc5f00f1762f78bf5e31ecb3c006630b57c..31b1708852602146c4820d6227715414d9b4f5b6 100644 (file)
     </literallayout>
     </chapter>
 
+  <chapter id="dist.readme-riscv64" 
+             xreflabel="Readme RISCV64">
+    <title>README.riscv64</title>
+    <literallayout>
+      <xi:include href="../../README.riscv64" 
+          parse="text" 
+          xmlns:xi="http://www.w3.org/2001/XInclude" />
+    </literallayout>
+    </chapter>
+
   <chapter id="dist.readme-solaris"
              xreflabel="Readme Solaris">
     <title>README.solaris</title>
index 3b71d749a9fbca40246611653a9744c45d8cc304..fa1506ed4fa92476dd92db4d850724b66be4c81a 100644 (file)
@@ -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.
index 80d326a0e2a91354aaf61fcb3c70716a1f3f5c5c..a6fb874bfc4981d2902f7de67d0994fef7e4f47f 100644 (file)
@@ -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
index 5d5162a46eb6e7d8142468a1f44ee2c30f2cf34d..3995d6de57142d527f070752d4c2461271eee9e1 100644 (file)
@@ -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   \
index bf5a5ba7fa770a7aa0a7e5b441d811760df3263f..155454bff4a5370f1ddac62e17a7b93c5b0f17f0 100644 (file)
@@ -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
index 08a72efac69b7c63466fc313a3f13d6be745a2da..9e5c0c24a3397dd84fb225a3b48c24b841828e2a 100644 (file)
@@ -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
index f462072572873df4cdc83620d4268c08471b070d..933dc8e12a7a91d87b29199fa672ec77a0d441ff 100644 (file)
 #  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
index f88d3b571f92d4e64ee9a368a3e4b7e1f010e546..788db2129318e90df4c17bf67df8a0fcf9578908 100644 (file)
 
 #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. --- */
index f97a3af3a19c3cc86458d84aa58b124edf6387d0..e7aa8797629f6748130dbcae2908030d10e831aa 100644 (file)
 #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"
 
index bc18f40f76e06adb5dbda6258dd5378f2496f67e..f1710924aa7372e7b7e2abfbf7366a2286e33d2d 100644 (file)
 #undef PLAT_mips32_linux
 #undef PLAT_mips64_linux
 #undef PLAT_nanomips_linux
+#undef PLAT_riscv64_linux
 #undef PLAT_x86_solaris
 #undef PLAT_amd64_solaris
 
 #  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
 
index d4e1908e1e9c46dfe5aa863b5052f3d0ca9428d3..0df1b4c4b468f62accc555aba88d0e0f976ad14b 100644 (file)
@@ -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
index 176c8e5cb914bf8340aede5f16f86054bfa3a547..34df0011ac8bc6a240c591fd1b4fa2137f3a4f62 100644 (file)
@@ -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