--- /dev/null
+
+Status
+~~~~~~
+
+The RISC-V port targets the 64-bit RISC-V architecture and the Linux operating
+system. The port has been tested to work on real hardware and under QEMU.
+
+The following ISA base and extensions are currently supported:
+
+| Name | Description | #Instrs | Notes |
+| ------------ | --------------------------------- | ------- | -------- |
+| RV64I | Base instruction set | 52/52 | |
+| RV64M | Integer multiplication & division | 12/13 | (1) |
+| RV64A | Atomic | 22/22 | (2) |
+| RV64F | Single-precision floating-point | 30/30 | (3) |
+| RV64D | Double-precision floating-point | 32/32 | |
+| RV64Zicsr | Control & status register | 2/6 | (4), (5) |
+| RV64Zifencei | Instruction-fetch fence | 0/1 | (6) |
+| RV64C | Compressed | 37/37 | |
+
+Notes:
+(1) MULHSU is not recognized.
+(2) LR and SC use the VEX "fallback" method which suffers from the ABA problem.
+(3) Operations do not check if the input operands are correctly NaN-boxed.
+(4) CSRRC, CSRRWI, CSRRSI and CSRRCI are not recognized.
+(5) Only registers fflags, frm and fcsr are accepted.
+(6) FENCE.I is not recognized.
+
+
+Implementation tidying-up/TODO notes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Implement a proper "non-fallback" method for LR and SC instructions.
+* Add a check for correct NaN-boxing of 32-bit floating-point operands.
+* Optimize instruction selection, in particular make more use of <instr>i
+ variants.
+* Optimize handling of floating-point exceptions. Avoid helpers and calculate
+ exception flags using the same instruction which produced an actual result.
+* Review register usage by the codegen.
+* Avoid re-use of Intel-constants CFIC_IA_SPREL and CFIC_IA_BPREL. Generalize
+ them for all architectures or introduce same CFIC_RISCV64_ variants.
+* Get rid of the typedef of vki_modify_ldt_t in include/vki/vki-riscv64-linux.h.
+* Review if setup_client_stack() should expose AT_SYSINFO_EHDR to clients.
+* Make sure that the final exit sequence in run_a_thread_NORETURN() is not racy
+ in regards to accessing the thread state.
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- The core dispatch loop, for jumping to a code address. ---*/
+/*--- dispatch-riscv64-linux.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+
+#if defined(VGP_riscv64_linux)
+
+#include "pub_core_dispatch_asm.h"
+#include "pub_core_transtab_asm.h"
+#include "libvex_guest_offsets.h"
+
+
+/*------------------------------------------------------------*/
+/*--- ---*/
+/*--- The dispatch loop. VG_(disp_run_translations) is ---*/
+/*--- used to run all translations, ---*/
+/*--- including no-redir ones. ---*/
+/*--- ---*/
+/*------------------------------------------------------------*/
+
+/*----------------------------------------------------*/
+/*--- Entry and preamble (set everything up) ---*/
+/*----------------------------------------------------*/
+
+/* signature:
+void VG_(disp_run_translations)( UWord* two_words,
+ void* guest_state,
+ Addr host_addr );
+*/
+.text
+.global VG_(disp_run_translations)
+VG_(disp_run_translations):
+ /* a0 holds two_words
+ a1 holds guest_state
+ a2 holds host_addr
+ */
+ /* Push the callee-saved registers. Note this sequence maintains
+ 16-alignment of sp. Also save a0 since it will be needed in the
+ postamble. */
+ addi sp, sp, -112
+ sd ra, 104(sp)
+ sd s0, 96(sp)
+ sd s1, 88(sp)
+ sd s2, 80(sp)
+ sd s3, 72(sp)
+ sd s4, 64(sp)
+ sd s5, 56(sp)
+ sd s6, 48(sp)
+ sd s7, 40(sp)
+ sd s8, 32(sp)
+ sd s9, 24(sp)
+ sd s10, 16(sp)
+ sd s11, 8(sp)
+ sd a0, 0(sp)
+
+ /* Set up the guest state pointer. */
+ li t0, 2048
+ add s0, a1, t0
+
+ /* and jump into the code cache. Chained translations in the code cache
+ run, until for whatever reason, they can't continue. When that
+ happens, the translation in question will jump (or call) to one of
+ the continuation points VG_(cp_...) below. */
+ jr a2
+ /* NOTREACHED */
+
+/*----------------------------------------------------*/
+/*--- Postamble and exit. ---*/
+/*----------------------------------------------------*/
+
+postamble:
+ /* At this point, t0 and t1 contain two words to be returned to the
+ caller. t0 holds a TRC value, and t1 optionally may hold another
+ word (for CHAIN_ME exits, the address of the place to patch.) */
+
+ /* Restore int regs, including importantly a0 (two_words). */
+ ld ra, 104(sp)
+ ld s0, 96(sp)
+ ld s1, 88(sp)
+ ld s2, 80(sp)
+ ld s3, 72(sp)
+ ld s4, 64(sp)
+ ld s5, 56(sp)
+ ld s6, 48(sp)
+ ld s7, 40(sp)
+ ld s8, 32(sp)
+ ld s9, 24(sp)
+ ld s10, 16(sp)
+ ld s11, 8(sp)
+ ld a0, 0(sp)
+ addi sp, sp, 112
+
+ /* Stash return values. */
+ sd t0, 0(a0)
+ sd t1, 8(a0)
+ ret
+
+/*----------------------------------------------------*/
+/*--- Continuation points ---*/
+/*----------------------------------------------------*/
+
+/* ------ Chain me to slow entry point ------ */
+.global VG_(disp_cp_chain_me_to_slowEP)
+VG_(disp_cp_chain_me_to_slowEP):
+ /* We got called. The return address indicates where the patching needs
+ to happen. Collect the return address and, exit back to C land,
+ handing the caller the pair (Chain_me_F, RA). */
+ li t0, VG_TRC_CHAIN_ME_TO_SLOW_EP
+ mv t1, ra
+ /* 4 = lui t0, disp_cp_chain_me_to_slowEP[47:28]'
+ 4 = addiw t0, t0, disp_cp_chain_me_to_slowEP[27:16]'
+ 2 = c.slli t0, 12
+ 4 = addi t0, t0, disp_cp_chain_me_to_slowEP[15:4]'
+ 2 = c.slli t0, 4
+ 2 = c.addi t0, disp_cp_chain_me_to_slowEP[3:0]'
+ 2 = c.jalr 0(t0)
+ */
+ addi t1, t1, -(4+4+2+4+2+2+2)
+ j postamble
+
+/* ------ Chain me to fast entry point ------ */
+.global VG_(disp_cp_chain_me_to_fastEP)
+VG_(disp_cp_chain_me_to_fastEP):
+ /* We got called. The return address indicates where the patching needs
+ to happen. Collect the return address and, exit back to C land,
+ handing the caller the pair (Chain_me_F, RA). */
+ li t0, VG_TRC_CHAIN_ME_TO_FAST_EP
+ mv t1, ra
+ /* 4 = lui t0, disp_cp_chain_me_to_fastEP[47:28]'
+ 4 = addiw t0, t0, disp_cp_chain_me_to_fastEP[27:16]'
+ 2 = c.slli t0, 12
+ 4 = addi t0, t0, disp_cp_chain_me_to_fastEP[15:4]'
+ 2 = c.slli t0, 4
+ 2 = c.addi t0, disp_cp_chain_me_to_fastEP[3:0]'
+ 2 = c.jalr 0(t0)
+ */
+ addi t1, t1, -(4+4+2+4+2+2+2)
+ j postamble
+
+/* ------ Indirect but boring jump ------ */
+.global VG_(disp_cp_xindir)
+VG_(disp_cp_xindir):
+ /* Where are we going? */
+ ld t0, OFFSET_riscv64_pc-2048(s0)
+
+ /* Stats only. */
+ lw t1, VG_(stats__n_xIndirs_32)
+ addi t1, t1, 1
+ sw t1, VG_(stats__n_xIndirs_32), t2
+
+ /* LIVE: s0 (guest state ptr), t0 (guest address to go to).
+ We use 6 temporaries:
+ t6 (to point at the relevant FastCacheSet),
+ t1, t2, t3 (scratch, for swapping entries within a set)
+ t4, t5 (other scratch) */
+
+ /* Try a fast lookup in the translation cache. This is pretty much
+ a handcoded version of VG_(lookupInFastCache). */
+
+ /* Compute t6 = VG_TT_FAST_HASH(guest). */
+ srli t6, t0, 1 /* g2 = guest >> 1 */
+ srli t4, t6, VG_TT_FAST_BITS /* g2 >> VG_TT_FAST_BITS */
+ xor t6, t4, t6 /* (g2 >> VG_TT_FAST_BITS) ^ g2 */
+ li t4, VG_TT_FAST_MASK /* VG_TT_FAST_MASK */
+ and t6, t6, t4 /* setNo */
+
+ /* Compute t6 = &VG_(tt_fast)[t6]. */
+ la t4, VG_(tt_fast) /* &VG_(tt_fast)[0] */
+ slli t6, t6, VG_FAST_CACHE_SET_BITS
+ add t6, t4, t6 /* &VG_(tt_fast)[setNo] */
+
+ /* LIVE: s0 (guest state ptr), t0 (guest addr), t6 (cache set). */
+ /* Try way 0. */
+ ld t4, FCS_g0(t6) /* t4 = .guest0 */
+ bne t4, t0, 1f /* cmp against .guest0 */
+ /* Hit at way 0. */
+ /* Go to .host0. */
+ ld t5, FCS_h0(t6) /* t5 = .host0 */
+ jr t5
+ /*NOTREACHED*/
+
+1: /* Try way 1. */
+ ld t4, FCS_g1(t6)
+ bne t4, t0, 2f /* cmp against .guest1 */
+ /* Hit at way 1; swap upwards. */
+ ld t1, FCS_g0(t6) /* t1 = old .guest0 */
+ ld t2, FCS_h0(t6) /* t2 = old .host0 */
+ ld t3, FCS_h1(t6) /* t3 = old .host1 */
+ sd t0, FCS_g0(t6) /* new .guest0 = guest */
+ sd t3, FCS_h0(t6) /* new .host0 = old .host1 */
+ sd t1, FCS_g1(t6) /* new .guest1 = old .guest0 */
+ sd t2, FCS_h1(t6) /* new .host1 = old .host0 */
+ /* Stats only. */
+ lw t4, VG_(stats__n_xIndir_hits1_32)
+ addi t4, t4, 1
+ sw t4, VG_(stats__n_xIndir_hits1_32), t5
+ /* Go to old .host1 a.k.a. new .host0. */
+ jr t3
+ /*NOTREACHED*/
+
+2: /* Try way 2. */
+ ld t4, FCS_g2(t6)
+ bne t4, t0, 3f /* cmp against .guest2 */
+ /* Hit at way 2; swap upwards. */
+ ld t1, FCS_g1(t6)
+ ld t2, FCS_h1(t6)
+ ld t3, FCS_h2(t6)
+ sd t0, FCS_g1(t6)
+ sd t3, FCS_h1(t6)
+ sd t1, FCS_g2(t6)
+ sd t2, FCS_h2(t6)
+ /* Stats only. */
+ lw t4, VG_(stats__n_xIndir_hits2_32)
+ addi t4, t4, 1
+ sw t4, VG_(stats__n_xIndir_hits2_32), t5
+ /* Go to old .host2 a.k.a. new .host1. */
+ jr t3
+ /*NOTREACHED*/
+
+3: /* Try way 3. */
+ ld t4, FCS_g3(t6)
+ bne t4, t0, 4f /* cmp against .guest3 */
+ /* Hit at way 3; swap upwards. */
+ ld t1, FCS_g2(t6)
+ ld t2, FCS_h2(t6)
+ ld t3, FCS_h3(t6)
+ sd t0, FCS_g2(t6)
+ sd t3, FCS_h2(t6)
+ sd t1, FCS_g3(t6)
+ sd t2, FCS_h3(t6)
+ /* Stats only. */
+ lw t4, VG_(stats__n_xIndir_hits3_32)
+ addi t4, t4, 1
+ sw t4, VG_(stats__n_xIndir_hits3_32), t5
+ /* Go to old .host3 a.k.a. new .host2. */
+ jr t3
+ /*NOTREACHED*/
+
+4: /* Fast lookup failed. */
+ lw t4, VG_(stats__n_xIndir_misses_32)
+ addi t4, t4, 1
+ sw t4, VG_(stats__n_xIndir_misses_32), t5
+
+ li t0, VG_TRC_INNER_FASTMISS
+ li t1, 0
+ j postamble
+
+/* ------ Assisted jump ------ */
+.global VG_(disp_cp_xassisted)
+VG_(disp_cp_xassisted):
+ /* s0 contains the TRC. */
+ mv t0, s0
+ li t1, 0
+ j postamble
+
+/* ------ Event check failed ------ */
+.global VG_(disp_cp_evcheck_fail)
+VG_(disp_cp_evcheck_fail):
+ li t0, VG_TRC_INNER_COUNTERZERO
+ li t1, 0
+ j postamble
+
+.size VG_(disp_run_translations), .-VG_(disp_run_translations)
+
+#endif // defined(VGP_riscv64_linux)
+
+/* Let the linker know we don't need an executable stack */
+MARK_STACK_NO_EXEC
+
+/*--------------------------------------------------------------------*/
+/*--- end dispatch-riscv64-linux.S ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.cpu.valgrind.s1">
+ <reg name="zeros1" bitsize="64" type="int" regnum="69"/>
+ <reg name="ras1" bitsize="64" type="int"/>
+ <reg name="sps1" bitsize="64" type="int"/>
+ <reg name="gps1" bitsize="64" type="int"/>
+ <reg name="tps1" bitsize="64" type="int"/>
+ <reg name="t0s1" bitsize="64" type="int"/>
+ <reg name="t1s1" bitsize="64" type="int"/>
+ <reg name="t2s1" bitsize="64" type="int"/>
+ <reg name="fps1" bitsize="64" type="int"/>
+ <reg name="s1s1" bitsize="64" type="int"/>
+ <reg name="a0s1" bitsize="64" type="int"/>
+ <reg name="a1s1" bitsize="64" type="int"/>
+ <reg name="a2s1" bitsize="64" type="int"/>
+ <reg name="a3s1" bitsize="64" type="int"/>
+ <reg name="a4s1" bitsize="64" type="int"/>
+ <reg name="a5s1" bitsize="64" type="int"/>
+ <reg name="a6s1" bitsize="64" type="int"/>
+ <reg name="a7s1" bitsize="64" type="int"/>
+ <reg name="s2s1" bitsize="64" type="int"/>
+ <reg name="s3s1" bitsize="64" type="int"/>
+ <reg name="s4s1" bitsize="64" type="int"/>
+ <reg name="s5s1" bitsize="64" type="int"/>
+ <reg name="s6s1" bitsize="64" type="int"/>
+ <reg name="s7s1" bitsize="64" type="int"/>
+ <reg name="s8s1" bitsize="64" type="int"/>
+ <reg name="s9s1" bitsize="64" type="int"/>
+ <reg name="s10s1" bitsize="64" type="int"/>
+ <reg name="s11s1" bitsize="64" type="int"/>
+ <reg name="t3s1" bitsize="64" type="int"/>
+ <reg name="t4s1" bitsize="64" type="int"/>
+ <reg name="t5s1" bitsize="64" type="int"/>
+ <reg name="t6s1" bitsize="64" type="int"/>
+ <reg name="pcs1" bitsize="64" type="int"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.cpu.valgrind.s2">
+ <reg name="zeros2" bitsize="64" type="int" regnum="138"/>
+ <reg name="ras2" bitsize="64" type="int"/>
+ <reg name="sps2" bitsize="64" type="int"/>
+ <reg name="gps2" bitsize="64" type="int"/>
+ <reg name="tps2" bitsize="64" type="int"/>
+ <reg name="t0s2" bitsize="64" type="int"/>
+ <reg name="t1s2" bitsize="64" type="int"/>
+ <reg name="t2s2" bitsize="64" type="int"/>
+ <reg name="fps2" bitsize="64" type="int"/>
+ <reg name="s1s2" bitsize="64" type="int"/>
+ <reg name="a0s2" bitsize="64" type="int"/>
+ <reg name="a1s2" bitsize="64" type="int"/>
+ <reg name="a2s2" bitsize="64" type="int"/>
+ <reg name="a3s2" bitsize="64" type="int"/>
+ <reg name="a4s2" bitsize="64" type="int"/>
+ <reg name="a5s2" bitsize="64" type="int"/>
+ <reg name="a6s2" bitsize="64" type="int"/>
+ <reg name="a7s2" bitsize="64" type="int"/>
+ <reg name="s2s2" bitsize="64" type="int"/>
+ <reg name="s3s2" bitsize="64" type="int"/>
+ <reg name="s4s2" bitsize="64" type="int"/>
+ <reg name="s5s2" bitsize="64" type="int"/>
+ <reg name="s6s2" bitsize="64" type="int"/>
+ <reg name="s7s2" bitsize="64" type="int"/>
+ <reg name="s8s2" bitsize="64" type="int"/>
+ <reg name="s9s2" bitsize="64" type="int"/>
+ <reg name="s10s2" bitsize="64" type="int"/>
+ <reg name="s11s2" bitsize="64" type="int"/>
+ <reg name="t3s2" bitsize="64" type="int"/>
+ <reg name="t4s2" bitsize="64" type="int"/>
+ <reg name="t5s2" bitsize="64" type="int"/>
+ <reg name="t6s2" bitsize="64" type="int"/>
+ <reg name="pcs2" bitsize="64" type="int"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- Register numbers are hard-coded in order to maintain backward
+ compatibility with older versions of tools that didn't use xml
+ register descriptions. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.cpu">
+ <reg name="zero" bitsize="64" type="int" regnum="0"/>
+ <reg name="ra" bitsize="64" type="code_ptr"/>
+ <reg name="sp" bitsize="64" type="data_ptr"/>
+ <reg name="gp" bitsize="64" type="data_ptr"/>
+ <reg name="tp" bitsize="64" type="data_ptr"/>
+ <reg name="t0" bitsize="64" type="int"/>
+ <reg name="t1" bitsize="64" type="int"/>
+ <reg name="t2" bitsize="64" type="int"/>
+ <reg name="fp" bitsize="64" type="data_ptr"/>
+ <reg name="s1" bitsize="64" type="int"/>
+ <reg name="a0" bitsize="64" type="int"/>
+ <reg name="a1" bitsize="64" type="int"/>
+ <reg name="a2" bitsize="64" type="int"/>
+ <reg name="a3" bitsize="64" type="int"/>
+ <reg name="a4" bitsize="64" type="int"/>
+ <reg name="a5" bitsize="64" type="int"/>
+ <reg name="a6" bitsize="64" type="int"/>
+ <reg name="a7" bitsize="64" type="int"/>
+ <reg name="s2" bitsize="64" type="int"/>
+ <reg name="s3" bitsize="64" type="int"/>
+ <reg name="s4" bitsize="64" type="int"/>
+ <reg name="s5" bitsize="64" type="int"/>
+ <reg name="s6" bitsize="64" type="int"/>
+ <reg name="s7" bitsize="64" type="int"/>
+ <reg name="s8" bitsize="64" type="int"/>
+ <reg name="s9" bitsize="64" type="int"/>
+ <reg name="s10" bitsize="64" type="int"/>
+ <reg name="s11" bitsize="64" type="int"/>
+ <reg name="t3" bitsize="64" type="int"/>
+ <reg name="t4" bitsize="64" type="int"/>
+ <reg name="t5" bitsize="64" type="int"/>
+ <reg name="t6" bitsize="64" type="int"/>
+ <reg name="pc" bitsize="64" type="code_ptr"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.fpu.valgrind.s1">
+
+ <reg name="ft0s1" bitsize="64" type="int" regnum="102"/>
+ <reg name="ft1s1" bitsize="64" type="int"/>
+ <reg name="ft2s1" bitsize="64" type="int"/>
+ <reg name="ft3s1" bitsize="64" type="int"/>
+ <reg name="ft4s1" bitsize="64" type="int"/>
+ <reg name="ft5s1" bitsize="64" type="int"/>
+ <reg name="ft6s1" bitsize="64" type="int"/>
+ <reg name="ft7s1" bitsize="64" type="int"/>
+ <reg name="fs0s1" bitsize="64" type="int"/>
+ <reg name="fs1s1" bitsize="64" type="int"/>
+ <reg name="fa0s1" bitsize="64" type="int"/>
+ <reg name="fa1s1" bitsize="64" type="int"/>
+ <reg name="fa2s1" bitsize="64" type="int"/>
+ <reg name="fa3s1" bitsize="64" type="int"/>
+ <reg name="fa4s1" bitsize="64" type="int"/>
+ <reg name="fa5s1" bitsize="64" type="int"/>
+ <reg name="fa6s1" bitsize="64" type="int"/>
+ <reg name="fa7s1" bitsize="64" type="int"/>
+ <reg name="fs2s1" bitsize="64" type="int"/>
+ <reg name="fs3s1" bitsize="64" type="int"/>
+ <reg name="fs4s1" bitsize="64" type="int"/>
+ <reg name="fs5s1" bitsize="64" type="int"/>
+ <reg name="fs6s1" bitsize="64" type="int"/>
+ <reg name="fs7s1" bitsize="64" type="int"/>
+ <reg name="fs8s1" bitsize="64" type="int"/>
+ <reg name="fs9s1" bitsize="64" type="int"/>
+ <reg name="fs10s1" bitsize="64" type="int"/>
+ <reg name="fs11s1" bitsize="64" type="int"/>
+ <reg name="ft8s1" bitsize="64" type="int"/>
+ <reg name="ft9s1" bitsize="64" type="int"/>
+ <reg name="ft10s1" bitsize="64" type="int"/>
+ <reg name="ft11s1" bitsize="64" type="int"/>
+
+ <reg name="fflagss1" bitsize="32" type="int" regnum="135"/>
+ <reg name="frms1" bitsize="32" type="int"/>
+ <reg name="fcsrs1" bitsize="32" type="int"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.fpu.valgrind.s2">
+
+ <reg name="ft0s2" bitsize="64" type="int" regnum="171"/>
+ <reg name="ft1s2" bitsize="64" type="int"/>
+ <reg name="ft2s2" bitsize="64" type="int"/>
+ <reg name="ft3s2" bitsize="64" type="int"/>
+ <reg name="ft4s2" bitsize="64" type="int"/>
+ <reg name="ft5s2" bitsize="64" type="int"/>
+ <reg name="ft6s2" bitsize="64" type="int"/>
+ <reg name="ft7s2" bitsize="64" type="int"/>
+ <reg name="fs0s2" bitsize="64" type="int"/>
+ <reg name="fs1s2" bitsize="64" type="int"/>
+ <reg name="fa0s2" bitsize="64" type="int"/>
+ <reg name="fa1s2" bitsize="64" type="int"/>
+ <reg name="fa2s2" bitsize="64" type="int"/>
+ <reg name="fa3s2" bitsize="64" type="int"/>
+ <reg name="fa4s2" bitsize="64" type="int"/>
+ <reg name="fa5s2" bitsize="64" type="int"/>
+ <reg name="fa6s2" bitsize="64" type="int"/>
+ <reg name="fa7s2" bitsize="64" type="int"/>
+ <reg name="fs2s2" bitsize="64" type="int"/>
+ <reg name="fs3s2" bitsize="64" type="int"/>
+ <reg name="fs4s2" bitsize="64" type="int"/>
+ <reg name="fs5s2" bitsize="64" type="int"/>
+ <reg name="fs6s2" bitsize="64" type="int"/>
+ <reg name="fs7s2" bitsize="64" type="int"/>
+ <reg name="fs8s2" bitsize="64" type="int"/>
+ <reg name="fs9s2" bitsize="64" type="int"/>
+ <reg name="fs10s2" bitsize="64" type="int"/>
+ <reg name="fs11s2" bitsize="64" type="int"/>
+ <reg name="ft8s2" bitsize="64" type="int"/>
+ <reg name="ft9s2" bitsize="64" type="int"/>
+ <reg name="ft10s2" bitsize="64" type="int"/>
+ <reg name="ft11s2" bitsize="64" type="int"/>
+
+ <reg name="fflagss2" bitsize="32" type="int" regnum="204"/>
+ <reg name="frms2" bitsize="32" type="int"/>
+ <reg name="fcsrs2" bitsize="32" type="int"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- Register numbers are hard-coded in order to maintain backward
+ compatibility with older versions of tools that didn't use xml
+ register descriptions. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.riscv.fpu">
+
+ <union id="riscv_double">
+ <field name="float" type="ieee_single"/>
+ <field name="double" type="ieee_double"/>
+ </union>
+
+ <reg name="ft0" bitsize="64" type="riscv_double" regnum="33"/>
+ <reg name="ft1" bitsize="64" type="riscv_double"/>
+ <reg name="ft2" bitsize="64" type="riscv_double"/>
+ <reg name="ft3" bitsize="64" type="riscv_double"/>
+ <reg name="ft4" bitsize="64" type="riscv_double"/>
+ <reg name="ft5" bitsize="64" type="riscv_double"/>
+ <reg name="ft6" bitsize="64" type="riscv_double"/>
+ <reg name="ft7" bitsize="64" type="riscv_double"/>
+ <reg name="fs0" bitsize="64" type="riscv_double"/>
+ <reg name="fs1" bitsize="64" type="riscv_double"/>
+ <reg name="fa0" bitsize="64" type="riscv_double"/>
+ <reg name="fa1" bitsize="64" type="riscv_double"/>
+ <reg name="fa2" bitsize="64" type="riscv_double"/>
+ <reg name="fa3" bitsize="64" type="riscv_double"/>
+ <reg name="fa4" bitsize="64" type="riscv_double"/>
+ <reg name="fa5" bitsize="64" type="riscv_double"/>
+ <reg name="fa6" bitsize="64" type="riscv_double"/>
+ <reg name="fa7" bitsize="64" type="riscv_double"/>
+ <reg name="fs2" bitsize="64" type="riscv_double"/>
+ <reg name="fs3" bitsize="64" type="riscv_double"/>
+ <reg name="fs4" bitsize="64" type="riscv_double"/>
+ <reg name="fs5" bitsize="64" type="riscv_double"/>
+ <reg name="fs6" bitsize="64" type="riscv_double"/>
+ <reg name="fs7" bitsize="64" type="riscv_double"/>
+ <reg name="fs8" bitsize="64" type="riscv_double"/>
+ <reg name="fs9" bitsize="64" type="riscv_double"/>
+ <reg name="fs10" bitsize="64" type="riscv_double"/>
+ <reg name="fs11" bitsize="64" type="riscv_double"/>
+ <reg name="ft8" bitsize="64" type="riscv_double"/>
+ <reg name="ft9" bitsize="64" type="riscv_double"/>
+ <reg name="ft10" bitsize="64" type="riscv_double"/>
+ <reg name="ft11" bitsize="64" type="riscv_double"/>
+
+ <reg name="fflags" bitsize="32" type="int" regnum="66"/>
+ <reg name="frm" bitsize="32" type="int" regnum="67"/>
+ <reg name="fcsr" bitsize="32" type="int" regnum="68"/>
+</feature>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>riscv</architecture>
+ <xi:include href="riscv64-cpu.xml"/>
+ <xi:include href="riscv64-fpu.xml"/>
+ <xi:include href="riscv64-cpu-valgrind-s1.xml"/>
+ <xi:include href="riscv64-fpu-valgrind-s1.xml"/>
+ <xi:include href="riscv64-cpu-valgrind-s2.xml"/>
+ <xi:include href="riscv64-fpu-valgrind-s2.xml"/>
+
+ <feature name="org.gnu.gdb.riscv.linux">
+ <reg name="restart" bitsize="64" group="system"/>
+ </feature>
+</target>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>riscv</architecture>
+ <xi:include href="riscv64-cpu.xml"/>
+ <xi:include href="riscv64-fpu.xml"/>
+
+ <feature name="org.gnu.gdb.riscv.linux">
+ <reg name="restart" bitsize="64" group="system"/>
+ </feature>
+</target>
\ No newline at end of file
--- /dev/null
+/* Low level interface to valgrind, for the remote server for GDB integrated
+ in valgrind.
+ Copyright (C) 2022
+ Free Software Foundation, Inc.
+
+ This file is part of VALGRIND.
+ It has been inspired from a file from gdbserver in gdb 6.6.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "server.h"
+#include "target.h"
+#include "regdef.h"
+#include "regcache.h"
+
+#include "pub_core_machine.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_transtab.h"
+#include "pub_core_gdbserver.h"
+#include "pub_core_debuginfo.h"
+
+#include "valgrind_low.h"
+
+#include "libvex_guest_riscv64.h"
+
+/* from GDB gdb/features/riscv/64bit-{cpu,fpu}.c */
+static struct reg regs[] = {
+ { "zero", 0, 64 },
+ { "ra", 64, 64 },
+ { "sp", 128, 64 },
+ { "gp", 192, 64 },
+ { "tp", 256, 64 },
+ { "t0", 320, 64 },
+ { "t1", 384, 64 },
+ { "t2", 448, 64 },
+ { "fp", 512, 64 },
+ { "s1", 576, 64 },
+ { "a0", 640, 64 },
+ { "a1", 704, 64 },
+ { "a2", 768, 64 },
+ { "a3", 832, 64 },
+ { "a4", 896, 64 },
+ { "a5", 960, 64 },
+ { "a6", 1024, 64 },
+ { "a7", 1088, 64 },
+ { "s2", 1152, 64 },
+ { "s3", 1216, 64 },
+ { "s4", 1280, 64 },
+ { "s5", 1344, 64 },
+ { "s6", 1408, 64 },
+ { "s7", 1472, 64 },
+ { "s8", 1536, 64 },
+ { "s9", 1600, 64 },
+ { "s10", 1664, 64 },
+ { "s11", 1728, 64 },
+ { "t3", 1792, 64 },
+ { "t4", 1856, 64 },
+ { "t5", 1920, 64 },
+ { "t6", 1984, 64 },
+ { "pc", 2048, 64 },
+
+ { "ft0", 2112, 64 },
+ { "ft1", 2176, 64 },
+ { "ft2", 2240, 64 },
+ { "ft3", 2304, 64 },
+ { "ft4", 2368, 64 },
+ { "ft5", 2432, 64 },
+ { "ft6", 2496, 64 },
+ { "ft7", 2560, 64 },
+ { "fs0", 2624, 64 },
+ { "fs1", 2688, 64 },
+ { "fa0", 2752, 64 },
+ { "fa1", 2816, 64 },
+ { "fa2", 2880, 64 },
+ { "fa3", 2944, 64 },
+ { "fa4", 3008, 64 },
+ { "fa5", 3072, 64 },
+ { "fa6", 3136, 64 },
+ { "fa7", 3200, 64 },
+ { "fs2", 3264, 64 },
+ { "fs3", 3328, 64 },
+ { "fs4", 3392, 64 },
+ { "fs5", 3456, 64 },
+ { "fs6", 3520, 64 },
+ { "fs7", 3584, 64 },
+ { "fs8", 3648, 64 },
+ { "fs9", 3712, 64 },
+ { "fs10", 3776, 64 },
+ { "fs11", 3840, 64 },
+ { "ft8", 3904, 64 },
+ { "ft9", 3968, 64 },
+ { "ft10", 4032, 64 },
+ { "ft11", 4096, 64 },
+ { "", 4160, 0 }, /* regnums have a hole here */
+ { "fflags", 4160, 32 },
+ { "frm", 4192, 32 },
+ { "fcsr", 4224, 32 },
+};
+
+/* from GDB gdbserver/linux-riscv-low.cc */
+static const char *expedite_regs[] = { "sp", "pc", 0 };
+
+#define num_regs (sizeof (regs) / sizeof (regs[0]))
+
+static
+CORE_ADDR get_pc (void)
+{
+ unsigned long pc;
+
+ collect_register_by_name ("pc", &pc);
+
+ dlog(1, "stop pc is %p\n", (void *) pc);
+ return pc;
+}
+
+static
+void set_pc (CORE_ADDR newpc)
+{
+ supply_register_by_name ("pc", &newpc);
+}
+
+/* store registers in the guest state (gdbserver_to_valgrind)
+ or fetch register from the guest state (valgrind_to_gdbserver). */
+static
+void transfer_register (ThreadId tid, int abs_regno, void * buf,
+ transfer_direction dir, int size, Bool *mod)
+{
+ ThreadState* tst = VG_(get_ThreadState)(tid);
+ int set = abs_regno / num_regs;
+ int regno = abs_regno % num_regs;
+ *mod = False;
+ UInt v, *p;
+
+ VexGuestRISCV64State* riscv = (VexGuestRISCV64State*) get_arch (set, tst);
+
+ switch (regno) {
+ // numbers here have to match the order of regs above
+ // Attention: gdb order does not match valgrind order.
+ case 0: VG_(transfer) (&riscv->guest_x0, buf, dir, size, mod); break;
+ case 1: VG_(transfer) (&riscv->guest_x1, buf, dir, size, mod); break;
+ case 2: VG_(transfer) (&riscv->guest_x2, buf, dir, size, mod); break;
+ case 3: VG_(transfer) (&riscv->guest_x3, buf, dir, size, mod); break;
+ case 4: VG_(transfer) (&riscv->guest_x4, buf, dir, size, mod); break;
+ case 5: VG_(transfer) (&riscv->guest_x5, buf, dir, size, mod); break;
+ case 6: VG_(transfer) (&riscv->guest_x6, buf, dir, size, mod); break;
+ case 7: VG_(transfer) (&riscv->guest_x7, buf, dir, size, mod); break;
+ case 8: VG_(transfer) (&riscv->guest_x8, buf, dir, size, mod); break;
+ case 9: VG_(transfer) (&riscv->guest_x9, buf, dir, size, mod); break;
+ case 10: VG_(transfer) (&riscv->guest_x10, buf, dir, size, mod); break;
+ case 11: VG_(transfer) (&riscv->guest_x11, buf, dir, size, mod); break;
+ case 12: VG_(transfer) (&riscv->guest_x12, buf, dir, size, mod); break;
+ case 13: VG_(transfer) (&riscv->guest_x13, buf, dir, size, mod); break;
+ case 14: VG_(transfer) (&riscv->guest_x14, buf, dir, size, mod); break;
+ case 15: VG_(transfer) (&riscv->guest_x15, buf, dir, size, mod); break;
+ case 16: VG_(transfer) (&riscv->guest_x16, buf, dir, size, mod); break;
+ case 17: VG_(transfer) (&riscv->guest_x17, buf, dir, size, mod); break;
+ case 18: VG_(transfer) (&riscv->guest_x18, buf, dir, size, mod); break;
+ case 19: VG_(transfer) (&riscv->guest_x19, buf, dir, size, mod); break;
+ case 20: VG_(transfer) (&riscv->guest_x20, buf, dir, size, mod); break;
+ case 21: VG_(transfer) (&riscv->guest_x21, buf, dir, size, mod); break;
+ case 22: VG_(transfer) (&riscv->guest_x22, buf, dir, size, mod); break;
+ case 23: VG_(transfer) (&riscv->guest_x23, buf, dir, size, mod); break;
+ case 24: VG_(transfer) (&riscv->guest_x24, buf, dir, size, mod); break;
+ case 25: VG_(transfer) (&riscv->guest_x25, buf, dir, size, mod); break;
+ case 26: VG_(transfer) (&riscv->guest_x26, buf, dir, size, mod); break;
+ case 27: VG_(transfer) (&riscv->guest_x27, buf, dir, size, mod); break;
+ case 28: VG_(transfer) (&riscv->guest_x28, buf, dir, size, mod); break;
+ case 29: VG_(transfer) (&riscv->guest_x29, buf, dir, size, mod); break;
+ case 30: VG_(transfer) (&riscv->guest_x30, buf, dir, size, mod); break;
+ case 31: VG_(transfer) (&riscv->guest_x31, buf, dir, size, mod); break;
+ case 32: VG_(transfer) (&riscv->guest_pc, buf, dir, size, mod); break;
+
+ case 33: VG_(transfer) (&riscv->guest_f0, buf, dir, size, mod); break;
+ case 34: VG_(transfer) (&riscv->guest_f1, buf, dir, size, mod); break;
+ case 35: VG_(transfer) (&riscv->guest_f2, buf, dir, size, mod); break;
+ case 36: VG_(transfer) (&riscv->guest_f3, buf, dir, size, mod); break;
+ case 37: VG_(transfer) (&riscv->guest_f4, buf, dir, size, mod); break;
+ case 38: VG_(transfer) (&riscv->guest_f5, buf, dir, size, mod); break;
+ case 39: VG_(transfer) (&riscv->guest_f6, buf, dir, size, mod); break;
+ case 40: VG_(transfer) (&riscv->guest_f7, buf, dir, size, mod); break;
+ case 41: VG_(transfer) (&riscv->guest_f8, buf, dir, size, mod); break;
+ case 42: VG_(transfer) (&riscv->guest_f9, buf, dir, size, mod); break;
+ case 43: VG_(transfer) (&riscv->guest_f10, buf, dir, size, mod); break;
+ case 44: VG_(transfer) (&riscv->guest_f11, buf, dir, size, mod); break;
+ case 45: VG_(transfer) (&riscv->guest_f12, buf, dir, size, mod); break;
+ case 46: VG_(transfer) (&riscv->guest_f13, buf, dir, size, mod); break;
+ case 47: VG_(transfer) (&riscv->guest_f14, buf, dir, size, mod); break;
+ case 48: VG_(transfer) (&riscv->guest_f15, buf, dir, size, mod); break;
+ case 49: VG_(transfer) (&riscv->guest_f16, buf, dir, size, mod); break;
+ case 50: VG_(transfer) (&riscv->guest_f17, buf, dir, size, mod); break;
+ case 51: VG_(transfer) (&riscv->guest_f18, buf, dir, size, mod); break;
+ case 52: VG_(transfer) (&riscv->guest_f19, buf, dir, size, mod); break;
+ case 53: VG_(transfer) (&riscv->guest_f20, buf, dir, size, mod); break;
+ case 54: VG_(transfer) (&riscv->guest_f21, buf, dir, size, mod); break;
+ case 55: VG_(transfer) (&riscv->guest_f22, buf, dir, size, mod); break;
+ case 56: VG_(transfer) (&riscv->guest_f23, buf, dir, size, mod); break;
+ case 57: VG_(transfer) (&riscv->guest_f24, buf, dir, size, mod); break;
+ case 58: VG_(transfer) (&riscv->guest_f25, buf, dir, size, mod); break;
+ case 59: VG_(transfer) (&riscv->guest_f26, buf, dir, size, mod); break;
+ case 60: VG_(transfer) (&riscv->guest_f27, buf, dir, size, mod); break;
+ case 61: VG_(transfer) (&riscv->guest_f28, buf, dir, size, mod); break;
+ case 62: VG_(transfer) (&riscv->guest_f29, buf, dir, size, mod); break;
+ case 63: VG_(transfer) (&riscv->guest_f30, buf, dir, size, mod); break;
+ case 64: VG_(transfer) (&riscv->guest_f31, buf, dir, size, mod); break;
+
+ case 65: break;
+
+ case 66: /* fflags = fcsr & 0x1F */
+ p = &riscv->guest_fcsr;
+ if (dir == valgrind_to_gdbserver)
+ v = *p & 0x1F;
+ VG_(transfer) (&v, buf, dir, size, mod);
+ if (dir == gdbserver_to_valgrind)
+ *p = (*p & ~0x1F) | v;
+ break;
+
+ case 67: /* frm = (fcsr & 0xE0) >> 5 */
+ p = &riscv->guest_fcsr;
+ if (dir == valgrind_to_gdbserver)
+ v = (*p & 0xE0) >> 5;
+ VG_(transfer) (&v, buf, dir, size, mod);
+ if (dir == gdbserver_to_valgrind)
+ *p = (*p & ~0xE0) | (v << 5);
+ break;
+
+ case 68: VG_(transfer) (&riscv->guest_fcsr, buf, dir, size, mod); break;
+ default: vg_assert(0);
+ }
+}
+
+static
+const char* target_xml (Bool shadow_mode)
+{
+ if (shadow_mode) {
+ return "riscv64-linux-valgrind.xml";
+ } else {
+ return "riscv64-linux.xml";
+ }
+}
+
+static CORE_ADDR** target_get_dtv (ThreadState *tst)
+{
+ VexGuestRISCV64State* riscv = (VexGuestRISCV64State*)&tst->arch.vex;
+
+ /* RISC-V uses Variant I as described by the ELF TLS specification,
+ with tp containing the address one past the end of the TCB.
+
+ from GLIBC sysdeps/riscv/nptl/tls.h, tp is just after tcbhead_t
+ typedef struct {
+ dtv_t *dtv;
+ void *private;
+ } tcbhead_t;
+ */
+ return (CORE_ADDR**)(void *)(riscv->guest_x4 - 2 * sizeof(void *));
+}
+
+static struct valgrind_target_ops low_target = {
+ num_regs,
+ 2, //SP
+ regs,
+ transfer_register,
+ get_pc,
+ set_pc,
+ "riscv64",
+ target_xml,
+ target_get_dtv
+};
+
+void riscv64_init_architecture (struct valgrind_target_ops *target)
+{
+ *target = low_target;
+ set_register_cache (regs, num_regs);
+ gdbserver_expedite_regs = expedite_regs;
+}
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames. ---*/
+/*--- sigframe-riscv64-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_riscv64_linux)
+
+#include "libvex_guest_offsets.h"
+#include "priv_sigframe.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_basics.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_signals.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+#include "pub_core_vki.h"
+
+/*------------------------------------------------------------*/
+/*--- Signal frame layout ---*/
+/*------------------------------------------------------------*/
+
+/* Valgrind-specific parts of the signal frame. */
+struct vg_sigframe {
+ /* Sanity check word. */
+ UInt magicPI;
+
+ /* Safely-saved version of sigNo. */
+ Int sigNo_private;
+
+ /* Sanity check word. */
+ UInt magicE;
+};
+
+/* Complete signal frame. */
+struct rt_sigframe {
+ struct vki_siginfo info;
+ struct vki_ucontext uc;
+ struct vg_sigframe vg;
+};
+
+/*------------------------------------------------------------*/
+/*--- Creating a signal frame ---*/
+/*------------------------------------------------------------*/
+
+static void synth_ucontext(ThreadState* tst,
+ const vki_siginfo_t* si,
+ const vki_sigset_t* set,
+ struct vki_ucontext* uc)
+{
+ VG_(memset)(uc, 0, sizeof(*uc));
+
+ /* Prepare common data. */
+ uc->uc_flags = 0;
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&uc->uc_flags,
+ sizeof(uc->uc_flags));
+ uc->uc_link = 0;
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&uc->uc_link,
+ sizeof(uc->uc_link));
+ uc->uc_sigmask = *set;
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&uc->uc_sigmask,
+ sizeof(uc->uc_sigmask));
+ uc->uc_stack = tst->altstack;
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&uc->uc_stack,
+ sizeof(uc->uc_stack));
+
+ struct vki_sigcontext* sc = &uc->uc_mcontext;
+
+ /* Save integer registers. */
+#define IREG_TO_CTX(ureg, vreg) \
+ sc->sc_regs.ureg = tst->arch.vex.guest_##vreg; \
+ VG_TRACK(copy_reg_to_mem, Vg_CoreSignal, tst->tid, OFFSET_riscv64_##vreg, \
+ (Addr)&sc->sc_regs.ureg, sizeof(UWord));
+ IREG_TO_CTX(pc, pc);
+ IREG_TO_CTX(ra, x1);
+ IREG_TO_CTX(sp, x2);
+ IREG_TO_CTX(gp, x3);
+ IREG_TO_CTX(tp, x4);
+ IREG_TO_CTX(t0, x5);
+ IREG_TO_CTX(t1, x6);
+ IREG_TO_CTX(t2, x7);
+ IREG_TO_CTX(s0, x8);
+ IREG_TO_CTX(s1, x9);
+ IREG_TO_CTX(a0, x10);
+ IREG_TO_CTX(a1, x11);
+ IREG_TO_CTX(a2, x12);
+ IREG_TO_CTX(a3, x13);
+ IREG_TO_CTX(a4, x14);
+ IREG_TO_CTX(a5, x15);
+ IREG_TO_CTX(a6, x16);
+ IREG_TO_CTX(a7, x17);
+ IREG_TO_CTX(s2, x18);
+ IREG_TO_CTX(s3, x19);
+ IREG_TO_CTX(s4, x20);
+ IREG_TO_CTX(s5, x21);
+ IREG_TO_CTX(s6, x22);
+ IREG_TO_CTX(s7, x23);
+ IREG_TO_CTX(s8, x24);
+ IREG_TO_CTX(s9, x25);
+ IREG_TO_CTX(s10, x26);
+ IREG_TO_CTX(s11, x27);
+ IREG_TO_CTX(t3, x28);
+ IREG_TO_CTX(t4, x29);
+ IREG_TO_CTX(t5, x30);
+ IREG_TO_CTX(t6, x31);
+#undef IREG_TO_CTX
+
+ /* Save floating point registers. */
+#define FREG_TO_CTX(ureg, vreg, type) \
+ sc->sc_fpregs.d.ureg = tst->arch.vex.guest_##vreg; \
+ VG_TRACK(copy_reg_to_mem, Vg_CoreSignal, tst->tid, OFFSET_riscv64_##vreg, \
+ (Addr)&sc->sc_fpregs.d.ureg, sizeof(type));
+ FREG_TO_CTX(f[0], f0, UWord);
+ FREG_TO_CTX(f[1], f1, UWord);
+ FREG_TO_CTX(f[2], f2, UWord);
+ FREG_TO_CTX(f[3], f3, UWord);
+ FREG_TO_CTX(f[4], f4, UWord);
+ FREG_TO_CTX(f[5], f5, UWord);
+ FREG_TO_CTX(f[6], f6, UWord);
+ FREG_TO_CTX(f[7], f7, UWord);
+ FREG_TO_CTX(f[8], f8, UWord);
+ FREG_TO_CTX(f[9], f9, UWord);
+ FREG_TO_CTX(f[10], f10, UWord);
+ FREG_TO_CTX(f[11], f11, UWord);
+ FREG_TO_CTX(f[12], f12, UWord);
+ FREG_TO_CTX(f[13], f13, UWord);
+ FREG_TO_CTX(f[14], f14, UWord);
+ FREG_TO_CTX(f[15], f15, UWord);
+ FREG_TO_CTX(f[16], f16, UWord);
+ FREG_TO_CTX(f[17], f17, UWord);
+ FREG_TO_CTX(f[18], f18, UWord);
+ FREG_TO_CTX(f[19], f19, UWord);
+ FREG_TO_CTX(f[20], f20, UWord);
+ FREG_TO_CTX(f[21], f21, UWord);
+ FREG_TO_CTX(f[22], f22, UWord);
+ FREG_TO_CTX(f[23], f23, UWord);
+ FREG_TO_CTX(f[24], f24, UWord);
+ FREG_TO_CTX(f[25], f25, UWord);
+ FREG_TO_CTX(f[26], f26, UWord);
+ FREG_TO_CTX(f[27], f27, UWord);
+ FREG_TO_CTX(f[28], f28, UWord);
+ FREG_TO_CTX(f[29], f29, UWord);
+ FREG_TO_CTX(f[30], f30, UWord);
+ FREG_TO_CTX(f[31], f31, UWord);
+ FREG_TO_CTX(fcsr, fcsr, UInt);
+#undef FREG_TO_CTX
+}
+
+/* Build the Valgrind-specific part of a signal frame. */
+static void build_vg_sigframe(struct vg_sigframe* frame, Int sigNo)
+{
+ frame->magicPI = 0x31415927;
+ frame->sigNo_private = sigNo;
+ frame->magicE = 0x27182818;
+}
+
+static Addr build_rt_sigframe(ThreadState* tst,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t* siginfo,
+ UInt flags,
+ const vki_sigset_t* mask)
+{
+ SizeT size = sizeof(struct rt_sigframe);
+ Addr sp = VG_ROUNDDN(sp_top_of_frame - size, 16);
+
+ if (!ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
+ return sp_top_of_frame;
+
+ /* Tell the tools that the sigframe is to be written. */
+ VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", sp,
+ sizeof(struct rt_sigframe));
+
+ struct rt_sigframe* frame = (struct rt_sigframe*)sp;
+
+ /* Fill in the siginfo. */
+ frame->info = *siginfo;
+
+ /* SIGILL defines addr to be the faulting address. */
+ Int sigNo = siginfo->si_signo;
+ if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
+ frame->info._sifields._sigfault._addr = (void*)VG_(get_IP)(tst->tid);
+
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&frame->info,
+ sizeof(frame->info));
+
+ /* Fill in the ucontext. */
+ synth_ucontext(tst, siginfo, mask, &frame->uc);
+
+ /* Fill in the Valgrind-specific part. */
+ build_vg_sigframe(&frame->vg, sigNo);
+
+ return sp;
+}
+
+void VG_(sigframe_create)(ThreadId tid,
+ Bool on_altstack,
+ Addr rsp_top_of_frame,
+ const vki_siginfo_t* siginfo,
+ const struct vki_ucontext* siguc,
+ void* handler,
+ UInt flags,
+ const vki_sigset_t* mask,
+ void* restorer)
+{
+ /* The restorer functionality (SA_RESTORER) is not used on riscv64-linux. */
+ vg_assert(restorer == NULL);
+
+ ThreadState* tst = VG_(get_ThreadState)(tid);
+
+ /* Build the signal frame on the stack. */
+ Addr sp = build_rt_sigframe(tst, rsp_top_of_frame, siginfo, flags, mask);
+ struct rt_sigframe* frame = (struct rt_sigframe*)sp;
+
+ /* Configure guest registers for the signal delivery. */
+ VG_(set_SP)(tid, sp);
+ VG_TRACK(post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(UWord));
+
+ tst->arch.vex.guest_x10 = siginfo->si_signo;
+ VG_TRACK(post_reg_write, Vg_CoreSignal, tst->tid, OFFSET_riscv64_x10,
+ sizeof(UWord));
+ tst->arch.vex.guest_x11 = (Addr)&frame->info;
+ VG_TRACK(post_reg_write, Vg_CoreSignal, tst->tid, OFFSET_riscv64_x11,
+ sizeof(UWord));
+ tst->arch.vex.guest_x12 = (Addr)&frame->uc;
+ VG_TRACK(post_reg_write, Vg_CoreSignal, tst->tid, OFFSET_riscv64_x12,
+ sizeof(UWord));
+
+ tst->arch.vex.guest_x1 = (Addr)&VG_(riscv64_linux_SUBST_FOR_rt_sigreturn);
+ VG_TRACK(post_reg_write, Vg_CoreSignal, tst->tid, OFFSET_riscv64_x1,
+ sizeof(UWord));
+
+ /* Set up the program counter. Note that it is not necessary to inform the
+ tools about this write because pc is always defined. */
+ VG_(set_IP)(tid, (Addr)handler);
+
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg,
+ "sigframe_create (thread %u): next pc=%#lx, next sp=%#lx\n",
+ tid, (Addr)handler, sp);
+}
+
+/*------------------------------------------------------------*/
+/*--- Destroying a signal frame ---*/
+/*------------------------------------------------------------*/
+
+/* Restore the Valgrind-specific part of a signal frame. The returned value
+ indicates whether the frame is valid. If not then nothing is restored and the
+ client is set to take a segfault. */
+static Bool
+restore_vg_sigframe(ThreadState* tst, struct vg_sigframe* frame, Int* sigNo)
+{
+ if (frame->magicPI != 0x31415927 || frame->magicE != 0x27182818) {
+ VG_(message)(
+ Vg_UserMsg,
+ "Thread %u return signal frame corrupted. Killing process.\n",
+ tst->tid);
+ VG_(set_default_handler)(VKI_SIGSEGV);
+ VG_(synth_fault)(tst->tid);
+ *sigNo = VKI_SIGSEGV;
+ return False;
+ }
+ *sigNo = frame->sigNo_private;
+ return True;
+}
+
+static void restore_ucontext(ThreadState* tst, struct vki_ucontext* uc)
+{
+ /* Restore common data. */
+ VG_TRACK(pre_mem_read, Vg_CoreSignal, tst->tid, "signal frame mask",
+ (Addr)&uc->uc_sigmask, sizeof(uc->uc_sigmask));
+ tst->sig_mask = uc->uc_sigmask;
+ tst->tmp_sig_mask = tst->sig_mask;
+
+ struct vki_sigcontext* sc = &uc->uc_mcontext;
+
+ /* Restore integer registers. */
+#define IREG_FROM_CTX(ureg, vreg) \
+ tst->arch.vex.guest_##vreg = sc->sc_regs.ureg; \
+ VG_TRACK(copy_mem_to_reg, Vg_CoreSignal, tst->tid, (Addr)&sc->sc_regs.ureg, \
+ OFFSET_riscv64_##vreg, sizeof(UWord));
+ IREG_FROM_CTX(pc, pc);
+ IREG_FROM_CTX(ra, x1);
+ IREG_FROM_CTX(sp, x2);
+ IREG_FROM_CTX(gp, x3);
+ IREG_FROM_CTX(tp, x4);
+ IREG_FROM_CTX(t0, x5);
+ IREG_FROM_CTX(t1, x6);
+ IREG_FROM_CTX(t2, x7);
+ IREG_FROM_CTX(s0, x8);
+ IREG_FROM_CTX(s1, x9);
+ IREG_FROM_CTX(a0, x10);
+ IREG_FROM_CTX(a1, x11);
+ IREG_FROM_CTX(a2, x12);
+ IREG_FROM_CTX(a3, x13);
+ IREG_FROM_CTX(a4, x14);
+ IREG_FROM_CTX(a5, x15);
+ IREG_FROM_CTX(a6, x16);
+ IREG_FROM_CTX(a7, x17);
+ IREG_FROM_CTX(s2, x18);
+ IREG_FROM_CTX(s3, x19);
+ IREG_FROM_CTX(s4, x20);
+ IREG_FROM_CTX(s5, x21);
+ IREG_FROM_CTX(s6, x22);
+ IREG_FROM_CTX(s7, x23);
+ IREG_FROM_CTX(s8, x24);
+ IREG_FROM_CTX(s9, x25);
+ IREG_FROM_CTX(s10, x26);
+ IREG_FROM_CTX(s11, x27);
+ IREG_FROM_CTX(t3, x28);
+ IREG_FROM_CTX(t4, x29);
+ IREG_FROM_CTX(t5, x30);
+ IREG_FROM_CTX(t6, x31);
+#undef IREG_FROM_CTX
+
+ /* Restore floating point registers. */
+#define FREG_FROM_CTX(ureg, vreg, type) \
+ tst->arch.vex.guest_##vreg = sc->sc_fpregs.d.ureg; \
+ VG_TRACK(copy_mem_to_reg, Vg_CoreSignal, tst->tid, \
+ (Addr)&sc->sc_fpregs.d.ureg, OFFSET_riscv64_##vreg, sizeof(type));
+ FREG_FROM_CTX(f[0], f0, UWord);
+ FREG_FROM_CTX(f[1], f1, UWord);
+ FREG_FROM_CTX(f[2], f2, UWord);
+ FREG_FROM_CTX(f[3], f3, UWord);
+ FREG_FROM_CTX(f[4], f4, UWord);
+ FREG_FROM_CTX(f[5], f5, UWord);
+ FREG_FROM_CTX(f[6], f6, UWord);
+ FREG_FROM_CTX(f[7], f7, UWord);
+ FREG_FROM_CTX(f[8], f8, UWord);
+ FREG_FROM_CTX(f[9], f9, UWord);
+ FREG_FROM_CTX(f[10], f10, UWord);
+ FREG_FROM_CTX(f[11], f11, UWord);
+ FREG_FROM_CTX(f[12], f12, UWord);
+ FREG_FROM_CTX(f[13], f13, UWord);
+ FREG_FROM_CTX(f[14], f14, UWord);
+ FREG_FROM_CTX(f[15], f15, UWord);
+ FREG_FROM_CTX(f[16], f16, UWord);
+ FREG_FROM_CTX(f[17], f17, UWord);
+ FREG_FROM_CTX(f[18], f18, UWord);
+ FREG_FROM_CTX(f[19], f19, UWord);
+ FREG_FROM_CTX(f[20], f20, UWord);
+ FREG_FROM_CTX(f[21], f21, UWord);
+ FREG_FROM_CTX(f[22], f22, UWord);
+ FREG_FROM_CTX(f[23], f23, UWord);
+ FREG_FROM_CTX(f[24], f24, UWord);
+ FREG_FROM_CTX(f[25], f25, UWord);
+ FREG_FROM_CTX(f[26], f26, UWord);
+ FREG_FROM_CTX(f[27], f27, UWord);
+ FREG_FROM_CTX(f[28], f28, UWord);
+ FREG_FROM_CTX(f[29], f29, UWord);
+ FREG_FROM_CTX(f[30], f30, UWord);
+ FREG_FROM_CTX(f[31], f31, UWord);
+ FREG_FROM_CTX(fcsr, fcsr, UInt);
+#undef FREG_FROM_CTX
+}
+
+static void
+restore_rt_sigframe(ThreadState* tst, struct rt_sigframe* frame, Int* sigNo)
+{
+ if (restore_vg_sigframe(tst, &frame->vg, sigNo))
+ restore_ucontext(tst, &frame->uc);
+}
+
+void VG_(sigframe_destroy)(ThreadId tid, Bool isRT)
+{
+ /* Non-rt sigreturn does not exist on riscv64-linux. */
+ vg_assert(isRT);
+
+ ThreadState* tst = VG_(get_ThreadState)(tid);
+
+ /* Correctly reestablish the frame base address. */
+ Addr sp = VG_(get_SP)(tid);
+
+ /* Restore a state from the signal frame. */
+ Int sigNo;
+ restore_rt_sigframe(tst, (struct rt_sigframe*)sp, &sigNo);
+
+ VG_TRACK(die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
+ sizeof(struct rt_sigframe) + VG_STACK_REDZONE_SZB);
+
+ /* Returning from a signal handler. */
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg, "sigframe_return (thread %u): pc=%#lx\n", tid,
+ VG_(get_IP)(tid));
+
+ /* Tell the tools. */
+ VG_TRACK(post_deliver_signal, tid, sigNo);
+}
+
+#endif // defined(VGP_riscv64_linux)
+
+/*--------------------------------------------------------------------*/
+/*--- end sigframe-riscv64-linux.c ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- Support for doing system calls. syscall-riscv64-linux.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+
+#if defined(VGP_riscv64_linux)
+
+#include "pub_core_vkiscnums_asm.h"
+#include "libvex_guest_offsets.h"
+
+
+/*----------------------------------------------------------------*/
+/*
+ Perform a syscall for the client. This will run a syscall
+ with the client's specific per-thread signal mask.
+
+ The structure of this function is such that, if the syscall is
+ interrupted by a signal, we can determine exactly what
+ execution state we were in with respect to the execution of
+ the syscall by examining the value of pc in the signal
+ handler. This means that we can always do the appropriate
+ thing to precisely emulate the kernel's signal/syscall
+ interactions.
+
+ The syscall number is taken from the argument, even though it
+ should also be in guest_state->guest_x17. The syscall result
+ is written back to guest_state->guest_x10 on completion.
+
+ Returns 0 if the syscall was successfully called (even if the
+ syscall itself failed), or a nonzero error code in the lowest
+ 8 bits if one of the sigprocmasks failed (there's no way to
+ determine which one failed). And there's no obvious way to
+ recover from that either, but nevertheless we want to know.
+
+ VG_(fixup_guest_state_after_syscall_interrupted) does the
+ thread state fixup in the case where we were interrupted by a
+ signal.
+
+ Prototype:
+
+ UWord ML_(do_syscall_for_client_WRK)(
+ Int syscallno, // a0
+ void* guest_state, // a1
+ const vki_sigset_t *sysmask, // a2
+ const vki_sigset_t *postmask, // a3
+ Int nsigwords) // a4
+*/
+/* from vki-riscv64-linux.h */
+#define VKI_SIG_SETMASK 2
+
+.globl ML_(do_syscall_for_client_WRK)
+ML_(do_syscall_for_client_WRK):
+
+ /* Stash callee-saves and our args on the stack */
+ addi sp, sp, -144
+ sd ra, 136(sp)
+ sd s0, 128(sp)
+ sd s1, 120(sp)
+ sd s2, 112(sp)
+ sd s3, 104(sp)
+ sd s4, 96(sp)
+ sd s5, 88(sp)
+ sd s6, 80(sp)
+ sd s7, 72(sp)
+ sd s8, 64(sp)
+ sd s9, 56(sp)
+ sd s10, 48(sp)
+ sd s11, 40(sp)
+ sd a0, 32(sp)
+ sd a1, 24(sp)
+ sd a2, 16(sp)
+ sd a3, 8(sp)
+ sd a4, 0(sp)
+
+1:
+
+ li a7, __NR_rt_sigprocmask
+ li a0, VKI_SIG_SETMASK
+ mv a1, a2 /* sysmask */
+ mv a2, a3 /* postmask */
+ mv a3, a4 /* nsigwords */
+ ecall
+
+
+ ld a5, 24(sp) /* saved a1 == guest_state */
+
+ ld a7, 32(sp) /* saved a0 == syscall# */
+ ld a0, OFFSET_riscv64_x10(a5)
+ ld a1, OFFSET_riscv64_x11(a5)
+ ld a2, OFFSET_riscv64_x12(a5)
+ ld a3, OFFSET_riscv64_x13(a5)
+ ld a4, OFFSET_riscv64_x14(a5)
+ ld a5, OFFSET_riscv64_x15(a5)
+
+2: ecall
+3:
+ ld a5, 24(sp) /* saved a1 == guest_state */
+ sd a0, OFFSET_riscv64_x10(a5)
+
+4:
+ li a7, __NR_rt_sigprocmask
+ li a0, VKI_SIG_SETMASK
+ ld a1, 8(sp) /* saved a3 == postmask */
+ li a2, 0
+ ld a3, 0(sp) /* saved a4 == nsigwords */
+ ecall
+
+ bltz x0, 7f
+
+5: /* Success: return zero */
+ li a0, 0
+ ld ra, 136(sp)
+ ld s0, 128(sp)
+ ld s1, 120(sp)
+ ld s2, 112(sp)
+ ld s3, 104(sp)
+ ld s4, 96(sp)
+ ld s5, 88(sp)
+ ld s6, 80(sp)
+ ld s7, 72(sp)
+ ld s8, 64(sp)
+ ld s9, 56(sp)
+ ld s10, 48(sp)
+ ld s11, 40(sp)
+ addi sp, sp, 144
+ ret
+
+7: /* Failure: return 0x8000 | error code */
+ li a1, 0x8000
+ or a0, a0, a1
+ ld ra, 136(sp)
+ ld s0, 128(sp)
+ ld s1, 120(sp)
+ ld s2, 112(sp)
+ ld s3, 104(sp)
+ ld s4, 96(sp)
+ ld s5, 88(sp)
+ ld s6, 80(sp)
+ ld s7, 72(sp)
+ ld s8, 64(sp)
+ ld s9, 56(sp)
+ ld s10, 48(sp)
+ ld s11, 40(sp)
+ addi sp, sp, 144
+ ret
+
+
+
+.section .rodata
+/* export the ranges so that
+ VG_(fixup_guest_state_after_syscall_interrupted) can do the
+ right thing */
+
+.align 3
+.globl ML_(blksys_setup)
+.globl ML_(blksys_restart)
+.globl ML_(blksys_complete)
+.globl ML_(blksys_committed)
+.globl ML_(blksys_finished)
+ML_(blksys_setup): .quad 1b
+ML_(blksys_restart): .quad 2b
+ML_(blksys_complete): .quad 3b
+ML_(blksys_committed): .quad 4b
+ML_(blksys_finished): .quad 5b
+
+#endif // defined(VGP_riscv64_linux)
+
+/* Let the linker know we don't need an executable stack */
+MARK_STACK_NO_EXEC
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- Platform-specific syscalls stuff. syswrap-riscv64-linux.c -----*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_riscv64_linux)
+
+#include "pub_core_basics.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_options.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_stacktrace.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_transtab.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+
+#include "priv_syswrap-generic.h"
+#include "priv_syswrap-linux.h"
+#include "priv_types_n_macros.h"
+
+/* ---------------------------------------------------------------------
+ clone() handling
+ ------------------------------------------------------------------ */
+
+/* Call f(arg1), but first switch stacks, using 'stack' as the new stack, and
+ use 'retaddr' as f's return-to address. Also, clear all the integer registers
+ before entering f.*/
+__attribute__((noreturn)) void ML_(call_on_new_stack_0_1)(Addr stack,
+ Addr retaddr,
+ void (*f)(Word),
+ Word arg1);
+/* a0 = stack
+ a1 = retaddr
+ a2 = f
+ a3 = arg1 */
+asm(".text\n"
+ ".globl vgModuleLocal_call_on_new_stack_0_1\n"
+ "vgModuleLocal_call_on_new_stack_0_1:\n"
+ "mv sp, a0\n" /* Set the stack pointer. */
+ "mv ra, a1\n" /* Set the return address. */
+ "mv a0, a3\n" /* Set the first argument. */
+ "li t0, 0\n" /* Clear our GPRs. */
+ "li t1, 0\n"
+ "li t2, 0\n"
+ "li s0, 0\n"
+ "li s1, 0\n"
+ /* Don't zero out a0, already set to the first argument. */
+ "li a1, 0\n"
+ /* Don't zero out a2, holds the target function f(). */
+ "li a3, 0\n"
+ "li a4, 0\n"
+ "li a5, 0\n"
+ "li a6, 0\n"
+ "li a7, 0\n"
+ "li s2, 0\n"
+ "li s3, 0\n"
+ "li s4, 0\n"
+ "li s5, 0\n"
+ "li s6, 0\n"
+ "li s7, 0\n"
+ "li s8, 0\n"
+ "li s9, 0\n"
+ "li s10, 0\n"
+ "li s11, 0\n"
+ "li t3, 0\n"
+ "li t4, 0\n"
+ "li t5, 0\n"
+ "li t6, 0\n"
+ "jr a2\n"
+ ".previous\n");
+
+/* Perform a clone system call. Clone is strange because it has fork()-like
+ return-twice semantics, so it needs special handling here.
+
+ Upon entry, we have:
+
+ Word (*fn)(void*) in a0
+ void* child_stack in a1
+ int flags in a2
+ void* arg in a3
+ pid_t* child_tid in a4
+ pid_t* parent_tid in a5
+ void* tls_ptr in a6
+
+ System call requires:
+
+ int $__NR_clone in a7
+ int flags in a0
+ void* child_stack in a1
+ pid_t* parent_tid in a2
+ void* tls_ptr in a3
+ pid_t* child_tid in a4
+
+ Returns a Long encoded in the linux-riscv64 way, not a SysRes.
+*/
+#define __NR_CLONE VG_STRINGIFY(__NR_clone)
+#define __NR_EXIT VG_STRINGIFY(__NR_exit)
+
+/* See priv_syswrap-linux.h for arg profile. */
+asm(".text\n"
+ ".globl do_syscall_clone_riscv64_linux\n"
+ "do_syscall_clone_riscv64_linux:\n"
+ /* Set up the child stack, temporarily preserving fn and arg. */
+ "addi a1, a1, -16\n" /* Make space on the stack. */
+ "sd a3, 8(a1)\n" /* Save arg. */
+ "sd a0, 0(a1)\n" /* Save fn. */
+
+ /* Setup the syscall. */
+ "li a7, " __NR_CLONE "\n" /* Load the syscall number. */
+ "mv a0, a2\n" /* Load syscall arg1: flags. */
+ "mv a1, a1\n" /* Load syscall arg2: child_stack. */
+ "mv a2, a5\n" /* Load syscall arg3: parent_tid. */
+ "mv a3, a6\n" /* Load syscall arg4: tls_ptr. */
+ "mv a4, a4\n" /* Load syscall arg5: child_tid. */
+
+ "ecall\n" /* clone() */
+
+ "bnez a0, 1f\n" /* Child if retval == 0. */
+
+ /* CHILD - call the thread function. */
+ "ld a1, 0(sp)\n" /* Pop fn. */
+ "ld a0, 8(sp)\n" /* Pop fn arg1: arg. */
+ "addi sp, sp, 16\n"
+ "jalr a1\n" /* Call fn. */
+
+ /* Exit with result. */
+ "mv a0, a0\n" /* arg1: return value from fn. */
+ "li a7, " __NR_EXIT "\n"
+
+ "ecall\n"
+
+ /* Exit returned?! */
+ "unimp\n"
+
+ "1:\n" /* PARENT or ERROR. a0 holds return value from the clone syscall. */
+ "ret\n"
+ ".previous\n");
+
+#undef __NR_CLONE
+#undef __NR_EXIT
+
+/* ---------------------------------------------------------------------
+ More thread stuff
+ ------------------------------------------------------------------ */
+
+/* riscv64 doesn't have any architecture specific thread stuff that needs to be
+ cleaned up. */
+void VG_(cleanup_thread)(ThreadArchState* arch) {}
+
+/* ---------------------------------------------------------------------
+ PRE/POST wrappers for riscv64/Linux-specific syscalls
+ ------------------------------------------------------------------ */
+
+#define PRE(name) DEFN_PRE_TEMPLATE(riscv64_linux, name)
+#define POST(name) DEFN_POST_TEMPLATE(riscv64_linux, name)
+
+/* ARG3 is only used for pointers into the traced process's address space and
+ for offsets into the traced process's struct user_regs_struct. It is never
+ a pointer into this process's memory space, and we should therefore not check
+ anything it points to. */
+static PRE(sys_ptrace)
+{
+ PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", SARG1, SARG2, ARG3, ARG4);
+ PRE_REG_READ4(int, "ptrace", long, request, long, pid, long, addr, long,
+ data);
+ switch (ARG1) {
+ case VKI_PTRACE_TRACEME:
+ break;
+ case VKI_PTRACE_PEEKTEXT:
+ case VKI_PTRACE_PEEKDATA:
+ case VKI_PTRACE_PEEKUSR:
+ PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long));
+ break;
+ case VKI_PTRACE_GETEVENTMSG:
+ PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
+ break;
+ case VKI_PTRACE_GETSIGINFO:
+ PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_SETSIGINFO:
+ PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_GETREGSET:
+ ML_(linux_PRE_getregset)(tid, ARG3, ARG4);
+ break;
+ case VKI_PTRACE_SETREGSET:
+ ML_(linux_PRE_setregset)(tid, ARG3, ARG4);
+ break;
+ default:
+ VG_(umsg)("WARNING: unhandled ptrace request %ld.\n", SARG1);
+ if (VG_(clo_verbosity) > 1)
+ VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
+ break;
+ }
+}
+
+static POST(sys_ptrace)
+{
+ switch (ARG1) {
+ case VKI_PTRACE_TRACEME:
+ ML_(linux_POST_traceme)(tid);
+ break;
+ case VKI_PTRACE_PEEKTEXT:
+ case VKI_PTRACE_PEEKDATA:
+ case VKI_PTRACE_PEEKUSR:
+ POST_MEM_WRITE(ARG4, sizeof(long));
+ break;
+ case VKI_PTRACE_GETEVENTMSG:
+ POST_MEM_WRITE(ARG4, sizeof(unsigned long));
+ break;
+ case VKI_PTRACE_GETSIGINFO:
+ /* XXX: This is a simplification. Different parts of the siginfo_t are
+ valid depending on the type of signal. */
+ POST_MEM_WRITE(ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_GETREGSET:
+ ML_(linux_POST_getregset)(tid, ARG3, ARG4);
+ break;
+ default:
+ break;
+ }
+}
+
+static PRE(sys_rt_sigreturn)
+{
+ /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
+ an explanation of what follows. */
+
+ PRINT("rt_sigreturn ( )");
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ vg_assert(tid >= 1 && tid < VG_N_THREADS);
+ vg_assert(VG_(is_running_thread)(tid));
+
+ /* Restore register state from frame and remove it. */
+ VG_(sigframe_destroy)(tid, True);
+
+ /* Tell the driver not to update the guest state with the "result", and set
+ a bogus result to keep it happy. */
+ *flags |= SfNoWriteResult;
+ SET_STATUS_Success(0);
+
+ /* Check to see if any signals arose as a result of this. */
+ *flags |= SfPollAfter;
+}
+
+static PRE(sys_mmap)
+{
+ PRINT("sys_mmap ( %#lx, %lu, %lu, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4,
+ ARG5, ARG6);
+ PRE_REG_READ6(long, "mmap", unsigned long, start, unsigned long, length,
+ unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ unsigned long, offset);
+
+ SysRes r =
+ ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+ SET_STATUS_from_SysRes(r);
+}
+
+static PRE(sys_riscv_flush_icache)
+{
+ PRINT("sys_riscv_flush_icache ( %#lx, %lx, %#lx )", ARG1, ARG2, ARG3);
+ PRE_REG_READ3(long, "riscv_flush_icache", unsigned long, start,
+ unsigned long, end, unsigned long, flags);
+
+ VG_(discard_translations)((Addr)ARG1, (ULong)ARG2 - (ULong)ARG1,
+ "PRE(sys_riscv_flush_icache)");
+ SET_STATUS_Success(0);
+}
+
+#undef PRE
+#undef POST
+
+/* ---------------------------------------------------------------------
+ The riscv64/Linux syscall table
+ ------------------------------------------------------------------ */
+
+/* Add a riscv64-linux specific wrapper to a syscall table. */
+#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(riscv64_linux, sysno, name)
+#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(riscv64_linux, sysno, name)
+
+/* This table maps from __NR_xxx syscall numbers to the appropriate PRE/POST
+ sys_foo() wrappers on riscv64. */
+static SyscallTableEntry syscall_main_table[] = {
+ LINXY(__NR_io_setup, sys_io_setup), /* 0 */
+ LINX_(__NR_io_destroy, sys_io_destroy), /* 1 */
+ LINX_(__NR_io_submit, sys_io_submit), /* 2 */
+ LINXY(__NR_io_cancel, sys_io_cancel), /* 3 */
+ LINXY(__NR_io_getevents, sys_io_getevents), /* 4 */
+ LINX_(__NR_setxattr, sys_setxattr), /* 5 */
+ LINX_(__NR_lsetxattr, sys_lsetxattr), /* 6 */
+ LINX_(__NR_fsetxattr, sys_fsetxattr), /* 7 */
+ LINXY(__NR_getxattr, sys_getxattr), /* 8 */
+ LINXY(__NR_lgetxattr, sys_lgetxattr), /* 9 */
+ LINXY(__NR_fgetxattr, sys_fgetxattr), /* 10 */
+ LINXY(__NR_listxattr, sys_listxattr), /* 11 */
+ LINXY(__NR_llistxattr, sys_llistxattr), /* 12 */
+ LINXY(__NR_flistxattr, sys_flistxattr), /* 13 */
+ LINX_(__NR_removexattr, sys_removexattr), /* 14 */
+ LINX_(__NR_lremovexattr, sys_lremovexattr), /* 15 */
+ LINX_(__NR_fremovexattr, sys_fremovexattr), /* 16 */
+ GENXY(__NR_getcwd, sys_getcwd), /* 17 */
+ LINXY(__NR_lookup_dcookie, sys_lookup_dcookie), /* 18 */
+ LINXY(__NR_eventfd2, sys_eventfd2), /* 19 */
+ LINXY(__NR_epoll_create1, sys_epoll_create1), /* 20 */
+ LINX_(__NR_epoll_ctl, sys_epoll_ctl), /* 21 */
+ LINXY(__NR_epoll_pwait, sys_epoll_pwait), /* 22 */
+ GENXY(__NR_dup, sys_dup), /* 23 */
+ LINXY(__NR_dup3, sys_dup3), /* 24 */
+ LINXY(__NR_fcntl, sys_fcntl), /* 25 */
+ LINXY(__NR_inotify_init1, sys_inotify_init1), /* 26 */
+ LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), /* 27 */
+ LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), /* 28 */
+ LINXY(__NR_ioctl, sys_ioctl), /* 29 */
+ LINX_(__NR_ioprio_set, sys_ioprio_set), /* 30 */
+ LINX_(__NR_ioprio_get, sys_ioprio_get), /* 31 */
+ GENX_(__NR_flock, sys_flock), /* 32 */
+ LINX_(__NR_mknodat, sys_mknodat), /* 33 */
+ LINX_(__NR_mkdirat, sys_mkdirat), /* 34 */
+ LINX_(__NR_unlinkat, sys_unlinkat), /* 35 */
+ LINX_(__NR_symlinkat, sys_symlinkat), /* 36 */
+ LINX_(__NR_linkat, sys_linkat), /* 37 */
+ LINX_(__NR_umount2, sys_umount), /* 39 */
+ LINX_(__NR_mount, sys_mount), /* 40 */
+ LINX_(__NR_pivot_root, sys_pivot_root), /* 41 */
+ GENXY(__NR_statfs, sys_statfs), /* 43 */
+ GENXY(__NR_fstatfs, sys_fstatfs), /* 44 */
+ GENX_(__NR_truncate, sys_truncate), /* 45 */
+ GENX_(__NR_ftruncate, sys_ftruncate), /* 46 */
+ LINX_(__NR_fallocate, sys_fallocate), /* 47 */
+ LINX_(__NR_faccessat, sys_faccessat), /* 48 */
+ GENX_(__NR_chdir, sys_chdir), /* 49 */
+ GENX_(__NR_fchdir, sys_fchdir), /* 50 */
+ GENX_(__NR_chroot, sys_chroot), /* 51 */
+ GENX_(__NR_fchmod, sys_fchmod), /* 52 */
+ LINX_(__NR_fchmodat, sys_fchmodat), /* 53 */
+ LINX_(__NR_fchownat, sys_fchownat), /* 54 */
+ GENX_(__NR_fchown, sys_fchown), /* 55 */
+ LINXY(__NR_openat, sys_openat), /* 56 */
+ GENX_(__NR_close, sys_close), /* 57 */
+ LINX_(__NR_vhangup, sys_vhangup), /* 58 */
+ LINXY(__NR_pipe2, sys_pipe2), /* 59 */
+ LINX_(__NR_quotactl, sys_quotactl), /* 60 */
+ GENXY(__NR_getdents64, sys_getdents64), /* 61 */
+ LINX_(__NR_lseek, sys_lseek), /* 62 */
+ GENXY(__NR_read, sys_read), /* 63 */
+ GENX_(__NR_write, sys_write), /* 64 */
+ GENXY(__NR_readv, sys_readv), /* 65 */
+ GENX_(__NR_writev, sys_writev), /* 66 */
+ GENXY(__NR_pread64, sys_pread64), /* 67 */
+ GENX_(__NR_pwrite64, sys_pwrite64), /* 68 */
+ LINXY(__NR_preadv, sys_preadv), /* 69 */
+ LINX_(__NR_pwritev, sys_pwritev), /* 70 */
+ LINXY(__NR_sendfile, sys_sendfile), /* 71 */
+ LINXY(__NR_pselect6, sys_pselect6), /* 72 */
+ LINXY(__NR_ppoll, sys_ppoll), /* 73 */
+ LINXY(__NR_signalfd4, sys_signalfd4), /* 74 */
+ LINX_(__NR_vmsplice, sys_vmsplice), /* 75 */
+ LINX_(__NR_splice, sys_splice), /* 76 */
+ LINX_(__NR_tee, sys_tee), /* 77 */
+ LINXY(__NR_readlinkat, sys_readlinkat), /* 78 */
+ LINXY(__NR_newfstatat, sys_newfstatat), /* 79 */
+ GENXY(__NR_fstat, sys_newfstat), /* 80 */
+ GENX_(__NR_sync, sys_sync), /* 81 */
+ GENX_(__NR_fsync, sys_fsync), /* 82 */
+ GENX_(__NR_fdatasync, sys_fdatasync), /* 83 */
+ LINX_(__NR_sync_file_range, sys_sync_file_range), /* 84 */
+ LINXY(__NR_timerfd_create, sys_timerfd_create), /* 85 */
+ LINXY(__NR_timerfd_settime, sys_timerfd_settime), /* 86 */
+ LINXY(__NR_timerfd_gettime, sys_timerfd_gettime), /* 87 */
+ LINX_(__NR_utimensat, sys_utimensat), /* 88 */
+ GENX_(__NR_acct, sys_acct), /* 89 */
+ LINXY(__NR_capget, sys_capget), /* 90 */
+ LINX_(__NR_capset, sys_capset), /* 91 */
+ LINX_(__NR_personality, sys_personality), /* 92 */
+ GENX_(__NR_exit, sys_exit), /* 93 */
+ LINX_(__NR_exit_group, sys_exit_group), /* 94 */
+ LINXY(__NR_waitid, sys_waitid), /* 95 */
+ LINX_(__NR_set_tid_address, sys_set_tid_address), /* 96 */
+ LINX_(__NR_unshare, sys_unshare), /* 97 */
+ LINXY(__NR_futex, sys_futex), /* 98 */
+ LINX_(__NR_set_robust_list, sys_set_robust_list), /* 99 */
+ LINXY(__NR_get_robust_list, sys_get_robust_list), /* 100 */
+ GENXY(__NR_nanosleep, sys_nanosleep), /* 101 */
+ GENXY(__NR_getitimer, sys_getitimer), /* 102 */
+ GENXY(__NR_setitimer, sys_setitimer), /* 103 */
+ GENX_(__NR_kexec_load, sys_ni_syscall), /* 104 */
+ LINX_(__NR_init_module, sys_init_module), /* 105 */
+ LINX_(__NR_delete_module, sys_delete_module), /* 106 */
+ LINXY(__NR_timer_create, sys_timer_create), /* 107 */
+ LINXY(__NR_timer_gettime, sys_timer_gettime), /* 108 */
+ LINX_(__NR_timer_getoverrun, sys_timer_getoverrun), /* 109 */
+ LINXY(__NR_timer_settime, sys_timer_settime), /* 110 */
+ LINX_(__NR_timer_delete, sys_timer_delete), /* 111 */
+ LINX_(__NR_clock_settime, sys_clock_settime), /* 112 */
+ LINXY(__NR_clock_gettime, sys_clock_gettime), /* 113 */
+ LINXY(__NR_clock_getres, sys_clock_getres), /* 114 */
+ LINXY(__NR_clock_nanosleep, sys_clock_nanosleep), /* 115 */
+ LINXY(__NR_syslog, sys_syslog), /* 116 */
+ PLAXY(__NR_ptrace, sys_ptrace), /* 117 */
+ LINXY(__NR_sched_setparam, sys_sched_setparam), /* 118 */
+ LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), /* 119 */
+ LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), /* 120 */
+ LINXY(__NR_sched_getparam, sys_sched_getparam), /* 121 */
+ LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), /* 122 */
+ LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), /* 123 */
+ LINX_(__NR_sched_yield, sys_sched_yield), /* 124 */
+ LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max), /* 125 */
+ LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min), /* 126 */
+ LINXY(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), /* 127 */
+ GENX_(__NR_kill, sys_kill), /* 129 */
+ LINXY(__NR_tkill, sys_tkill), /* 130 */
+ LINX_(__NR_tgkill, sys_tgkill), /* 131 */
+ GENXY(__NR_sigaltstack, sys_sigaltstack), /* 132 */
+ LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), /* 133 */
+ LINXY(__NR_rt_sigaction, sys_rt_sigaction), /* 134 */
+ LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), /* 135 */
+ LINXY(__NR_rt_sigpending, sys_rt_sigpending), /* 136 */
+ LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait), /* 137 */
+ LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), /* 138 */
+ PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), /* 139 */
+ GENX_(__NR_setpriority, sys_setpriority), /* 140 */
+ GENX_(__NR_getpriority, sys_getpriority), /* 141 */
+ GENX_(__NR_setregid, sys_setregid), /* 143 */
+ GENX_(__NR_setgid, sys_setgid), /* 144 */
+ GENX_(__NR_setreuid, sys_setreuid), /* 145 */
+ GENX_(__NR_setuid, sys_setuid), /* 146 */
+ LINX_(__NR_setresuid, sys_setresuid), /* 147 */
+ LINXY(__NR_getresuid, sys_getresuid), /* 148 */
+ LINX_(__NR_setresgid, sys_setresgid), /* 149 */
+ LINXY(__NR_getresgid, sys_getresgid), /* 150 */
+ LINX_(__NR_setfsuid, sys_setfsuid), /* 151 */
+ LINX_(__NR_setfsgid, sys_setfsgid), /* 152 */
+ GENXY(__NR_times, sys_times), /* 153 */
+ GENX_(__NR_setpgid, sys_setpgid), /* 154 */
+ GENX_(__NR_getpgid, sys_getpgid), /* 155 */
+ GENX_(__NR_getsid, sys_getsid), /* 156 */
+ GENX_(__NR_setsid, sys_setsid), /* 157 */
+ GENXY(__NR_getgroups, sys_getgroups), /* 158 */
+ GENX_(__NR_setgroups, sys_setgroups), /* 159 */
+ GENXY(__NR_uname, sys_newuname), /* 160 */
+ GENX_(__NR_sethostname, sys_sethostname), /* 161 */
+ GENXY(__NR_getrlimit, sys_getrlimit), /* 163 */
+ GENX_(__NR_setrlimit, sys_setrlimit), /* 164 */
+ GENXY(__NR_getrusage, sys_getrusage), /* 165 */
+ GENX_(__NR_umask, sys_umask), /* 166 */
+ LINXY(__NR_prctl, sys_prctl), /* 167 */
+ LINXY(__NR_getcpu, sys_getcpu), /* 168 */
+ GENXY(__NR_gettimeofday, sys_gettimeofday), /* 169 */
+ GENX_(__NR_settimeofday, sys_settimeofday), /* 170 */
+ LINXY(__NR_adjtimex, sys_adjtimex), /* 171 */
+ GENX_(__NR_getpid, sys_getpid), /* 172 */
+ GENX_(__NR_getppid, sys_getppid), /* 173 */
+ GENX_(__NR_getuid, sys_getuid), /* 174 */
+ GENX_(__NR_geteuid, sys_geteuid), /* 175 */
+ GENX_(__NR_getgid, sys_getgid), /* 176 */
+ GENX_(__NR_getegid, sys_getegid), /* 177 */
+ LINX_(__NR_gettid, sys_gettid), /* 178 */
+ LINXY(__NR_sysinfo, sys_sysinfo), /* 179 */
+ LINXY(__NR_mq_open, sys_mq_open), /* 180 */
+ LINX_(__NR_mq_unlink, sys_mq_unlink), /* 181 */
+ LINX_(__NR_mq_timedsend, sys_mq_timedsend), /* 182 */
+ LINXY(__NR_mq_timedreceive, sys_mq_timedreceive), /* 183 */
+ LINX_(__NR_mq_notify, sys_mq_notify), /* 184 */
+ LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), /* 185 */
+ LINX_(__NR_msgget, sys_msgget), /* 186 */
+ LINXY(__NR_msgctl, sys_msgctl), /* 187 */
+ LINXY(__NR_msgrcv, sys_msgrcv), /* 188 */
+ LINX_(__NR_msgsnd, sys_msgsnd), /* 189 */
+ LINX_(__NR_semget, sys_semget), /* 190 */
+ LINXY(__NR_semctl, sys_semctl), /* 191 */
+ LINX_(__NR_semtimedop, sys_semtimedop), /* 192 */
+ LINX_(__NR_semop, sys_semop), /* 193 */
+ LINX_(__NR_shmget, sys_shmget), /* 194 */
+ LINXY(__NR_shmctl, sys_shmctl), /* 195 */
+ LINXY(__NR_shmat, sys_shmat), /* 196 */
+ LINXY(__NR_shmdt, sys_shmdt), /* 197 */
+ LINXY(__NR_socket, sys_socket), /* 198 */
+ LINXY(__NR_socketpair, sys_socketpair), /* 199 */
+ LINX_(__NR_bind, sys_bind), /* 200 */
+ LINX_(__NR_listen, sys_listen), /* 201 */
+ LINXY(__NR_accept, sys_accept), /* 202 */
+ LINX_(__NR_connect, sys_connect), /* 203 */
+ LINXY(__NR_getsockname, sys_getsockname), /* 204 */
+ LINXY(__NR_getpeername, sys_getpeername), /* 205 */
+ LINX_(__NR_sendto, sys_sendto), /* 206 */
+ LINXY(__NR_recvfrom, sys_recvfrom), /* 207 */
+ LINX_(__NR_setsockopt, sys_setsockopt), /* 208 */
+ LINXY(__NR_getsockopt, sys_getsockopt), /* 209 */
+ LINX_(__NR_shutdown, sys_shutdown), /* 210 */
+ LINX_(__NR_sendmsg, sys_sendmsg), /* 211 */
+ LINXY(__NR_recvmsg, sys_recvmsg), /* 212 */
+ LINX_(__NR_readahead, sys_readahead), /* 213 */
+ GENX_(__NR_brk, sys_brk), /* 214 */
+ GENXY(__NR_munmap, sys_munmap), /* 215 */
+ GENX_(__NR_mremap, sys_mremap), /* 216 */
+ LINX_(__NR_add_key, sys_add_key), /* 217 */
+ LINX_(__NR_request_key, sys_request_key), /* 218 */
+ LINXY(__NR_keyctl, sys_keyctl), /* 219 */
+ LINX_(__NR_clone, sys_clone), /* 220 */
+ GENX_(__NR_execve, sys_execve), /* 221 */
+ PLAX_(__NR_mmap, sys_mmap), /* 222 */
+ GENX_(__NR_fadvise64, sys_ni_syscall), /* 223 */
+ GENXY(__NR_mprotect, sys_mprotect), /* 226 */
+ GENX_(__NR_msync, sys_msync), /* 227 */
+ GENX_(__NR_mlock, sys_mlock), /* 228 */
+ GENX_(__NR_munlock, sys_munlock), /* 229 */
+ GENX_(__NR_mlockall, sys_mlockall), /* 230 */
+ LINX_(__NR_munlockall, sys_munlockall), /* 231 */
+ GENXY(__NR_mincore, sys_mincore), /* 232 */
+ GENX_(__NR_madvise, sys_madvise), /* 233 */
+ LINX_(__NR_mbind, sys_mbind), /* 235 */
+ LINXY(__NR_get_mempolicy, sys_get_mempolicy), /* 236 */
+ LINX_(__NR_set_mempolicy, sys_set_mempolicy), /* 237 */
+ LINXY(__NR_move_pages, sys_move_pages), /* 239 */
+ LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo), /* 240 */
+ LINXY(__NR_perf_event_open, sys_perf_event_open), /* 241 */
+ LINXY(__NR_accept4, sys_accept4), /* 242 */
+ LINXY(__NR_recvmmsg, sys_recvmmsg), /* 243 */
+ PLAX_(__NR_riscv_flush_icache, sys_riscv_flush_icache), /* 259 */
+ GENXY(__NR_wait4, sys_wait4), /* 260 */
+ LINXY(__NR_prlimit64, sys_prlimit64), /* 261 */
+ LINXY(__NR_fanotify_init, sys_fanotify_init), /* 262 */
+ LINX_(__NR_fanotify_mark, sys_fanotify_mark), /* 263 */
+ LINXY(__NR_name_to_handle_at, sys_name_to_handle_at), /* 264 */
+ LINXY(__NR_open_by_handle_at, sys_open_by_handle_at), /* 265 */
+ LINXY(__NR_clock_adjtime, sys_clock_adjtime), /* 266 */
+ LINX_(__NR_syncfs, sys_syncfs), /* 267 */
+ LINX_(__NR_setns, sys_setns), /* 268 */
+ LINXY(__NR_sendmmsg, sys_sendmmsg), /* 269 */
+ LINXY(__NR_process_vm_readv, sys_process_vm_readv), /* 270 */
+ LINX_(__NR_process_vm_writev, sys_process_vm_writev), /* 271 */
+ LINX_(__NR_kcmp, sys_kcmp), /* 272 */
+ LINX_(__NR_finit_module, sys_finit_module), /* 273 */
+ LINX_(__NR_sched_setattr, sys_sched_setattr), /* 274 */
+ LINXY(__NR_sched_getattr, sys_sched_getattr), /* 275 */
+ LINX_(__NR_renameat2, sys_renameat2), /* 276 */
+ LINXY(__NR_getrandom, sys_getrandom), /* 278 */
+ LINXY(__NR_memfd_create, sys_memfd_create), /* 279 */
+ LINXY(__NR_bpf, sys_bpf), /* 280 */
+ LINX_(__NR_execveat, sys_execveat), /* 281 */
+ LINX_(__NR_membarrier, sys_membarrier), /* 283 */
+ GENX_(__NR_mlock2, sys_mlock2), /* 284 */
+ LINX_(__NR_copy_file_range, sys_copy_file_range), /* 285 */
+ LINXY(__NR_preadv2, sys_preadv2), /* 286 */
+ LINX_(__NR_pwritev2, sys_pwritev2), /* 287 */
+ LINXY(__NR_statx, sys_statx), /* 291 */
+ GENX_(__NR_rseq, sys_ni_syscall), /* 293 */
+ LINXY(__NR_io_uring_setup, sys_io_uring_setup), /* 425 */
+ LINXY(__NR_io_uring_enter, sys_io_uring_enter), /* 426 */
+ LINXY(__NR_io_uring_register, sys_io_uring_register), /* 427 */
+ GENX_(__NR_clone3, sys_ni_syscall), /* 435 */
+ LINXY(__NR_close_range, sys_close_range), /* 436 */
+ LINX_(__NR_faccessat2, sys_faccessat2), /* 439 */
+ LINXY(__NR_memfd_secret, sys_memfd_secret), /* 447 */
+};
+
+SyscallTableEntry* ML_(get_linux_syscall_entry)(UInt sysno)
+{
+ const UInt syscall_main_table_size =
+ sizeof(syscall_main_table) / sizeof(syscall_main_table[0]);
+
+ /* Is it in the contiguous initial section of the table? */
+ if (sysno < syscall_main_table_size) {
+ SyscallTableEntry* sys = &syscall_main_table[sysno];
+ if (sys->before == NULL)
+ return NULL; /* no entry */
+ else
+ return sys;
+ }
+
+ /* Can't find a wrapper. */
+ return NULL;
+}
+
+#endif // defined(VGP_riscv64_linux)
+
+/*--------------------------------------------------------------------*/
+/*--- end syswrap-riscv64-linux.c ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+How to install and configure a QEMU riscv64-linux installation.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Last updated 25 March 2023
+
+This file is a variant of qemu-aarch64-linux-HOWTO.txt but for RISCV64. It
+differs in use of openSUSE Tumbleweed and an already prepared image.
+
+
+Use a distribution package manager to install QEMU with support for running
+a 64-bit RISC-V system. It should provide the qemu-system-riscv64 executable.
+Make sure the package comes with an OpenSBI binary which is normally stored at
+/usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin.
+
+Get a Tumbleweed image and convert it to qcow2:
+
+mkdir tumbleweed && cd tumbleweed
+wget http://download.opensuse.org/ports/riscv/tumbleweed/images/openSUSE-Tumbleweed-RISC-V-JeOS-efi.riscv64.raw.xz
+unxz openSUSE-Tumbleweed-RISC-V-JeOS-efi.riscv64.raw.xz
+qemu-img convert -f raw -O qcow2 openSUSE-Tumbleweed-RISC-V-JeOS-efi.riscv64.raw image.qcow2
+qemu-img resize image.qcow2 20G
+
+Obtain a U-Boot loader:
+
+UBOOT=$(wget https://download.opensuse.org/ports/riscv/tumbleweed/repo/oss/INDEX.gz -O - | gunzip | grep 'u-boot-qemu-riscv64smode-[0123456789\.-]*\.riscv64\.rpm')
+wget --directory-prefix=u-boot https://download.opensuse.org/ports/riscv/tumbleweed/repo/oss/$UBOOT
+rpm2cpio u-boot/u-boot-qemu-riscv64smode-*.riscv64.rpm | cpio -D u-boot -idm
+
+Boot the system:
+
+qemu-system-riscv64 -nographic -machine virt -smp 4 -m 8G \
+ -kernel u-boot/boot/u-boot.bin \
+ -device virtio-blk-device,drive=hd0 -drive file=image.qcow2,format=qcow2,id=hd0 \
+ -device virtio-net-device,netdev=usernet -netdev user,id=usernet,hostfwd=tcp::5555-:22
+
+Now you can ssh into the VM and install stuff as usual:
+
+ssh -p 5555 root@localhost
+[The preset password is linux.]
+
+ (on the guest)
+ useradd username && passwd username
+ zypper install autoconf automake make gcc gcc-c++ git-core
+
+Hack on, etc.
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- riscv64/Linux-specific kernel interface: posix types. ---*/
+/*--- vki-posixtypes-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __VKI_POSIXTYPES_RISCV64_LINUX_H
+#define __VKI_POSIXTYPES_RISCV64_LINUX_H
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/posix_types.h
+//----------------------------------------------------------------------
+
+typedef unsigned int __vki_kernel_mode_t;
+typedef long __vki_kernel_off_t;
+typedef int __vki_kernel_pid_t;
+typedef int __vki_kernel_ipc_pid_t;
+typedef unsigned int __vki_kernel_uid_t;
+typedef unsigned int __vki_kernel_gid_t;
+typedef unsigned long __vki_kernel_size_t;
+typedef long __vki_kernel_time_t;
+typedef long __vki_kernel_suseconds_t;
+typedef long __vki_kernel_clock_t;
+typedef int __vki_kernel_timer_t;
+typedef int __vki_kernel_clockid_t;
+typedef char * __vki_kernel_caddr_t;
+typedef unsigned int __vki_kernel_uid32_t;
+typedef unsigned int __vki_kernel_gid32_t;
+
+typedef unsigned int __vki_kernel_old_uid_t;
+typedef unsigned int __vki_kernel_old_gid_t;
+
+typedef long long __vki_kernel_loff_t;
+
+typedef struct {
+ int val[2];
+} __vki_kernel_fsid_t;
+
+#endif // __VKI_POSIXTYPES_RISCV64_LINUX_H
+
+/*--------------------------------------------------------------------*/
+/*--- end vki-posixtypes-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- riscv64/Linux-specific kernel interface. vki-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __VKI_RISCV64_LINUX_H
+#define __VKI_RISCV64_LINUX_H
+
+// riscv64 is little-endian.
+#define VKI_LITTLE_ENDIAN 1
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/int-ll64.h
+//----------------------------------------------------------------------
+
+typedef unsigned char __vki_u8;
+
+typedef __signed__ short __vki_s16;
+typedef unsigned short __vki_u16;
+
+typedef __signed__ int __vki_s32;
+typedef unsigned int __vki_u32;
+
+typedef __signed__ long long __vki_s64;
+typedef unsigned long long __vki_u64;
+
+typedef unsigned short vki_u16;
+
+typedef unsigned int vki_u32;
+
+//----------------------------------------------------------------------
+// From linux-6.0/arch/riscv/include/asm/page.h
+//----------------------------------------------------------------------
+
+#define VKI_PAGE_SHIFT (12)
+#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT)
+#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT
+#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/asm-generic/shmparam.h
+//----------------------------------------------------------------------
+
+#define VKI_SHMLBA VKI_PAGE_SIZE /* attach addr a multiple of this */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/signal-defs.h
+//----------------------------------------------------------------------
+
+#define VKI_SIG_BLOCK 0 /* for blocking signals */
+#define VKI_SIG_UNBLOCK 1 /* for unblocking signals */
+#define VKI_SIG_SETMASK 2 /* for setting the signal mask */
+
+typedef void __vki_signalfn_t(int);
+typedef __vki_signalfn_t __user *__vki_sighandler_t;
+
+#define VKI_SIG_DFL ((__vki_sighandler_t)0) /* default signal handling */
+#define VKI_SIG_IGN ((__vki_sighandler_t)1) /* ignore signal */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/signal.h
+//----------------------------------------------------------------------
+
+#define _VKI_NSIG 64
+#define _VKI_NSIG_BPW 64
+#define _VKI_NSIG_WORDS (_VKI_NSIG / _VKI_NSIG_BPW)
+
+typedef unsigned long vki_old_sigset_t;
+
+typedef struct {
+ unsigned long sig[_VKI_NSIG_WORDS];
+} vki_sigset_t;
+
+#define VKI_SIGHUP 1
+#define VKI_SIGINT 2
+#define VKI_SIGQUIT 3
+#define VKI_SIGILL 4
+#define VKI_SIGTRAP 5
+#define VKI_SIGABRT 6
+#define VKI_SIGBUS 7
+#define VKI_SIGFPE 8
+#define VKI_SIGKILL 9
+#define VKI_SIGUSR1 10
+#define VKI_SIGSEGV 11
+#define VKI_SIGUSR2 12
+#define VKI_SIGPIPE 13
+#define VKI_SIGALRM 14
+#define VKI_SIGTERM 15
+#define VKI_SIGSTKFLT 16
+#define VKI_SIGCHLD 17
+#define VKI_SIGCONT 18
+#define VKI_SIGSTOP 19
+#define VKI_SIGTSTP 20
+#define VKI_SIGTTIN 21
+#define VKI_SIGTTOU 22
+#define VKI_SIGURG 23
+#define VKI_SIGXCPU 24
+#define VKI_SIGXFSZ 25
+#define VKI_SIGVTALRM 26
+#define VKI_SIGPROF 27
+#define VKI_SIGWINCH 28
+#define VKI_SIGIO 29
+#define VKI_SIGPWR 30
+#define VKI_SIGSYS 31
+#define VKI_SIGUNUSED 31
+
+#define VKI_SIGRTMIN 32
+#define VKI_SIGRTMAX _VKI_NSIG
+
+#define VKI_SA_NOCLDSTOP 0x00000001
+#define VKI_SA_NOCLDWAIT 0x00000002
+#define VKI_SA_SIGINFO 0x00000004
+#define VKI_SA_ONSTACK 0x08000000
+#define VKI_SA_RESTART 0x10000000
+#define VKI_SA_NODEFER 0x40000000
+#define VKI_SA_RESETHAND 0x80000000
+
+#define VKI_SA_NOMASK VKI_SA_NODEFER
+#define VKI_SA_ONESHOT VKI_SA_RESETHAND
+
+#define VKI_MINSIGSTKSZ 2048
+
+struct vki_sigaction_base {
+ __vki_sighandler_t ksa_handler;
+ unsigned long sa_flags;
+ vki_sigset_t sa_mask;
+};
+
+/* On Linux we use the same type for passing sigactions to
+ and from the kernel. Hence: */
+typedef struct vki_sigaction_base vki_sigaction_toK_t;
+typedef struct vki_sigaction_base vki_sigaction_fromK_t;
+
+typedef struct vki_sigaltstack {
+ void __user *ss_sp;
+ int ss_flags;
+ vki_size_t ss_size;
+} vki_stack_t;
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/linux/signal.h
+//----------------------------------------------------------------------
+
+#define VKI_SS_ONSTACK 1
+#define VKI_SS_DISABLE 2
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/mman-common.h
+//----------------------------------------------------------------------
+
+#define VKI_PROT_READ 0x1 /* page can be read */
+#define VKI_PROT_WRITE 0x2 /* page can be written */
+#define VKI_PROT_EXEC 0x4 /* page can be executed */
+#define VKI_PROT_NONE 0x0 /* page can not be accessed */
+#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
+
+#define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */
+#define VKI_MAP_ANONYMOUS 0x20 /* don't use a file */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/mman.h
+//----------------------------------------------------------------------
+
+#define VKI_MAP_NORESERVE 0x4000 /* don't check for reservations */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/linux/mman.h
+//----------------------------------------------------------------------
+
+#define VKI_MAP_SHARED 0x01 /* Share changes */
+#define VKI_MAP_PRIVATE 0x02 /* Changes are private */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/fcntl.h
+//----------------------------------------------------------------------
+
+#define VKI_O_ACCMODE 03
+#define VKI_O_RDONLY 00
+#define VKI_O_WRONLY 01
+#define VKI_O_RDWR 02
+#define VKI_O_CREAT 0100 /* not fcntl */
+#define VKI_O_EXCL 0200 /* not fcntl */
+#define VKI_O_TRUNC 01000 /* not fcntl */
+#define VKI_O_APPEND 02000
+#define VKI_O_NONBLOCK 04000
+#define VKI_O_LARGEFILE 0100000
+#define VKI_O_DIRECT 00040000
+
+#define VKI_F_DUPFD 0 /* dup */
+#define VKI_F_GETFD 1 /* get close_on_exec */
+#define VKI_F_SETFD 2 /* set/clear close_on_exec */
+#define VKI_F_GETFL 3 /* get file->f_flags */
+#define VKI_F_SETFL 4 /* set file->f_flags */
+#define VKI_F_GETLK 5
+#define VKI_F_SETLK 6
+#define VKI_F_SETLKW 7
+
+#define VKI_F_SETOWN 8 /* for sockets. */
+#define VKI_F_GETOWN 9 /* for sockets. */
+#define VKI_F_SETSIG 10 /* for sockets. */
+#define VKI_F_GETSIG 11 /* for sockets. */
+
+#define VKI_F_SETOWN_EX 15
+#define VKI_F_GETOWN_EX 16
+
+#define VKI_F_OFD_GETLK 36
+#define VKI_F_OFD_SETLK 37
+#define VKI_F_OFD_SETLKW 38
+
+struct vki_f_owner_ex {
+ int type;
+ __vki_kernel_pid_t pid;
+};
+
+#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+#define VKI_F_LINUX_SPECIFIC_BASE 1024
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/linux/fcntl.h
+//----------------------------------------------------------------------
+
+#define VKI_AT_FDCWD -100
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/resource.h
+//----------------------------------------------------------------------
+
+#define VKI_RLIMIT_DATA 2 /* max data size */
+#define VKI_RLIMIT_STACK 3 /* max stack size */
+#define VKI_RLIMIT_CORE 4 /* max core file size */
+#define VKI_RLIMIT_NOFILE 7 /* max number of open files */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/socket.h
+//----------------------------------------------------------------------
+
+#define VKI_SOL_SOCKET 1
+
+#define VKI_SO_TYPE 3
+
+#define VKI_SO_ATTACH_FILTER 26
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/sockios.h
+//----------------------------------------------------------------------
+
+#define VKI_SIOCSPGRP 0x8902
+#define VKI_SIOCGPGRP 0x8904
+#define VKI_SIOCATMARK 0x8905
+#define VKI_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
+#define VKI_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/stat.h
+//----------------------------------------------------------------------
+
+struct vki_stat {
+ unsigned long st_dev; /* Device. */
+ unsigned long st_ino; /* File serial number. */
+ unsigned int st_mode; /* File mode. */
+ unsigned int st_nlink; /* Link count. */
+ unsigned int st_uid; /* User ID of the file's owner. */
+ unsigned int st_gid; /* Group ID of the file's group. */
+ unsigned long st_rdev; /* Device number, if device. */
+ unsigned long __pad1;
+ long st_size; /* Size of file, in bytes. */
+ int st_blksize; /* Optimal block size for I/O. */
+ int __pad2;
+ long st_blocks; /* Number 512-byte blocks allocated. */
+ long st_atime; /* Time of last access. */
+ unsigned long st_atime_nsec;
+ long st_mtime; /* Time of last modification. */
+ unsigned long st_mtime_nsec;
+ long st_ctime; /* Time of last status change. */
+ unsigned long st_ctime_nsec;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/statfs.h
+//----------------------------------------------------------------------
+
+struct vki_statfs {
+ long f_type;
+ long f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+ __vki_kernel_fsid_t f_fsid;
+ long f_namelen;
+ long f_frsize;
+ long f_flags;
+ long f_spare[4];
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/termios.h
+//----------------------------------------------------------------------
+
+struct vki_winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define VKI_NCC 8
+struct vki_termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[VKI_NCC]; /* control characters */
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/termbits.h
+//----------------------------------------------------------------------
+
+typedef unsigned char vki_cc_t;
+typedef unsigned int vki_tcflag_t;
+
+#define VKI_NCCS 19
+struct vki_termios {
+ vki_tcflag_t c_iflag; /* input mode flags */
+ vki_tcflag_t c_oflag; /* output mode flags */
+ vki_tcflag_t c_cflag; /* control mode flags */
+ vki_tcflag_t c_lflag; /* local mode flags */
+ vki_cc_t c_line; /* line discipline */
+ vki_cc_t c_cc[VKI_NCCS]; /* control characters */
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/ioctl.h
+//----------------------------------------------------------------------
+
+#define _VKI_IOC_NRBITS 8
+#define _VKI_IOC_TYPEBITS 8
+#define _VKI_IOC_SIZEBITS 14
+#define _VKI_IOC_DIRBITS 2
+
+#define _VKI_IOC_SIZEMASK ((1 << _VKI_IOC_SIZEBITS)-1)
+#define _VKI_IOC_DIRMASK ((1 << _VKI_IOC_DIRBITS)-1)
+
+#define _VKI_IOC_NRSHIFT 0
+#define _VKI_IOC_TYPESHIFT (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS)
+#define _VKI_IOC_SIZESHIFT (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS)
+#define _VKI_IOC_DIRSHIFT (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS)
+
+#define _VKI_IOC_NONE 0U
+#define _VKI_IOC_WRITE 1U
+#define _VKI_IOC_READ 2U
+
+#define _VKI_IOC(dir,type,nr,size) \
+ (((dir) << _VKI_IOC_DIRSHIFT) | \
+ ((type) << _VKI_IOC_TYPESHIFT) | \
+ ((nr) << _VKI_IOC_NRSHIFT) | \
+ ((size) << _VKI_IOC_SIZESHIFT))
+
+#define _VKI_IO(type,nr) _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0)
+#define _VKI_IOR(type,nr,size) _VKI_IOC(_VKI_IOC_READ,(type),(nr),sizeof(size))
+#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr),sizeof(size))
+#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type),(nr),sizeof(size))
+
+#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK)
+#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK)
+
+//----------------------------------------------------------------------
+// From linux-3.10.5/include/uapi/asm-generic/ioctls.h
+//----------------------------------------------------------------------
+
+#define VKI_TCGETS 0x5401
+#define VKI_TCSETS 0x5402
+#define VKI_TCSETSW 0x5403
+#define VKI_TCSETSF 0x5404
+#define VKI_TCGETA 0x5405
+#define VKI_TCSETA 0x5406
+#define VKI_TCSETAW 0x5407
+#define VKI_TCSETAF 0x5408
+#define VKI_TCSBRK 0x5409
+#define VKI_TCXONC 0x540A
+#define VKI_TCFLSH 0x540B
+#define VKI_TIOCSCTTY 0x540E
+#define VKI_TIOCGPGRP 0x540F
+#define VKI_TIOCSPGRP 0x5410
+#define VKI_TIOCOUTQ 0x5411
+#define VKI_TIOCGWINSZ 0x5413
+#define VKI_TIOCSWINSZ 0x5414
+#define VKI_TIOCMGET 0x5415
+#define VKI_TIOCMBIS 0x5416
+#define VKI_TIOCMBIC 0x5417
+#define VKI_TIOCMSET 0x5418
+#define VKI_FIONREAD 0x541B
+#define VKI_TIOCLINUX 0x541C
+#define VKI_TIOCGSERIAL 0x541E
+#define VKI_TIOCSSERIAL 0x541F
+#define VKI_FIONBIO 0x5421
+#define VKI_TIOCNOTTY 0x5422
+#define VKI_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define VKI_FIONCLEX 0x5450
+#define VKI_FIOCLEX 0x5451
+#define VKI_FIOASYNC 0x5452
+#define VKI_TIOCSERGETLSR 0x5459 /* Get line status register */
+
+#define VKI_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/poll.h
+//----------------------------------------------------------------------
+
+#define VKI_POLLIN 0x0001
+
+struct vki_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/arch/riscv/include/uapi/asm/ptrace.h
+//----------------------------------------------------------------------
+
+struct vki_user_regs_struct {
+ unsigned long pc;
+ unsigned long ra;
+ unsigned long sp;
+ unsigned long gp;
+ unsigned long tp;
+ unsigned long t0;
+ unsigned long t1;
+ unsigned long t2;
+ unsigned long s0;
+ unsigned long s1;
+ unsigned long a0;
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+ unsigned long a4;
+ unsigned long a5;
+ unsigned long a6;
+ unsigned long a7;
+ unsigned long s2;
+ unsigned long s3;
+ unsigned long s4;
+ unsigned long s5;
+ unsigned long s6;
+ unsigned long s7;
+ unsigned long s8;
+ unsigned long s9;
+ unsigned long s10;
+ unsigned long s11;
+ unsigned long t3;
+ unsigned long t4;
+ unsigned long t5;
+ unsigned long t6;
+};
+
+struct __vki_riscv_f_ext_state {
+ __vki_u32 f[32];
+ __vki_u32 fcsr;
+};
+
+struct __vki_riscv_d_ext_state {
+ __vki_u64 f[32];
+ __vki_u32 fcsr;
+};
+
+struct __vki_riscv_q_ext_state {
+ __vki_u64 f[64] __attribute__((aligned(16)));
+ __vki_u32 fcsr;
+ __vki_u32 reserved[3];
+};
+
+union __vki_riscv_fp_state {
+ struct __vki_riscv_f_ext_state f;
+ struct __vki_riscv_d_ext_state d;
+ struct __vki_riscv_q_ext_state q;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/arch/riscv/include/uapi/asm/sigcontext.h
+//----------------------------------------------------------------------
+
+struct vki_sigcontext {
+ struct vki_user_regs_struct sc_regs;
+ union __vki_riscv_fp_state sc_fpregs;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/arch/riscv/include/uapi/asm/elf.h
+//----------------------------------------------------------------------
+
+typedef unsigned long vki_elf_greg_t;
+typedef struct vki_user_regs_struct vki_elf_gregset_t;
+#define VKI_ELF_NGREG (sizeof (struct vki_elf_gregset_t) / sizeof(vki_elf_greg_t))
+
+typedef union __vki_riscv_fp_state vki_elf_fpregset_t;
+
+//----------------------------------------------------------------------
+// From linux-6.0/arch/riscv/include/uapi/asm/ucontext.h
+//----------------------------------------------------------------------
+
+struct vki_ucontext {
+ unsigned long uc_flags;
+ struct vki_ucontext *uc_link;
+ vki_stack_t uc_stack;
+ vki_sigset_t uc_sigmask;
+ __vki_u8 __unused[1024 / 8 - sizeof(vki_sigset_t)];
+ struct vki_sigcontext uc_mcontext;
+};
+
+typedef char vki_modify_ldt_t;
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/ipcbuf.h
+//----------------------------------------------------------------------
+
+struct vki_ipc64_perm {
+ __vki_kernel_key_t key;
+ __vki_kernel_uid32_t uid;
+ __vki_kernel_gid32_t gid;
+ __vki_kernel_uid32_t cuid;
+ __vki_kernel_gid32_t cgid;
+ __vki_kernel_mode_t mode;
+ unsigned char __pad1[4 - sizeof(__vki_kernel_mode_t)];
+ unsigned short seq;
+ unsigned short __pad2;
+ unsigned long __unused1;
+ unsigned long __unused2;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/sembuf.h
+//----------------------------------------------------------------------
+
+struct vki_semid64_ds {
+ struct vki_ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ __vki_kernel_time_t sem_otime; /* last semop time */
+ __vki_kernel_time_t sem_ctime; /* last change time */
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/msgbuf.h
+//----------------------------------------------------------------------
+
+struct vki_msqid64_ds {
+ struct vki_ipc64_perm msg_perm;
+ __vki_kernel_time_t msg_stime; /* last msgsnd time */
+ __vki_kernel_time_t msg_rtime; /* last msgrcv time */
+ __vki_kernel_time_t msg_ctime; /* last change time */
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __vki_kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __vki_kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/shmbuf.h
+//----------------------------------------------------------------------
+
+struct vki_shmid64_ds {
+ struct vki_ipc64_perm shm_perm; /* operation perms */
+ vki_size_t shm_segsz; /* size of segment (bytes) */
+ __vki_kernel_time_t shm_atime; /* last attach time */
+ __vki_kernel_time_t shm_dtime; /* last detach time */
+ __vki_kernel_time_t shm_ctime; /* last change time */
+ __vki_kernel_pid_t shm_cpid; /* pid of creator */
+ __vki_kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct vki_shminfo64 {
+ unsigned long shmmax;
+ unsigned long shmmin;
+ unsigned long shmmni;
+ unsigned long shmseg;
+ unsigned long shmall;
+ unsigned long __unused1;
+ unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+//----------------------------------------------------------------------
+// From linux-6.0/include/uapi/asm-generic/errno.h
+//----------------------------------------------------------------------
+
+#define VKI_ENOSYS 38 /* Invalid system call number */
+#define VKI_EOVERFLOW 75 /* Value too large for defined data type */
+
+#endif // __VKI_RISCV64_LINUX_H
+
+/*--------------------------------------------------------------------*/
+/*--- end vki-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- System call numbers for riscv64-linux. ---*/
+/*--- vki-scnums-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2020-2023 Petr Pavlu
+ petr.pavlu@dagobah.cz
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __VKI_SCNUMS_RISCV64_LINUX_H
+#define __VKI_SCNUMS_RISCV64_LINUX_H
+
+// From linux-6.0/arch/riscv/include/uapi/asm/unistd.h
+// is a #include of
+// linux-6.0/include/uapi/asm-generic/unistd.h
+
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR3264_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR3264_statfs 43
+#define __NR3264_fstatfs 44
+#define __NR3264_truncate 45
+#define __NR3264_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR3264_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR3264_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR3264_fstatat 79
+#define __NR3264_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR3264_mmap 222
+#define __NR3264_fadvise64 223
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_arch_specific_syscall 244
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_rseq 293
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_faccessat2 439
+#define __NR_memfd_secret 447
+
+#define __NR_fcntl __NR3264_fcntl
+#define __NR_statfs __NR3264_statfs
+#define __NR_fstatfs __NR3264_fstatfs
+#define __NR_truncate __NR3264_truncate
+#define __NR_ftruncate __NR3264_ftruncate
+#define __NR_lseek __NR3264_lseek
+#define __NR_sendfile __NR3264_sendfile
+#define __NR_newfstatat __NR3264_fstatat
+#define __NR_fstat __NR3264_fstat
+#define __NR_mmap __NR3264_mmap
+#define __NR_fadvise64 __NR3264_fadvise64
+
+#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
+
+#endif /* __VKI_SCNUMS_RISCV64_LINUX_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end vki-scnums-riscv64-linux.h ---*/
+/*--------------------------------------------------------------------*/