]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
riscv64: Add initial support: test modifications
authorPetr Pavlu <petr.pavlu@dagobah.cz>
Tue, 11 Apr 2023 19:30:43 +0000 (19:30 +0000)
committerMark Wielaard <mark@klomp.org>
Tue, 25 Feb 2025 16:05:17 +0000 (17:05 +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>

Some integration fixes were added by Mark Wielaard <mark@klomp.org>
- helgrind/tests/tc11_XCHG.c: Fix XCHG_M_R guard

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

15 files changed:
helgrind/tests/annotate_hbefore.c
helgrind/tests/tc07_hbl1.c
helgrind/tests/tc08_hbl2.c
helgrind/tests/tc11_XCHG.c
memcheck/tests/Makefile.am
memcheck/tests/atomic_incs.c
memcheck/tests/leak-segv-jmp.c
memcheck/tests/leak-segv-jmp.stderr.exp
memcheck/tests/leak.h
none/tests/Makefile.am
none/tests/allexec_prepare_prereq
none/tests/faultstatus.c
none/tests/libvex_test.c
tests/arch_test.c
tests/platform_test

index 259d3b64c895800390375d16b10206014a8affb9..52dce3e76e8437a62364ac2d4a62c924ed85a550 100644 (file)
@@ -314,6 +314,36 @@ UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
    return success;
 }
 
+#elif defined(VGA_riscv64)
+
+// riscv64
+/* return 1 if success, 0 if failure */
+UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
+{
+  UWord success;
+  UWord block[3] = { (UWord)addr, nyu, expected};
+
+   __asm__ __volatile__(
+      "ld     t0, 0(%1)"         "\n\t"
+      "ld     t2, 16(%1)"        "\n\t"
+      "ld     t3, 8(%1)"         "\n\t"
+      "lr.d   t1, 0(t0)"         "\n\t"
+      "bne    t1, t2, 1f"        "\n\t"
+      "sc.d   t1, t3, 0(t0)"     "\n\t"
+      "xori   %0, t1, 1"         "\n\t"
+      "j 2f"                     "\n\t"
+      "1:"                       "\n\t"
+      "mv     %0, zero"          "\n\t"
+      "2:"                       "\n\t"
+      : /*out*/ "=r"(success)
+      : /*in*/ "r"(&block[0])
+      : /*trash*/ "t0", "t1", "t2", "t3", "memory"
+   );
+
+   assert(success == 0 || success == 1);
+   return success;
+}
+
 #endif
 
 void atomic_incW ( UWord* w )
index a4250c62c43df2000607abac5d2108bf4c2527d4..ee0564d20dccb14efe997862f09456b5679fad19 100644 (file)
@@ -19,6 +19,7 @@
 #undef PLAT_arm64_linux
 #undef PLAT_s390x_linux
 #undef PLAT_mips32_linux
+#undef PLAT_riscv64_linux
 #undef PLAT_x86_solaris
 #undef PLAT_amd64_solaris
 
@@ -50,6 +51,8 @@
 #  define PLAT_mips32_linux 1
 #elif defined(__linux__) && defined(__nanomips__)
 #  define PLAT_nanomips_linux 1
+#elif defined(__linux__) && defined(__riscv) && (__riscv_xlen == 64)
+#  define PLAT_riscv64_linux 1
 #elif defined(__sun__) && defined(__i386__)
 #  define PLAT_x86_solaris 1
 #elif defined(__sun__) && defined(__x86_64__)
       : /*out*/ : /*in*/ "r"(&(_lval))              \
       : /*trash*/ "$t0", "$t1", "memory"            \
    )
+#elif defined(PLAT_riscv64_linux)
+#  define INC(_lval,_lqual)                         \
+     __asm__ __volatile__ (                         \
+      "        amoadd.w zero, %1, (%0)\n"           \
+      : /*out*/ : /*in*/ "r"(&(_lval)), "r"(1)      \
+      : /*trash*/ "memory"                          \
+   )
 #else
 #  error "Fix Me for this platform"
 #endif
