1 /* 2 * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #ifndef OSSL_CRYPTO_RISCV_ARCH_H 11 #define OSSL_CRYPTO_RISCV_ARCH_H 12 13 #include <ctype.h> 14 #include <stdint.h> 15 16 #if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) 17 #if __has_include(<asm/hwprobe.h>) 18 #include <sys/syscall.h> 19 #/* 20 * Some environments using musl are reported to have the hwprobe.h include 21 * file but not have the __NR_riscv_hwprobe define. 22 */ 23 #ifdef __NR_riscv_hwprobe 24 #define OSSL_RISCV_HWPROBE 25 #include <asm/hwcap.h> 26 extern unsigned int OPENSSL_riscv_hwcap_P; 27 #define VECTOR_CAPABLE (OPENSSL_riscv_hwcap_P & COMPAT_HWCAP_ISA_V) 28 #define ZVX_MIN 15 29 #define ZVX_MAX 23 30 #define IS_IN_DEPEND_VECTOR(offset) ((ZVX_MIN >= offset) && (offset <= ZVX_MAX)) 31 #endif 32 #endif 33 #endif 34 35 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 36 HWPROBE_KEY, HWPROBE_VALUE) +1 37 extern uint32_t OPENSSL_riscvcap_P[(( 38 #include "riscv_arch.def" 39 ) 40 + sizeof(uint32_t) - 1) 41 / sizeof(uint32_t)]; 42 43 #ifdef OPENSSL_RISCVCAP_IMPL 44 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 45 HWPROBE_KEY, HWPROBE_VALUE) +1 46 uint32_t OPENSSL_riscvcap_P[(( 47 #include "riscv_arch.def" 48 ) 49 + sizeof(uint32_t) - 1) 50 / sizeof(uint32_t)]; 51 #endif 52 53 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 54 HWPROBE_KEY, HWPROBE_VALUE) \ 55 static inline int RISCV_HAS_##NAME(void) \ 56 { \ 57 return (OPENSSL_riscvcap_P[INDEX] & (1 << BIT_INDEX)) != 0; \ 58 } 59 #include "riscv_arch.def" 60 61 struct RISCV_capability_s { 62 const char *name; 63 size_t index; 64 size_t bit_offset; 65 #ifdef OSSL_RISCV_HWPROBE 66 int32_t hwprobe_key; 67 uint64_t hwprobe_value; 68 #endif 69 }; 70 71 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 72 OSSL_RISCV_HWPROBE_KEY, OSSL_RISCV_HWPROBE_VALUE) +1 73 extern const struct RISCV_capability_s RISCV_capabilities[ 74 #include "riscv_arch.def" 75 ]; 76 77 #ifdef OPENSSL_RISCVCAP_IMPL 78 #ifdef OSSL_RISCV_HWPROBE 79 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 80 HWPROBE_KEY, HWPROBE_VALUE) \ 81 { #NAME, INDEX, BIT_INDEX, HWPROBE_KEY, HWPROBE_VALUE }, 82 #else 83 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 84 HWPROBE_KEY, HWPROBE_VALUE) \ 85 { #NAME, INDEX, BIT_INDEX }, 86 #endif 87 const struct RISCV_capability_s RISCV_capabilities[] = { 88 #include "riscv_arch.def" 89 }; 90 #endif 91 92 #define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ 93 HWPROBE_KEY, HWPROBE_VALUE) +1 94 static const size_t kRISCVNumCaps = 95 #include "riscv_arch.def" 96 ; 97 98 #ifdef OSSL_RISCV_HWPROBE 99 /* 100 * Content is an array of { hwprobe_key, 0 } where 101 * hwprobe_key is copied from asm/hwprobe.h. 102 * It should be updated along with riscv_arch.def. 103 */ 104 #define OSSL_RISCV_HWPROBE_PAIR_COUNT 1 105 #define OSSL_RISCV_HWPROBE_PAIR_CONTENT \ 106 { 4, 0 }, 107 #endif 108 109 /* Extension combination tests. */ 110 #define RISCV_HAS_ZBB_AND_ZBC() (RISCV_HAS_ZBB() && RISCV_HAS_ZBC()) 111 #define RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE() (RISCV_HAS_ZBKB() && RISCV_HAS_ZKND() && RISCV_HAS_ZKNE()) 112 #define RISCV_HAS_ZKND_AND_ZKNE() (RISCV_HAS_ZKND() && RISCV_HAS_ZKNE()) 113 /* 114 * The ZVBB is the superset of ZVKB extension. We use macro here to replace the 115 * `RISCV_HAS_ZVKB()` with `RISCV_HAS_ZVBB() || RISCV_HAS_ZVKB()`. 116 */ 117 #define RISCV_HAS_ZVKB() (RISCV_HAS_ZVBB() || RISCV_HAS_ZVKB()) 118 #define RISCV_HAS_ZVKB_AND_ZVKNHA() (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKNHA()) 119 #define RISCV_HAS_ZVKB_AND_ZVKNHB() (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKNHB()) 120 #define RISCV_HAS_ZVKB_AND_ZVKSED() (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKSED()) 121 #define RISCV_HAS_ZVKB_AND_ZVKSH() (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKSH()) 122 123 /* 124 * Get the size of a vector register in bits (VLEN). 125 * If RISCV_HAS_V() is false, then this returns 0. 126 */ 127 size_t riscv_vlen(void); 128 129 #endif 130