@@ -296,6 +296,12 @@ F: drivers/*/*/*_altivec.*
F: app/*/*_altivec.*
F: examples/*/*_altivec.*
+RISC-V
+M: Stanislaw Kardach <kda@semihalf.com>
+F: config/riscv/
+F: doc/guides/linux_gsg/cross_build_dpdk_for_riscv.rst
+F: lib/eal/riscv/
+
Intel x86
M: Bruce Richardson <bruce.richardson@intel.com>
M: Konstantin Ananyev <konstantin.ananyev@intel.com>
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2015 Cavium, Inc
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
*/
#ifndef _TEST_XMMT_OPS_H_
@@ -49,6 +52,19 @@ vect_set_epi32(int i3, int i2, int i1, int i0)
return data;
}
+#elif defined(RTE_ARCH_RISCV)
+
+#define vect_loadu_sil128(p) vect_load_128(p)
+
+/* sets the 4 signed 32-bit integer values and returns the xmm_t variable */
+static __rte_always_inline xmm_t
+vect_set_epi32(int i3, int i2, int i1, int i0)
+{
+ xmm_t data = (xmm_t){i0, i1, i2, i3};
+
+ return data;
+}
+
#endif
#endif /* _TEST_XMMT_OPS_H_ */
@@ -121,6 +121,8 @@ if cpu_instruction_set == 'generic'
cpu_instruction_set = 'generic'
elif host_machine.cpu_family().startswith('ppc')
cpu_instruction_set = 'power8'
+ elif host_machine.cpu_family().startswith('riscv')
+ cpu_instruction_set = 'riscv'
endif
endif
new file mode 100644
@@ -0,0 +1,143 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation.
+# Copyright(c) 2017 Cavium, Inc
+# Copyright(c) 2021 PANTHEON.tech s.r.o.
+# Copyright(c) 2022 StarFive
+# Copyright(c) 2022 SiFive
+# Copyright(c) 2022 Semihalf
+
+if not is_linux
+ error('Only Linux is supported at this point in time.')
+endif
+
+if not dpdk_conf.get('RTE_ARCH_64')
+ error('Only 64-bit compiles are supported for this platform type')
+endif
+
+dpdk_conf.set('RTE_ARCH', 'riscv')
+dpdk_conf.set('RTE_ARCH_RISCV', 1)
+dpdk_conf.set('RTE_FORCE_INTRINSICS', 1)
+
+# common flags to all riscv builds, with lowest priority
+flags_common = [
+ ['RTE_ARCH_RISCV', true],
+ ['RTE_CACHE_LINE_SIZE', 64],
+ # Set this to true if target emulates U-mode TIME CSR via M or S mode trap.
+ # This allows to remove a FENCE on rte_rdtsc_precise() as trap effectively
+ # acts as one.
+ ['RTE_RISCV_EMU_UTIME', false],
+ # Set this to true if target emulates U-mode CYCLE CSR via M or S mode trap.
+ # This allows to remove a FENCE on rte_rdtsc_precise() as trap effectively
+ # acts as one.
+ ['RTE_RISCV_EMU_UCYCLE', false],
+ # Manually set wall time clock frequency for the target. If 0, then it is
+ # read from /proc/device-tree/cpus/timebase-frequency. This property is
+ # guaranteed on Linux, as riscv time_init() requires it.
+ ['RTE_RISCV_TIME_FREQ', 0],
+]
+
+## SoC-specific options.
+# The priority is like this: arch > vendor > common.
+#
+# Note that currently there's no way of getting vendor/microarchitecture id
+# values in userspace which is why the logic of choosing the right flag
+# combination is strictly based on the values passed from a cross-file.
+vendor_generic = {
+ 'description': 'Generic RISC-V',
+ 'flags': [
+ ['RTE_MACHINE', '"riscv"'],
+ ['RTE_USE_C11_MEM_MODEL', true],
+ ['RTE_MAX_LCORE', 128],
+ ['RTE_MAX_NUMA_NODES', 2]
+ ],
+ 'arch_config': {
+ 'generic': {'machine_args': ['-march=rv64gc']}
+ }
+}
+
+arch_config_riscv = {
+ '0x8000000000000007': {
+ 'machine_args': ['-march=rv64gc', '-mtune=sifive-7-series'],
+ 'flags': [
+ ['RTE_RISCV_EMU_UTIME', true],
+ ['RTE_RISCV_EMU_UCYCLE', true]
+ ]
+ },
+}
+
+vendor_sifive = {
+ 'description': 'SiFive',
+ 'flags': [
+ ['RTE_MACHINE', '"riscv"'],
+ ['RTE_USE_C11_MEM_MODEL', true],
+ ['RTE_MAX_LCORE', 4],
+ ['RTE_MAX_NUMA_NODES', 1],
+ ],
+ 'arch_config': arch_config_riscv
+}
+
+vendors = {
+ 'generic': vendor_generic,
+ '0x489': vendor_sifive
+}
+
+# Native/cross vendor/arch detection
+if not meson.is_cross_build()
+ if machine == 'default'
+ # default build
+ vendor_id = 'generic'
+ arch_id = 'generic'
+ message('generic RISC-V')
+ else
+ vendor_id = 'generic'
+ arch_id = 'generic'
+ warning('RISC-V arch discovery not available, using generic!')
+ endif
+else
+ # cross build
+ vendor_id = meson.get_cross_property('vendor_id')
+ arch_id = meson.get_cross_property('arch_id')
+endif
+
+if vendors.has_key(vendor_id)
+ vendor_config = vendors[vendor_id]
+else
+ error('Unsupported RISC-V vendor: @0@. '.format(vendor_id) +
+ 'Please add support for it or use the generic ' +
+ '(-Dmachine=generic) build.')
+endif
+
+message('RISC-V vendor: ' + vendor_config['description'])
+message('RISC-V architecture id: ' + arch_id)
+
+arch_config = vendor_config['arch_config']
+if arch_config.has_key(arch_id)
+ # use the specified arch_id machine args if found
+ arch_config = arch_config[arch_id]
+else
+ # unknown micro-architecture id
+ error('Unsupported architecture @0@ of vendor @1@. '
+ .format(arch_id, vendor_id) +
+ 'Please add support for it or use the generic ' +
+ '(-Dmachine=generic) build.')
+endif
+
+# Concatenate flags respecting priorities.
+dpdk_flags = flags_common + vendor_config['flags'] + arch_config.get('flags', [])
+
+# apply supported machine args
+machine_args = [] # Clear previous machine args
+foreach flag: arch_config['machine_args']
+ if cc.has_argument(flag)
+ machine_args += flag
+ endif
+endforeach
+
+# apply flags
+foreach flag: dpdk_flags
+ if flag.length() > 0
+ dpdk_conf.set(flag[0], flag[1])
+ endif
+endforeach
+message('Using machine args: @0@'.format(machine_args))
+
new file mode 100644
@@ -0,0 +1,17 @@
+[binaries]
+c = 'riscv64-linux-gnu-gcc'
+cpp = 'riscv64-linux-gnu-g++'
+ar = 'riscv64-linux-gnu-ar'
+strip = 'riscv64-linux-gnu-strip'
+pcap-config = ''
+pkgconfig = 'riscv64-linux-gnu-pkg-config'
+
+[host_machine]
+system = 'linux'
+cpu_family = 'riscv64'
+cpu = 'rv64gc'
+endian = 'little'
+
+[properties]
+vendor_id = 'generic'
+arch_id = 'generic'
new file mode 100644
@@ -0,0 +1,19 @@
+[binaries]
+c = 'riscv64-unknown-linux-gnu-gcc'
+cpp = 'riscv64-unknown-linux-gnu-g++'
+ar = 'riscv64-unknown-linux-gnu-ar'
+strip = 'riscv64-unknown-linux-gnu-strip'
+pcap-config = ''
+pkgconfig = 'riscv64-unknown-linux-gnu-pkg-config'
+
+[host_machine]
+system = 'linux'
+cpu_family = 'riscv64'
+cpu = 'rv64gc'
+endian = 'little'
+
+[properties]
+vendor_id = '0x489'
+arch_id = '0x8000000000000007'
+max_lcores = 4
+max_numa_nodes = 1
@@ -42,7 +42,7 @@ Per Architecture Sources
The following macro options can be used:
* ``RTE_ARCH`` is a string that contains the name of the architecture.
-* ``RTE_ARCH_I686``, ``RTE_ARCH_X86_64``, ``RTE_ARCH_X86_X32``, ``RTE_ARCH_PPC_64``, ``RTE_ARCH_ARM``, ``RTE_ARCH_ARMv7`` or ``RTE_ARCH_ARM64`` are defined only if we are building for those architectures.
+* ``RTE_ARCH_I686``, ``RTE_ARCH_X86_64``, ``RTE_ARCH_X86_X32``, ``RTE_ARCH_PPC_64``, ``RTE_ARCH_RISCV``, ``RTE_ARCH_ARM``, ``RTE_ARCH_ARMv7`` or ``RTE_ARCH_ARM64`` are defined only if we are building for those architectures.
Per Execution Environment Sources
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
new file mode 100644
@@ -0,0 +1,125 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2020 ARM Corporation.
+ Copyright(c) 2022 StarFive
+ Copyright(c) 2022 SiFive
+ Copyright(c) 2022 Semihalf
+
+Cross compiling DPDK for RISC-V
+===============================
+
+This chapter describes how to cross compile DPDK for RISC-V from x86 build
+hosts.
+
+.. note::
+
+ While it's possible to compile DPDK natively on a RISC-V host, it is
+ currently recommended to cross-compile as Linux kernel does not offer any
+ way for userspace to discover the vendor and architecture identifiers of the
+ CPU and therefore any per-chip optimization options have to be chosen via
+ a cross-file or ``c_args``.
+
+
+Prerequisites
+-------------
+
+
+Linux kernel
+~~~~~~~~~~~~
+
+It is recommended to use Linux kernel built from
+`SiFive Freedom Unleashed SDK <https://github.com/sifive/freedom-u-sdk>`_.
+
+
+Meson prerequisites
+~~~~~~~~~~~~~~~~~~~
+
+Meson depends on pkgconfig to find the dependencies.
+The package ``pkg-config-riscv64-linux-gnu`` is required for RISC-V.
+To install it in Ubuntu::
+
+ sudo apt install pkg-config-riscv64-linux-gnu
+
+
+GNU toolchain
+-------------
+
+
+Obtain the cross toolchain
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The build process was tested using:
+
+* Ubuntu toolchain (the ``crossbuild-essential-riscv64`` package).
+
+* Latest `RISC-V GNU toolchain
+ <https://github.com/riscv/riscv-gnu-toolchain/releases>`_ on Ubuntu or Arch
+ Linux.
+
+Alternatively the toolchain may be built straight from the source, to do that
+follow the instructions on the riscv-gnu-toolchain github page.
+
+
+Unzip and add into the PATH
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This step is only required for the riscv-gnu-toolchain. The Ubuntu toolchain is
+in the PATH already.
+
+.. code-block:: console
+
+ tar -xvf riscv64-glibc-ubuntu-20.04-<version>.tar.gz
+ export PATH=$PATH:<cross_install_dir>/riscv/bin
+
+
+Cross Compiling DPDK with GNU toolchain using Meson
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To cross-compile DPDK for a desired target machine use the following command::
+
+ meson cross-build --cross-file <target_machine_configuration>
+ ninja -C cross-build
+
+For example if the target machine is a generic rv64gc RISC-V, use the following
+command::
+
+ meson riscv64-build-gcc --cross-file config/riscv/riscv64_linux_gcc
+ ninja -C riscv64-build-gcc
+
+If riscv-gnu-toolchain is used, binary names should be updated to match. Update the following lines in the cross-file:
+
+.. code-block:: console
+
+ [binaries]
+ c = 'riscv64-unknown-linux-gnu-gcc'
+ cpp = 'riscv64-unknown-linux-gnu-g++'
+ ar = 'riscv64-unknown-linux-gnu-ar'
+ strip = 'riscv64-unknown-linux-gnu-strip'
+ ...
+
+Some toolchains (such as freedom-u-sdk one) require also setting ``--sysroot``,
+otherwise include paths might not be resolved. To do so, add the appropriate
+paths to the cross-file:
+
+.. code-block:: console
+
+ [properties]
+ ...
+ c_args = ['--sysroot', '<path/to/toolchain/sysroot>']
+ cpp_args = c_args
+ c_link_args = ['--sysroot', '<path/to/toolchain/sysroot>']
+ cpp_link_args = c_link_args
+ ...
+
+
+Supported cross-compilation targets
+-----------------------------------
+
+Currently the following targets are supported:
+
+* Generic rv64gc ISA: ``config/riscv/riscv64_linux_gcc``
+
+* SiFive U740 SoC: ``config/riscv/riscv64_sifive_u740_linux_gcc``
+
+To add a new target support, ``config/riscv/meson.build`` has to be modified by
+adding a new vendor/architecture id and a corresponding cross-file has to be
+added to ``config/riscv`` directory.
@@ -14,6 +14,7 @@ Getting Started Guide for Linux
sys_reqs
build_dpdk
cross_build_dpdk_for_arm64
+ cross_build_dpdk_for_riscv
linux_drivers
build_sample_apps
linux_eal_parameters
@@ -855,6 +855,11 @@ x86-64
Support 64bits x86 architecture.
+rv64
+----
+
+Support 64-bit RISC-V architecture.
+
.. _nic_features_usage_doc:
@@ -74,6 +74,7 @@ ARMv8 =
Power8 =
x86-32 =
x86-64 =
+rv64 =
Usage doc =
Design doc =
Perf doc =
@@ -55,6 +55,14 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+* **Added initial RISC-V architecture support.***
+
+ Added EAL implementation for RISC-V architecture. The initial device the
+ porting was tested on is a HiFive Unmatched development board based on the
+ SiFive Freedom U740 SoC. In theory this implementation should work with any
+ ``rv64gc`` ISA compatible implementation with MMU supporting a reasonable
+ address space size (U740 uses sv39 MMU).
+
* **Updated Intel iavf driver.**
* Added Tx QoS queue rate limitation support.
@@ -1,6 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation
+if arch_subdir == 'riscv'
+ build = false
+ reason = 'riscv arch not supported'
+ subdir_done()
+endif
+
cflags += ['-DPF_DRIVER',
'-DVF_DRIVER',
'-DINTEGRATED_VF',
@@ -1,6 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation
+if arch_subdir == 'riscv'
+ build = false
+ reason = 'riscv arch not supported'
+ subdir_done()
+endif
+
cflags += ['-DRTE_LIBRTE_IXGBE_BYPASS']
subdir('base')
@@ -5,6 +5,11 @@ if not is_linux
build = false
reason = 'only supported on Linux'
endif
+if arch_subdir == 'riscv'
+ build = false
+ reason = 'riscv arch not supported'
+ subdir_done()
+endif
sources = files(
'memif_socket.c',
@@ -5,6 +5,11 @@ if not is_linux
build = false
reason = 'only supported on Linux'
endif
+if arch_subdir == 'riscv'
+ build = false
+ reason = 'riscv arch not supported'
+ subdir_done()
+endif
sources = files(
'rte_eth_tap.c',
'tap_bpf_api.c',
@@ -6,6 +6,12 @@
# To build this example as a standalone application with an already-installed
# DPDK instance, use 'make'
+if dpdk_conf.has('RTE_ARCH_RISCV')
+ build = false
+ reason = 'riscv arch not supported'
+ subdir_done()
+endif
+
allow_experimental_apis = true
deps += ['hash', 'lpm', 'fib', 'eventdev']
sources = files(
new file mode 100644
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2022 StarFive
+# Copyright(c) 2022 SiFive
+# Copyright(c) 2022 Semihalf
+
+arch_headers = files(
+ 'rte_atomic.h',
+ 'rte_byteorder.h',
+ 'rte_cpuflags.h',
+ 'rte_cycles.h',
+ 'rte_io.h',
+ 'rte_mcslock.h',
+ 'rte_memcpy.h',
+ 'rte_pause.h',
+ 'rte_pflock.h',
+ 'rte_power_intrinsics.h',
+ 'rte_prefetch.h',
+ 'rte_rwlock.h',
+ 'rte_spinlock.h',
+ 'rte_ticketlock.h',
+ 'rte_vect.h',
+)
+install_headers(arch_headers, subdir: get_option('include_subdir_arch'))
new file mode 100644
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ * All rights reserved.
+ */
+
+#ifndef RTE_ATOMIC_RISCV_H
+#define RTE_ATOMIC_RISCV_H
+
+#ifndef RTE_FORCE_INTRINSICS
+# error Platform must be built with RTE_FORCE_INTRINSICS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <rte_common.h>
+#include <rte_config.h>
+#include "generic/rte_atomic.h"
+
+#define rte_mb() asm volatile("fence rw, rw" : : : "memory")
+
+#define rte_wmb() asm volatile("fence w, w" : : : "memory")
+
+#define rte_rmb() asm volatile("fence r, r" : : : "memory")
+
+#define rte_smp_mb() rte_mb()
+
+#define rte_smp_wmb() rte_wmb()
+
+#define rte_smp_rmb() rte_rmb()
+
+#define rte_io_mb() asm volatile("fence iorw, iorw" : : : "memory")
+
+#define rte_io_wmb() asm volatile("fence orw, ow" : : : "memory")
+
+#define rte_io_rmb() asm volatile("fence ir, ir" : : : "memory")
+
+static __rte_always_inline void
+rte_atomic_thread_fence(int memorder)
+{
+ __atomic_thread_fence(memorder);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_ATOMIC_RISCV_H */
new file mode 100644
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Inspired from FreeBSD src/sys/powerpc/include/endian.h
+ * Copyright(c) 1987, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ */
+
+#ifndef RTE_BYTEORDER_RISCV_H
+#define RTE_BYTEORDER_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <rte_common.h>
+#include "generic/rte_byteorder.h"
+
+#ifndef RTE_BYTE_ORDER
+#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN
+#endif
+
+#define rte_cpu_to_le_16(x) (x)
+#define rte_cpu_to_le_32(x) (x)
+#define rte_cpu_to_le_64(x) (x)
+
+#define rte_cpu_to_be_16(x) rte_bswap16(x)
+#define rte_cpu_to_be_32(x) rte_bswap32(x)
+#define rte_cpu_to_be_64(x) rte_bswap64(x)
+
+#define rte_le_to_cpu_16(x) (x)
+#define rte_le_to_cpu_32(x) (x)
+#define rte_le_to_cpu_64(x) (x)
+
+#define rte_be_to_cpu_16(x) rte_bswap16(x)
+#define rte_be_to_cpu_32(x) rte_bswap32(x)
+#define rte_be_to_cpu_64(x) rte_bswap64(x)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_BYTEORDER_RISCV_H */
new file mode 100644
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014 IBM Corporation
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_CPUFLAGS_RISCV_H
+#define RTE_CPUFLAGS_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Enumeration of all CPU features supported
+ */
+enum rte_cpu_flag_t {
+ RTE_CPUFLAG_RISCV_ISA_A, /* Atomic */
+ RTE_CPUFLAG_RISCV_ISA_B, /* Bit-Manipulation */
+ RTE_CPUFLAG_RISCV_ISA_C, /* Compressed instruction */
+ RTE_CPUFLAG_RISCV_ISA_D, /* Double precision floating-point */
+ RTE_CPUFLAG_RISCV_ISA_E, /* RV32E ISA */
+ RTE_CPUFLAG_RISCV_ISA_F, /* Single precision floating-point */
+ RTE_CPUFLAG_RISCV_ISA_G, /* Extension pack (IMAFD, Zicsr, Zifencei) */
+ RTE_CPUFLAG_RISCV_ISA_H, /* Hypervisor */
+ RTE_CPUFLAG_RISCV_ISA_I, /* RV32I/RV64I/IRV128I base ISA */
+ RTE_CPUFLAG_RISCV_ISA_J, /* Dynamic Translation Language */
+ RTE_CPUFLAG_RISCV_ISA_K, /* Reserved */
+ RTE_CPUFLAG_RISCV_ISA_L, /* Decimal Floating-Point */
+ RTE_CPUFLAG_RISCV_ISA_M, /* Integer Multiply/Divide */
+ RTE_CPUFLAG_RISCV_ISA_N, /* User-level interrupts */
+ RTE_CPUFLAG_RISCV_ISA_O, /* Reserved */
+ RTE_CPUFLAG_RISCV_ISA_P, /* Packed-SIMD */
+ RTE_CPUFLAG_RISCV_ISA_Q, /* Quad-precision floating-points */
+ RTE_CPUFLAG_RISCV_ISA_R, /* Reserved */
+ RTE_CPUFLAG_RISCV_ISA_S, /* Supervisor mode */
+ RTE_CPUFLAG_RISCV_ISA_T, /* Transactional memory */
+ RTE_CPUFLAG_RISCV_ISA_U, /* User mode */
+ RTE_CPUFLAG_RISCV_ISA_V, /* Vector */
+ RTE_CPUFLAG_RISCV_ISA_W, /* Reserved */
+ RTE_CPUFLAG_RISCV_ISA_X, /* Non-standard extension present */
+ RTE_CPUFLAG_RISCV_ISA_Y, /* Reserved */
+ RTE_CPUFLAG_RISCV_ISA_Z, /* Reserved */
+ /* The last item */
+ RTE_CPUFLAG_NUMFLAGS,/**< This should always be the last! */
+};
+
+#include "generic/rte_cpuflags.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_CPUFLAGS_RISCV_H */
new file mode 100644
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Cavium, Inc
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_CYCLES_RISCV_H
+#define RTE_CYCLES_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_cycles.h"
+
+#ifndef RTE_RISCV_RDTSC_USE_HPM
+#define RTE_RISCV_RDTSC_USE_HPM 0
+#endif
+
+#define RV64_CSRR(reg, value) \
+ asm volatile("csrr %0, " #reg : "=r" (value) : : "memory")
+
+/** Read wall time counter */
+static __rte_always_inline uint64_t
+__rte_riscv_rdtime(void)
+{
+ uint64_t tsc;
+ RV64_CSRR(time, tsc);
+ return tsc;
+}
+
+/** Read wall time counter ensuring no re-ordering */
+static __rte_always_inline uint64_t
+__rte_riscv_rdtime_precise(void)
+{
+#if !defined(RTE_RISCV_EMU_UTIME)
+ asm volatile("fence" : : : "memory");
+#endif
+ return __rte_riscv_rdtime();
+}
+
+/** Read hart cycle counter */
+static __rte_always_inline uint64_t
+__rte_riscv_rdcycle(void)
+{
+ uint64_t tsc;
+ RV64_CSRR(cycle, tsc);
+ return tsc;
+}
+
+/** Read hart cycle counter ensuring no re-ordering */
+static __rte_always_inline uint64_t
+__rte_riscv_rdcycle_precise(void)
+{
+#if !defined(RTE_RISCV_EMU_UCYCLE)
+ asm volatile("fence" : : : "memory");
+#endif
+ return __rte_riscv_rdcycle();
+}
+
+/**
+ * Read the time base register.
+ *
+ * @return
+ * The time base for this lcore.
+ */
+static __rte_always_inline uint64_t
+rte_rdtsc(void)
+{
+ /**
+ * By default TIME userspace counter is used. Although it's frequency
+ * may not be enough for all applications.
+ */
+ if (!RTE_RISCV_RDTSC_USE_HPM)
+ return __rte_riscv_rdtime();
+ /**
+ * Alternatively HPM's CYCLE counter may be used. However this counter
+ * is not guaranteed by ISA to either be stable frequency or always
+ * enabled for userspace access (it may trap to kernel or firmware).
+ */
+ return __rte_riscv_rdcycle();
+}
+
+static inline uint64_t
+rte_rdtsc_precise(void)
+{
+ if (!RTE_RISCV_RDTSC_USE_HPM)
+ return __rte_riscv_rdtime_precise();
+ return __rte_riscv_rdcycle_precise();
+}
+
+static __rte_always_inline uint64_t
+rte_get_tsc_cycles(void)
+{
+ return rte_rdtsc();
+}
+
+#undef RV64_CSRR
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_CYCLES_RISCV_H */
new file mode 100644
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Cavium, Inc
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_IO_RISCV_H
+#define RTE_IO_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_io.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_IO_RISCV_H */
new file mode 100644
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ */
+
+#ifndef RTE_MCSLOCK_RISCV_H
+#define RTE_MCSLOCK_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_mcslock.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_MCSLOCK_RISCV_H */
new file mode 100644
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_MEMCPY_RISCV_H
+#define RTE_MEMCPY_RISCV_H
+
+#include <stdint.h>
+#include <string.h>
+
+#include "rte_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_memcpy.h"
+
+static inline void
+rte_mov16(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 16);
+}
+
+static inline void
+rte_mov32(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 32);
+}
+
+static inline void
+rte_mov48(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 48);
+}
+
+static inline void
+rte_mov64(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 64);
+}
+
+static inline void
+rte_mov128(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 128);
+}
+
+static inline void
+rte_mov256(uint8_t *dst, const uint8_t *src)
+{
+ memcpy(dst, src, 256);
+}
+
+#define rte_memcpy(d, s, n) memcpy((d), (s), (n))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_MEMCPY_RISCV_H */
new file mode 100644
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_PAUSE_RISCV_H
+#define RTE_PAUSE_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "rte_atomic.h"
+
+#include "generic/rte_pause.h"
+
+static inline void rte_pause(void)
+{
+ /* Insert pause hint directly to be compatible with old compilers.
+ * This will work even on platforms without Zihintpause extension
+ * because this is a FENCE hint instruction which evaluates to NOP then.
+ */
+ asm volatile(".int 0x0100000F"::: "memory");
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_PAUSE_RISCV_H */
new file mode 100644
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Microsoft Corporation
+ */
+#ifndef RTE_PFLOCK_RISCV_H
+#define RTE_PFLOCK_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_pflock.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_PFLOCK_RISCV_H */
new file mode 100644
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_POWER_INTRINSIC_RISCV_H
+#define RTE_POWER_INTRINSIC_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+
+#include "generic/rte_power_intrinsics.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_POWER_INTRINSIC_RISCV_H */
new file mode 100644
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014 IBM Corporation
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_PREFETCH_RISCV_H
+#define RTE_PREFETCH_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+#include "generic/rte_prefetch.h"
+
+static inline void rte_prefetch0(const volatile void *p)
+{
+ RTE_SET_USED(p);
+}
+
+static inline void rte_prefetch1(const volatile void *p)
+{
+ RTE_SET_USED(p);
+}
+
+static inline void rte_prefetch2(const volatile void *p)
+{
+ RTE_SET_USED(p);
+}
+
+static inline void rte_prefetch_non_temporal(const volatile void *p)
+{
+ /* non-temporal version not available, fallback to rte_prefetch0 */
+ rte_prefetch0(p);
+}
+
+__rte_experimental
+static inline void
+rte_cldemote(const volatile void *p)
+{
+ RTE_SET_USED(p);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_PREFETCH_RISCV_H */
new file mode 100644
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_RWLOCK_RISCV_H
+#define RTE_RWLOCK_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_rwlock.h"
+
+static inline void
+rte_rwlock_read_lock_tm(rte_rwlock_t *rwl)
+{
+ rte_rwlock_read_lock(rwl);
+}
+
+static inline void
+rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl)
+{
+ rte_rwlock_read_unlock(rwl);
+}
+
+static inline void
+rte_rwlock_write_lock_tm(rte_rwlock_t *rwl)
+{
+ rte_rwlock_write_lock(rwl);
+}
+
+static inline void
+rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl)
+{
+ rte_rwlock_write_unlock(rwl);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_RWLOCK_RISCV_H */
new file mode 100644
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 RehiveTech. All rights reserved.
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_SPINLOCK_RISCV_H
+#define RTE_SPINLOCK_RISCV_H
+
+#ifndef RTE_FORCE_INTRINSICS
+# error Platform must be built with RTE_FORCE_INTRINSICS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+#include "generic/rte_spinlock.h"
+
+static inline int rte_tm_supported(void)
+{
+ return 0;
+}
+
+static inline void
+rte_spinlock_lock_tm(rte_spinlock_t *sl)
+{
+ rte_spinlock_lock(sl); /* fall-back */
+}
+
+static inline int
+rte_spinlock_trylock_tm(rte_spinlock_t *sl)
+{
+ return rte_spinlock_trylock(sl);
+}
+
+static inline void
+rte_spinlock_unlock_tm(rte_spinlock_t *sl)
+{
+ rte_spinlock_unlock(sl);
+}
+
+static inline void
+rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr)
+{
+ rte_spinlock_recursive_lock(slr); /* fall-back */
+}
+
+static inline void
+rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr)
+{
+ rte_spinlock_recursive_unlock(slr);
+}
+
+static inline int
+rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr)
+{
+ return rte_spinlock_recursive_trylock(slr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_SPINLOCK_RISCV_H */
new file mode 100644
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_TICKETLOCK_RISCV_H
+#define RTE_TICKETLOCK_RISCV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "generic/rte_ticketlock.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_TICKETLOCK_RISCV_H */
new file mode 100644
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#ifndef RTE_VECT_RISCV_H
+#define RTE_VECT_RISCV_H
+
+#include <stdint.h>
+#include "generic/rte_vect.h"
+#include "rte_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_VECT_DEFAULT_SIMD_BITWIDTH RTE_VECT_SIMD_DISABLED
+
+typedef int32_t xmm_t __attribute__((vector_size(16)));
+
+#define XMM_SIZE (sizeof(xmm_t))
+#define XMM_MASK (XMM_SIZE - 1)
+
+typedef union rte_xmm {
+ xmm_t x;
+ uint8_t u8[XMM_SIZE / sizeof(uint8_t)];
+ uint16_t u16[XMM_SIZE / sizeof(uint16_t)];
+ uint32_t u32[XMM_SIZE / sizeof(uint32_t)];
+ uint64_t u64[XMM_SIZE / sizeof(uint64_t)];
+ double pd[XMM_SIZE / sizeof(double)];
+} __rte_aligned(8) rte_xmm_t;
+
+static inline xmm_t
+vect_load_128(void *p)
+{
+ xmm_t ret = *((xmm_t *)p);
+ return ret;
+}
+
+static inline xmm_t
+vect_and(xmm_t data, xmm_t mask)
+{
+ rte_xmm_t ret = (rte_xmm_t)data;
+ rte_xmm_t m = (rte_xmm_t)mask;
+ ret.u64[0] &= m.u64[0];
+ ret.u64[1] &= m.u64[1];
+ return ret.x;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_VECT_RISCV_H */
new file mode 100644
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation.
+
+subdir('include')
+
+sources += files(
+ 'rte_cpuflags.c',
+ 'rte_cycles.c',
+ 'rte_hypervisor.c',
+ 'rte_power_intrinsics.c',
+)
new file mode 100644
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#include "rte_cpuflags.h"
+
+#include <elf.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef AT_HWCAP
+#define AT_HWCAP 16
+#endif
+
+#ifndef AT_HWCAP2
+#define AT_HWCAP2 26
+#endif
+
+#ifndef AT_PLATFORM
+#define AT_PLATFORM 15
+#endif
+
+enum cpu_register_t {
+ REG_NONE = 0,
+ REG_HWCAP,
+ REG_HWCAP2,
+ REG_PLATFORM,
+ REG_MAX
+};
+
+typedef uint32_t hwcap_registers_t[REG_MAX];
+
+/**
+ * Struct to hold a processor feature entry
+ */
+struct feature_entry {
+ uint32_t reg;
+ uint32_t bit;
+#define CPU_FLAG_NAME_MAX_LEN 64
+ char name[CPU_FLAG_NAME_MAX_LEN];
+};
+
+#define FEAT_DEF(name, reg, bit) \
+ [RTE_CPUFLAG_##name] = {reg, bit, #name},
+
+typedef Elf64_auxv_t _Elfx_auxv_t;
+
+const struct feature_entry rte_cpu_feature_table[] = {
+ FEAT_DEF(RISCV_ISA_A, REG_HWCAP, 0)
+ FEAT_DEF(RISCV_ISA_B, REG_HWCAP, 1)
+ FEAT_DEF(RISCV_ISA_C, REG_HWCAP, 2)
+ FEAT_DEF(RISCV_ISA_D, REG_HWCAP, 3)
+ FEAT_DEF(RISCV_ISA_E, REG_HWCAP, 4)
+ FEAT_DEF(RISCV_ISA_F, REG_HWCAP, 5)
+ FEAT_DEF(RISCV_ISA_G, REG_HWCAP, 6)
+ FEAT_DEF(RISCV_ISA_H, REG_HWCAP, 7)
+ FEAT_DEF(RISCV_ISA_I, REG_HWCAP, 8)
+ FEAT_DEF(RISCV_ISA_J, REG_HWCAP, 9)
+ FEAT_DEF(RISCV_ISA_K, REG_HWCAP, 10)
+ FEAT_DEF(RISCV_ISA_L, REG_HWCAP, 11)
+ FEAT_DEF(RISCV_ISA_M, REG_HWCAP, 12)
+ FEAT_DEF(RISCV_ISA_N, REG_HWCAP, 13)
+ FEAT_DEF(RISCV_ISA_O, REG_HWCAP, 14)
+ FEAT_DEF(RISCV_ISA_P, REG_HWCAP, 15)
+ FEAT_DEF(RISCV_ISA_Q, REG_HWCAP, 16)
+ FEAT_DEF(RISCV_ISA_R, REG_HWCAP, 17)
+ FEAT_DEF(RISCV_ISA_S, REG_HWCAP, 18)
+ FEAT_DEF(RISCV_ISA_T, REG_HWCAP, 19)
+ FEAT_DEF(RISCV_ISA_U, REG_HWCAP, 20)
+ FEAT_DEF(RISCV_ISA_V, REG_HWCAP, 21)
+ FEAT_DEF(RISCV_ISA_W, REG_HWCAP, 22)
+ FEAT_DEF(RISCV_ISA_X, REG_HWCAP, 23)
+ FEAT_DEF(RISCV_ISA_Y, REG_HWCAP, 24)
+ FEAT_DEF(RISCV_ISA_Z, REG_HWCAP, 25)
+};
+/*
+ * Read AUXV software register and get cpu features for ARM
+ */
+static void
+rte_cpu_get_features(hwcap_registers_t out)
+{
+ out[REG_HWCAP] = rte_cpu_getauxval(AT_HWCAP);
+ out[REG_HWCAP2] = rte_cpu_getauxval(AT_HWCAP2);
+}
+
+/*
+ * Checks if a particular flag is available on current machine.
+ */
+int
+rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
+{
+ const struct feature_entry *feat;
+ hwcap_registers_t regs = {0};
+
+ if (feature >= RTE_CPUFLAG_NUMFLAGS)
+ return -ENOENT;
+
+ feat = &rte_cpu_feature_table[feature];
+ if (feat->reg == REG_NONE)
+ return -EFAULT;
+
+ rte_cpu_get_features(regs);
+ return (regs[feat->reg] >> feat->bit) & 1;
+}
+
+const char *
+rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
+{
+ if (feature >= RTE_CPUFLAG_NUMFLAGS)
+ return NULL;
+ return rte_cpu_feature_table[feature].name;
+}
+
+void
+rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
+{
+ memset(intrinsics, 0, sizeof(*intrinsics));
+}
new file mode 100644
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Cavium, Inc
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#include <stdio.h>
+
+#include "eal_private.h"
+#include "rte_byteorder.h"
+#include "rte_cycles.h"
+#include "rte_log.h"
+
+/** Read generic counter frequency */
+static uint64_t
+__rte_riscv_timefrq(void)
+{
+#define TIMEBASE_FREQ_SIZE 8
+ if (RTE_RISCV_TIME_FREQ > 0)
+ return RTE_RISCV_TIME_FREQ;
+ uint8_t buf[TIMEBASE_FREQ_SIZE];
+ ssize_t cnt;
+ FILE *file;
+
+ file = fopen("/proc/device-tree/cpus/timebase-frequency", "rb");
+ if (!file)
+ goto fail;
+
+ cnt = fread(buf, 1, TIMEBASE_FREQ_SIZE, file);
+ fclose(file);
+ switch (cnt) {
+ case 8:
+ return rte_be_to_cpu_64(*(uint64_t *)buf);
+ case 4:
+ return rte_be_to_cpu_32(*(uint32_t *)buf);
+ default:
+ break;
+ }
+fail:
+ RTE_LOG(WARNING, EAL, "Unable to read timebase-frequency from FDT.\n");
+ return 0;
+}
+
+uint64_t
+get_tsc_freq_arch(void)
+{
+ RTE_LOG(NOTICE, EAL, "TSC using RISC-V %s.\n",
+ RTE_RISCV_RDTSC_USE_HPM ? "rdcycle" : "rdtime");
+ if (!RTE_RISCV_RDTSC_USE_HPM)
+ return __rte_riscv_timefrq();
+#define CYC_PER_1MHZ 1E6
+ /*
+ * Use real time clock to estimate current cycle frequency
+ */
+ uint64_t ticks, frq;
+ uint64_t start_ticks, cur_ticks;
+ uint64_t start_cycle, end_cycle;
+
+ /* Do not proceed unless clock frequency can be obtained. */
+ frq = __rte_riscv_timefrq();
+ if (!frq)
+ return 0;
+
+ /* Number of ticks for 1/10 second */
+ ticks = frq / 10;
+
+ start_ticks = __rte_riscv_rdtime_precise();
+ start_cycle = rte_rdtsc_precise();
+ do {
+ cur_ticks = __rte_riscv_rdtime();
+ } while ((cur_ticks - start_ticks) < ticks);
+ end_cycle = rte_rdtsc_precise();
+
+ /* Adjust the cycles to next 1Mhz */
+ return RTE_ALIGN_MUL_CEIL((end_cycle - start_cycle) * 10, CYC_PER_1MHZ);
+}
new file mode 100644
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#include "rte_hypervisor.h"
+
+enum rte_hypervisor
+rte_hypervisor_get(void)
+{
+ return RTE_HYPERVISOR_UNKNOWN;
+}
new file mode 100644
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 StarFive
+ * Copyright(c) 2022 SiFive
+ * Copyright(c) 2022 Semihalf
+ */
+
+#include "rte_power_intrinsics.h"
+
+/**
+ * This function is not supported on RISC-V 64
+ */
+int
+rte_power_monitor(const struct rte_power_monitor_cond *pmc,
+ const uint64_t tsc_timestamp)
+{
+ RTE_SET_USED(pmc);
+ RTE_SET_USED(tsc_timestamp);
+
+ return -ENOTSUP;
+}
+
+/**
+ * This function is not supported on RISC-V 64
+ */
+int
+rte_power_pause(const uint64_t tsc_timestamp)
+{
+ RTE_SET_USED(tsc_timestamp);
+
+ return -ENOTSUP;
+}
+
+/**
+ * This function is not supported on RISC-V 64
+ */
+int
+rte_power_monitor_wakeup(const unsigned int lcore_id)
+{
+ RTE_SET_USED(lcore_id);
+
+ return -ENOTSUP;
+}
+
+/**
+ * This function is not supported on RISC-V 64
+ */
+int
+rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[],
+ const uint32_t num, const uint64_t tsc_timestamp)
+{
+ RTE_SET_USED(pmc);
+ RTE_SET_USED(num);
+ RTE_SET_USED(tsc_timestamp);
+
+ return -ENOTSUP;
+}
@@ -50,6 +50,8 @@ elif host_machine.cpu_family().startswith('arm') or host_machine.cpu_family().st
arch_subdir = 'arm'
elif host_machine.cpu_family().startswith('ppc')
arch_subdir = 'ppc'
+elif host_machine.cpu_family().startswith('riscv')
+ arch_subdir = 'riscv'
endif
# configure the build, and make sure configs here and in config folder are