index 6a8543fa1d6fa6b0396ba91b287c37ec01bdd810..be2b78b01cb6451a93453d229c8b87ad51f70556 100644 (file)
@@ -36,6 +36,7 @@
 #undef PLAT_s390x_linux
 #undef PLAT_mips32_linux
 #undef PLAT_mips64_linux
+#undef PLAT_riscv64_linux
 #undef PLAT_x86_solaris
 #undef PLAT_amd64_solaris
 
@@ -71,6 +72,8 @@
 #endif
 #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__)
       : /*out*/ : /*in*/ "r"(&(_lval))              \
       : /*trash*/ "$t0", "$t1", "memory"            \
    )
+#elif defined(PLAT_riscv64_linux)
+#  define INC(_lval,_lqual)                         \
+     __asm__ __volatile__ (                         \
+      "        amoadd.w zero, %1, (%0)\n"           \
+      : /*out*/ : /*in*/ "r"(&(_lval)), "r"(1)      \
+      : /*trash*/ "memory"                          \
+   )
 #else
 #  error "Fix Me for this platform"
 #endif
index cc00ba38fed87506d59dbf6a1a7f9156e554996b..e92b671b7e44f6ef0e618f647be6c21cfdfc8918 100644 (file)
@@ -21,6 +21,7 @@
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
 #undef PLAT_mips32_linux
+#undef PLAT_riscv64_linux
 #undef PLAT_x86_solaris
 #undef PLAT_amd64_solaris
 
@@ -52,6 +53,8 @@
 #  define PLAT_mips32_linux 1
 #elif defined(__linux__) && defined(__nanomips__)
 #  define PLAT_nanomips_linux 1
+#elif defined(__linux__) && defined(__riscv) && (__riscv_xlen == 64)
+#  define PLAT_riscv64_linux 1
 #elif defined(__sun__) && defined(__i386__)
 #  define PLAT_x86_solaris 1
 #elif defined(__sun__) && defined(__x86_64__)
 
 #elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) \
       || defined(PLAT_arm_linux) || defined(PLAT_arm64_linux) \
-      || defined(PLAT_arm64_freebsd)
+      || defined(PLAT_arm64_freebsd) \
+      || defined(PLAT_riscv64_linux)
 #  if defined(HAVE_BUILTIN_ATOMIC)
 #    define XCHG_M_R(_addr,_lval)                                           \
         do {                                                                \
index bfdd86c7e3db3b3180bf8e732681ce875b4eb2bc..a4ca2853fbb3a9d6481d3c119a92c0d6c8691457 100644 (file)
@@ -53,6 +53,9 @@ endif
 if VGCONF_PLATFORMS_INCLUDE_ARM64_LINUX
 SUBDIRS += arm64-linux
 endif
+if VGCONF_PLATFORMS_INCLUDE_RISCV64_LINUX
+SUBDIRS += riscv64-linux
+endif
 if VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS
 SUBDIRS += x86-solaris
 endif
@@ -67,7 +70,7 @@ SUBDIRS += amd64-freebsd
 endif
 
 DIST_SUBDIRS = x86 amd64 arm64 ppc32 ppc64 s390x linux \
-               darwin solaris x86-linux amd64-linux arm64-linux \
+               darwin solaris x86-linux amd64-linux arm64-linux riscv64-linux \
                x86-solaris amd64-solaris mips32 mips64 \
                freebsd amd64-freebsd x86-freebsd \
                common .
index 1c738c530d0563ae051f4e4e7156b02d2c7828ac..89b6e1f757c844074d9e23e9d3eb0836bb3aa0b4 100644 (file)
@@ -245,6 +245,26 @@ __attribute__((noinline)) void atomic_add_8bit ( char* p, int n )
       );
    } while (block[2] != 1);
 #endif
