From cdea67193da8aab0f1a49d2b7ce144ad21bfc51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Tue, 14 Feb 2023 06:22:03 +0100 Subject: [PATCH] riscv: Add basic vector extension support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RISC-V vector extension comes with an implementation-defined number of bits per vector register (VLEN), which can be read out at run-time using the CSR 'vlenb' (which returns VLEN/8) followed by a multiplication by 8 (to convert bytes to bits). This patch introduces a RISC-V capability 'V' to specify the availability of the vector extension. If this extension is found at run-time, then we read out VLEN as described above and cache it. Caching ensures that we only read the CSR once at startup. This is necessary because reading out CSR can be expensive (e.g. if CSR readout is implemented using trap-and-emulate). Follow-up patches can make use of VLEN and chose the best strategy based on the available length of the vector registers. Signed-off-by: Christoph Müllner Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/21923) --- crypto/riscv64cpuid.pl | 16 ++++++++++++++++ crypto/riscvcap.c | 14 +++++++++++++- include/crypto/riscv_arch.def | 1 + include/crypto/riscv_arch.h | 6 ++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/crypto/riscv64cpuid.pl b/crypto/riscv64cpuid.pl index 675e9b6111..5dcdc5c584 100644 --- a/crypto/riscv64cpuid.pl +++ b/crypto/riscv64cpuid.pl @@ -84,6 +84,22 @@ OPENSSL_cleanse: ___ } +{ +my ($ret) = ('a0'); +$code .= <<___; +################################################################################ +# size_t riscv_vlen_asm(void) +# Return VLEN (i.e. the length of a vector register in bits). +.p2align 3 +.globl riscv_vlen_asm +.type riscv_vlen_asm,\@function +riscv_vlen_asm: + csrr $ret, vlenb + slli $ret, $ret, 3 + ret +.size riscv_vlen_asm,.-riscv_vlen_asm +___ +} print $code; close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/riscvcap.c b/crypto/riscvcap.c index 1cbfb4a574..db75c21b28 100644 --- a/crypto/riscvcap.c +++ b/crypto/riscvcap.c @@ -17,9 +17,13 @@ #define OPENSSL_RISCVCAP_IMPL #include "crypto/riscv_arch.h" +extern size_t riscv_vlen_asm(void); + static void parse_env(const char *envstr); static void strtoupper(char *str); +static size_t vlen = 0; + uint32_t OPENSSL_rdtsc(void) { return 0; @@ -67,6 +71,11 @@ static void parse_env(const char *envstr) } } +size_t riscv_vlen(void) +{ + return vlen; +} + # if defined(__GNUC__) && __GNUC__>=2 __attribute__ ((constructor)) # endif @@ -81,6 +90,9 @@ void OPENSSL_cpuid_setup(void) if ((e = getenv("OPENSSL_riscvcap"))) { parse_env(e); - return; + } + + if (RISCV_HAS_V()) { + vlen = riscv_vlen_asm(); } } diff --git a/include/crypto/riscv_arch.def b/include/crypto/riscv_arch.def index 6c26dbf401..b355fa4ddc 100644 --- a/include/crypto/riscv_arch.def +++ b/include/crypto/riscv_arch.def @@ -32,6 +32,7 @@ RISCV_DEFINE_CAP(ZKSED, 0, 10) RISCV_DEFINE_CAP(ZKSH, 0, 11) RISCV_DEFINE_CAP(ZKR, 0, 12) RISCV_DEFINE_CAP(ZKT, 0, 13) +RISCV_DEFINE_CAP(V, 0, 14) /* * In the future ... diff --git a/include/crypto/riscv_arch.h b/include/crypto/riscv_arch.h index 9518584111..8bd281ad80 100644 --- a/include/crypto/riscv_arch.h +++ b/include/crypto/riscv_arch.h @@ -61,4 +61,10 @@ static const size_t kRISCVNumCaps = #define RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE() (RISCV_HAS_ZBKB() && RISCV_HAS_ZKND() && RISCV_HAS_ZKNE()) #define RISCV_HAS_ZKND_AND_ZKNE() (RISCV_HAS_ZKND() && RISCV_HAS_ZKNE()) +/* + * Get the size of a vector register in bits (VLEN). + * If RISCV_HAS_V() is false, then this returns 0. + */ +size_t riscv_vlen(void); + #endif