+#elif defined(VGA_riscv64)
+   unsigned long long int block[3]
+      = { (unsigned long long int)p, (unsigned long long int)n,
+          0xFFFFFFFFFFFFFFFFULL};
+   do {
+      __asm__ __volatile__(
+         "mv     t0, %0"         "\n\t"
+         "ld     t1, (t0)"       "\n\t" // p
+         "ld     t2, 8(t0)"      "\n\t" // n
+         "lr.w   t3, (t1)"       "\n\t"
+         "slli   t3, t3, 56"     "\n\t" // sign-extend
+         "srai   t3, t3, 56"     "\n\t"
+         "add    t3, t3, t2"     "\n\t"
+         "sc.w   t4, t3, (t1)"   "\n\t"
+         "sd     t4, 16(t0)"     "\n\t"
+         : /*out*/
+         : /*in*/ "r"(&block[0])
+         : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
+      );
+   } while (block[2] != 0);
 #else
 # error "Unsupported arch"
 #endif
@@ -461,6 +481,26 @@ __attribute__((noinline)) void atomic_add_16bit ( short* p, int n )
       );
    } while (block[2] != 1);
 #endif
+#elif defined(VGA_riscv64)
+   unsigned long long int block[3]
+   = { (unsigned long long int)p, (unsigned long long int)n,
+       0xFFFFFFFFFFFFFFFFULL};
+   do {
+      __asm__ __volatile__(
+         "mv     t0, %0"         "\n\t"
+         "ld     t1, (t0)"       "\n\t" // p
+         "ld     t2, 8(t0)"      "\n\t" // n
+         "lr.w   t3, (t1)"       "\n\t"
+         "slli   t3, t3, 48"     "\n\t" // sign-extend
+         "srai   t3, t3, 48"     "\n\t"
+         "add    t3, t3, t2"     "\n\t"
+         "sc.w   t4, t3, (t1)"   "\n\t"
+         "sd     t4, 16(t0)"     "\n\t"
+         : /*out*/
+         : /*in*/ "r"(&block[0])
+         : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
+      );
+   } while (block[2] != 0);
 #else
 # error "Unsupported arch"
 #endif
@@ -616,6 +656,24 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n )
          : /*trash*/ "memory", "t0", "t1", "t2", "t3"
       );
    } while (block[2] != 1);
+#elif defined(VGA_riscv64)
+   unsigned long long int block[3]
+   = { (unsigned long long int)p, (unsigned long long int)n,
+       0xFFFFFFFFFFFFFFFFULL};
+   do {
+      __asm__ __volatile__(
+         "mv     t0, %0"         "\n\t"
+         "ld     t1, (t0)"       "\n\t" // p
+         "ld     t2, 8(t0)"      "\n\t" // n
+         "lr.w   t3, (t1)"       "\n\t"
+         "add    t3, t3, t2"     "\n\t"
+         "sc.w   t4, t3, (t1)"   "\n\t"
+         "sd     t4, 16(t0)"     "\n\t"
+         : /*out*/
+         : /*in*/ "r"(&block[0])
+         : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
+      );
+   } while (block[2] != 0);
 #else
 # error "Unsupported arch"
 #endif
@@ -718,6 +776,24 @@ __attribute__((noinline)) void atomic_add_64bit ( long long int* p, int n )
          : /*trash*/ "memory", "t0", "t1", "t2", "t3"
       );
    } while (block[2] != 1);
+#elif defined(VGA_riscv64)
+   unsigned long long int block[3]
+   = { (unsigned long long int)p, (unsigned long long int)n,
+       0xFFFFFFFFFFFFFFFFULL};
+   do {
+      __asm__ __volatile__(
+         "mv     t0, %0"         "\n\t"
+         "ld     t1, (t0)"       "\n\t" // p
+         "ld     t2, 8(t0)"      "\n\t" // n
+         "lr.d   t3, (t1)"       "\n\t"
+         "add    t3, t3, t2"     "\n\t"
+         "sc.d   t4, t3, (t1)"   "\n\t"
+         "sd     t4, 16(t0)"     "\n\t"
+         : /*out*/
+         : /*in*/ "r"(&block[0])
+         : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
+      );
+   } while (block[2] != 0);
 #else
 # error "Unsupported arch"
 #endif
@@ -731,7 +807,7 @@ __attribute__((noinline)) void atomic_add_128bit ( MyU128* p,
     || defined(VGA_amd64) \
     || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
     || defined(VGA_arm) \
-    || defined(VGA_s390x)
+    || defined(VGA_s390x) || defined(VGA_riscv64)
    /* do nothing; is not supported */
 #elif defined(VGA_arm64)
    unsigned long long int block[3]
index 30fe2a1a992f95a2eba035d3c2e920653f5ea4f1..15cc9f8fb2393705f2c1166099091201f5415721 100644 (file)
@@ -183,6 +183,23 @@ extern UWord do_syscall_WRK (
    return out;
 }
 
+#elif defined(VGP_riscv64_linux)
+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
 do_syscall_WRK(UWord a1, UWord a2, UWord a3,
@@ -369,7 +386,7 @@ static void non_simd_mprotect (long tid, void* addr, long len)
                                     &err);
    if (err)
       mprotect_result = -1;
-#elif defined(VGP_arm64_linux)
+#elif defined(VGP_arm64_linux) || defined(VGP_riscv64_linux)
    mprotect_result = do_syscall_WRK((UWord) addr, len, PROT_NONE,
                                     0, 0, 0,
                                     __NR_mprotect);
index 147bdf8cdfd814d10feb1da7566220737f3597e3..e18418d440e71b3cb683b83d8626ff6a1100312d 100644 (file)
@@ -14,8 +14,8 @@ To see them, rerun with: --leak-check=full --show-leak-kinds=all
 expecting a leak
 1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
    at 0x........: malloc (vg_replace_malloc.c:...)
-   by 0x........: f (leak-segv-jmp.c:420)
-   by 0x........: main (leak-segv-jmp.c:495)
+   by 0x........: f (leak-segv-jmp.c:437)
+   by 0x........: main (leak-segv-jmp.c:512)
 
 LEAK SUMMARY:
    definitely lost: 1,000 bytes in 1 blocks
@@ -30,8 +30,8 @@ mprotect result 0
 expecting a leak again
 1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
    at 0x........: malloc (vg_replace_malloc.c:...)
-   by 0x........: f (leak-segv-jmp.c:420)
-   by 0x........: main (leak-segv-jmp.c:495)
+   by 0x........: f (leak-segv-jmp.c:437)
+   by 0x........: main (leak-segv-jmp.c:512)
 
 LEAK SUMMARY:
    definitely lost: 1,000 bytes in 1 blocks
@@ -46,8 +46,8 @@ full mprotect result 0
 expecting a leak again after full mprotect
 1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
    at 0x........: malloc (vg_replace_malloc.c:...)
-   by 0x........: f (leak-segv-jmp.c:420)
-   by 0x........: main (leak-segv-jmp.c:495)
+   by 0x........: f (leak-segv-jmp.c:437)
+   by 0x........: main (leak-segv-jmp.c:512)
 
 LEAK SUMMARY:
    definitely lost: 1,000 bytes in 1 blocks
@@ -62,13 +62,13 @@ mprotect result 0
 expecting heuristic not to crash after full mprotect
 1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
    at 0x........: malloc (vg_replace_malloc.c:...)
-   by 0x........: f (leak-segv-jmp.c:420)
-   by 0x........: main (leak-segv-jmp.c:495)
+   by 0x........: f (leak-segv-jmp.c:437)
+   by 0x........: main (leak-segv-jmp.c:512)
 
 200,000 bytes in 1 blocks are possibly lost in loss record ... of ...
    at 0x........: calloc (vg_replace_malloc.c:...)
-   by 0x........: f (leak-segv-jmp.c:467)
-   by 0x........: main (leak-segv-jmp.c:495)
+   by 0x........: f (leak-segv-jmp.c:484)
+   by 0x........: main (leak-segv-jmp.c:512)
 
 LEAK SUMMARY:
    definitely lost: 1,000 bytes in 1 blocks
index bf78d5866f549feb0027b016e1a71b5189091703..f9a2db290d43d6dee3170b073036fd6fcf56f1fd 100644 (file)
       __asm__ __volatile__ ("mov x17, 0\n\t");                              \
       __asm__ __volatile__ ("mov x18, 0\n\t");                              \
    } while (0)
+#elif defined(__riscv)
+#define CLEAR_CALLER_SAVED_REGS \
+  do { \
+    __asm__ __volatile__( "li a0, 0" : : :/*trash*/"a0" ); \
+  } while (0)
 #else
 #define CLEAR_CALLER_SAVED_REGS  /*nothing*/
 #endif
index 7ceb0052b480bd8290454b7f3043d6726a6a1486..d119c74a1da295f48b0b0ae68f5a87384f42f58c 100644 (file)
@@ -35,6 +35,9 @@ endif
 if VGCONF_ARCHS_INCLUDE_NANOMIPS
 SUBDIRS += nanomips
 endif
+if VGCONF_ARCHS_INCLUDE_RISCV64
+SUBDIRS += riscv64
+endif
 
 
 # OS-specific tests
@@ -75,8 +78,9 @@ SUBDIRS += x86-freebsd
 endif
 
 DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm arm64 s390x mips32 mips64 nanomips \
-               linux darwin solaris freebsd amd64-linux x86-linux amd64-darwin \
-               x86-darwin amd64-solaris x86-solaris x86-freebsd scripts .
+               riscv64 linux darwin solaris freebsd amd64-linux x86-linux \
+               amd64-darwin x86-darwin amd64-solaris x86-solaris x86-freebsd \
+               scripts .
 
 dist_noinst_SCRIPTS = \
        filter_cmdline0 \
@@ -401,6 +405,11 @@ libvex_test_CFLAGS      = $(AM_CFLAGS) @FLAG_FSANITIZE@
 libvex_test_LDADD       = ../../VEX/libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a \
                           @LIB_UBSAN@
 libvexmultiarch_test_CFLAGS= $(AM_CFLAGS) @FLAG_FSANITIZE@
+if VGCONF_ARCHS_INCLUDE_RISCV64
+# Disable RISC-V linker relaxation, it takes GNU ld 2.39 tens of minutes to sort
+# it through on this large test.
+libvexmultiarch_test_LDFLAGS = -Wl,--no-relax
+endif
 libvexmultiarch_test_LDADD = \
        ../../VEX/libvexmultiarch-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a \
        ../../VEX/libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a @LIB_UBSAN@
index a541f42994dbea32262c3aa7462f86aa611800a2..fa4d3170699103780ed8a78c36b03f07f7a4dd6f 100755 (executable)
@@ -34,5 +34,6 @@ pair s390x_unexisting_in_32bits s390x
 pair arm                        arm64
 pair mips32                     mips64
 pair nanomips                   nanoMIPS_unexisting_in_64bits
+pair riscv_unexisting_in_32bits riscv64
 
 exit 0
index 9e262395bc9c26a47dcae3c4bf91ae6c503c6c6e..a83546b54bf22f25fb61df3ab68d3f9e0f0294cc 100644 (file)
@@ -11,7 +11,7 @@
 #include "../../config.h"
 
 /* Division by zero triggers a SIGFPE on x86 and x86_64,
-   but not on the PowerPC architecture.
+   but not on the PowerPC, AArch64 and RISC-V architectures.
 
    On ARM-Linux, we do get a SIGFPE, but not from the faulting of a
    division instruction (there isn't any such thing) but rather
@@ -19,7 +19,7 @@
    Hence we get a SIGFPE but the SI_CODE is different from that on
    x86/amd64-linux.
  */
-#if defined(__powerpc__) || defined(__aarch64__)
+#if defined(__powerpc__) || defined(__aarch64__) || defined(__riscv)
 #  define DIVISION_BY_ZERO_TRIGGERS_FPE 0
 #if defined(VGO_freebsd)
 #  define DIVISION_BY_ZERO_SI_CODE      SI_LWP
index 5b57a4c2e220ec1c4e545dcf31239457065a8a5a..6a8086aced0b5542829b069a2fab0cf881df9b68 100644 (file)
@@ -76,6 +76,8 @@ __attribute__((noinline)) static void get_guest_arch(VexArch    *ga)
    *ga = VexArchMIPS64;
 #elif defined(VGA_nanomips)
    *ga = VexArchNANOMIPS;
+#elif defined(VGA_riscv64)
+   *ga = VexArchRISCV64;
 #else
    missing arch;
 #endif
@@ -113,6 +115,7 @@ static VexEndness arch_endness (VexArch va) {
          else
             return VexEndnessBE;
       }
+   case VexArchRISCV64: return VexEndnessLE;
    default: failure_exit();
    }
 }
@@ -139,6 +142,7 @@ static UInt arch_hwcaps (VexArch va) {
    case VexArchMIPS64: return VEX_PRID_COMP_MIPS | VEX_MIPS_HOST_FR;
 #endif
    case VexArchNANOMIPS: return 0;
+   case VexArchRISCV64: return 0;
    default: failure_exit();
    }
 }
@@ -156,6 +160,7 @@ static Bool mode64 (VexArch va) {
    case VexArchMIPS32: return False;
    case VexArchMIPS64: return True;
    case VexArchNANOMIPS: return False;
+   case VexArchRISCV64: return True;
    default: failure_exit();
    }
 }
@@ -275,7 +280,7 @@ int main(int argc, char **argv)
    // explicitly via command line arguments.
    if (multiarch) {
       VexArch va;
-      for (va = VexArchX86; va <= VexArchNANOMIPS; va++) {
+      for (va = VexArchX86; va <= VexArchRISCV64; va++) {
          vta.arch_host = va;
          vta.archinfo_host.endness = arch_endness (vta.arch_host);
          vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host);
index 4dbb8ca1091111fa13c75188f45735bf4f6c309a..84b1f130791a26c433276ff878dc5500a4a4bd9e 100644 (file)
@@ -34,6 +34,7 @@ char* all_archs[] = {
    "mips32",
    "mips64",
    "nanomips",
+   "riscv64",
    NULL
 };
 
@@ -79,6 +80,10 @@ static Bool go(char* arch)
 
 #elif defined(VGP_nanomips_linux)
    if ( 0 == strcmp( arch, "nanomips" ) ) return True;
+
+#elif defined(VGP_riscv64_linux)
+   if ( 0 == strcmp( arch, "riscv64" ) ) return True;
+
 #else
 #  error Unknown platform
 #endif   // VGP_*
index c23a4f64538a58739e6ef1fc6835f016aaef0ada..9762d0c09b38e4f9cafe8d17d4b0e5b98ce8a835 100644 (file)
@@ -14,6 +14,7 @@ all_platforms=
 all_platforms="$all_platforms x86-linux amd64-linux ppc32-linux ppc64-linux"
 all_platforms="$all_platforms arm-linux arm64-linux"
 all_platforms="$all_platforms s390x-linux mips32-linux mips64-linux"
+all_platforms="$all_platforms riscv64-linux"
 all_platforms="$all_platforms x86-darwin amd64-darwin"
 all_platforms="$all_platforms x86-solaris amd64-solaris"
 all_platforms="$all_platforms x86-freebsd amd64-freebsd"