diff options
author | Hongren Zheng <i@zenithal.me> | 2024-04-17 17:21:53 +0800 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-05-09 10:50:42 +0200 |
commit | 66ad636b979554ddde5cd5908feabda79d07317b (patch) | |
tree | ebb5e855913788905fd7cd2b09153a1d9796e5f1 | |
parent | 13d37d8f7557ee7935032ea832eab3e3c5540158 (diff) |
riscv: use hwprobe syscall for capability detection
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24172)
-rw-r--r-- | crypto/riscvcap.c | 43 | ||||
-rw-r--r-- | include/crypto/riscv_arch.def | 62 | ||||
-rw-r--r-- | include/crypto/riscv_arch.h | 45 |
3 files changed, 117 insertions, 33 deletions
diff --git a/crypto/riscvcap.c b/crypto/riscvcap.c index db75c21b28..7683bf0fb8 100644 --- a/crypto/riscvcap.c +++ b/crypto/riscvcap.c @@ -17,6 +17,12 @@ #define OPENSSL_RISCVCAP_IMPL #include "crypto/riscv_arch.h" +#ifdef OSSL_RISCV_HWPROBE +# include <unistd.h> +# include <sys/syscall.h> +# include <asm/hwprobe.h> +#endif + extern size_t riscv_vlen_asm(void); static void parse_env(const char *envstr); @@ -71,6 +77,38 @@ static void parse_env(const char *envstr) } } +#ifdef OSSL_RISCV_HWPROBE +static long riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count, + size_t cpu_count, unsigned long *cpus, + unsigned int flags) +{ + return syscall(__NR_riscv_hwprobe, pairs, pair_count, cpu_count, cpus, flags); +} + +static void hwprobe_to_cap() +{ + long ret; + struct riscv_hwprobe pairs[OSSL_RISCV_HWPROBE_PAIR_COUNT] = { + OSSL_RISCV_HWPROBE_PAIR_CONTENT + }; + + ret = riscv_hwprobe(pairs, OSSL_RISCV_HWPROBE_PAIR_COUNT, 0, NULL, 0); + /* if hwprobe syscall does not exist, ret would be -ENOSYS */ + if (ret == 0) { + for (size_t i = 0; i < kRISCVNumCaps; ++i) { + for (size_t j = 0; j != OSSL_RISCV_HWPROBE_PAIR_COUNT; ++j) { + if (pairs[j].key == RISCV_capabilities[i].hwprobe_key + && (pairs[j].value & RISCV_capabilities[i].hwprobe_value) + != 0) + /* Match, set relevant bit in OPENSSL_riscvcap_P[] */ + OPENSSL_riscvcap_P[RISCV_capabilities[i].index] |= + (1 << RISCV_capabilities[i].bit_offset); + } + } + } +} +#endif /* OSSL_RISCV_HWPROBE */ + size_t riscv_vlen(void) { return vlen; @@ -91,6 +129,11 @@ void OPENSSL_cpuid_setup(void) if ((e = getenv("OPENSSL_riscvcap"))) { parse_env(e); } +#ifdef OSSL_RISCV_HWPROBE + else { + hwprobe_to_cap(); + } +#endif if (RISCV_HAS_V()) { vlen = riscv_vlen_asm(); diff --git a/include/crypto/riscv_arch.def b/include/crypto/riscv_arch.def index 70b0647ae2..23d46b4a8b 100644 --- a/include/crypto/riscv_arch.def +++ b/include/crypto/riscv_arch.def @@ -16,37 +16,45 @@ * second argument as the index in the array where the capability will be stored * and third argument as the index of the bit to be used to encode the * capability. - * RISCV_DEFINE_CAP(EXTENSION NAME, array index, bit index) */ + * + * The fourth and the fifth arguments are copied from linux header asm/hwprobe.h. + * Directly coping values instead of macro names comes from the fact + * that an old version may lack definition of some macro. + * When there is no hwprobe key/value pair for a capability, the key is set to -1 + * and the value is set to 0, as when the hwprobe syscall returns a key of -1, + * the value is set to 0 and the corresponding capability would not be enabled. + * + * RISCV_DEFINE_CAP(EXTENSION NAME, array index, bit index, hwprobe key, hwprobe value) */ -RISCV_DEFINE_CAP(ZBA, 0, 0) -RISCV_DEFINE_CAP(ZBB, 0, 1) -RISCV_DEFINE_CAP(ZBC, 0, 2) -RISCV_DEFINE_CAP(ZBS, 0, 3) -RISCV_DEFINE_CAP(ZBKB, 0, 4) -RISCV_DEFINE_CAP(ZBKC, 0, 5) -RISCV_DEFINE_CAP(ZBKX, 0, 6) -RISCV_DEFINE_CAP(ZKND, 0, 7) -RISCV_DEFINE_CAP(ZKNE, 0, 8) -RISCV_DEFINE_CAP(ZKNH, 0, 9) -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) -RISCV_DEFINE_CAP(ZVBB, 0, 15) -RISCV_DEFINE_CAP(ZVBC, 0, 16) -RISCV_DEFINE_CAP(ZVKB, 0, 17) -RISCV_DEFINE_CAP(ZVKG, 0, 18) -RISCV_DEFINE_CAP(ZVKNED, 0, 19) -RISCV_DEFINE_CAP(ZVKNHA, 0, 20) -RISCV_DEFINE_CAP(ZVKNHB, 0, 21) -RISCV_DEFINE_CAP(ZVKSED, 0, 22) -RISCV_DEFINE_CAP(ZVKSH, 0, 23) +RISCV_DEFINE_CAP(ZBA, 0, 0, 4, (1 << 3)) +RISCV_DEFINE_CAP(ZBB, 0, 1, 4, (1 << 4)) +RISCV_DEFINE_CAP(ZBC, 0, 2, 4, (1 << 7)) +RISCV_DEFINE_CAP(ZBS, 0, 3, 4, (1 << 5)) +RISCV_DEFINE_CAP(ZBKB, 0, 4, 4, (1 << 8)) +RISCV_DEFINE_CAP(ZBKC, 0, 5, 4, (1 << 9)) +RISCV_DEFINE_CAP(ZBKX, 0, 6, 4, (1 << 10)) +RISCV_DEFINE_CAP(ZKND, 0, 7, 4, (1 << 11)) +RISCV_DEFINE_CAP(ZKNE, 0, 8, 4, (1 << 12)) +RISCV_DEFINE_CAP(ZKNH, 0, 9, 4, (1 << 13)) +RISCV_DEFINE_CAP(ZKSED, 0, 10, 4, (1 << 14)) +RISCV_DEFINE_CAP(ZKSH, 0, 11, 4, (1 << 15)) +RISCV_DEFINE_CAP(ZKR, 0, 12, -1, 0) +RISCV_DEFINE_CAP(ZKT, 0, 13, 4, (1 << 16)) +RISCV_DEFINE_CAP(V, 0, 14, 4, (1 << 2)) +RISCV_DEFINE_CAP(ZVBB, 0, 15, 4, (1 << 17)) +RISCV_DEFINE_CAP(ZVBC, 0, 16, 4, (1 << 18)) +RISCV_DEFINE_CAP(ZVKB, 0, 17, 4, (1 << 19)) +RISCV_DEFINE_CAP(ZVKG, 0, 18, 4, (1 << 20)) +RISCV_DEFINE_CAP(ZVKNED, 0, 19, 4, (1 << 21)) +RISCV_DEFINE_CAP(ZVKNHA, 0, 20, 4, (1 << 22)) +RISCV_DEFINE_CAP(ZVKNHB, 0, 21, 4, (1 << 23)) +RISCV_DEFINE_CAP(ZVKSED, 0, 22, 4, (1 << 24)) +RISCV_DEFINE_CAP(ZVKSH, 0, 23, 4, (1 << 25)) /* * In the future ... - * RISCV_DEFINE_CAP(ZFOO, 0, 31) - * RISCV_DEFINE_CAP(ZBAR, 1, 0) + * RISCV_DEFINE_CAP(ZFOO, 0, 31, ..., ...) + * RISCV_DEFINE_CAP(ZBAR, 1, 0, ..., ...) * ... and so on. */ diff --git a/include/crypto/riscv_arch.h b/include/crypto/riscv_arch.h index 6950137f45..6712cdc659 100644 --- a/include/crypto/riscv_arch.h +++ b/include/crypto/riscv_arch.h @@ -13,19 +13,28 @@ # include <ctype.h> # include <stdint.h> -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 +# if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) +# if __has_include(<asm/hwprobe.h>) +# define OSSL_RISCV_HWPROBE +# endif +# endif + +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) +1 extern uint32_t OPENSSL_riscvcap_P[ (( # include "riscv_arch.def" ) + sizeof(uint32_t) - 1) / sizeof(uint32_t) ]; # ifdef OPENSSL_RISCVCAP_IMPL -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) +1 uint32_t OPENSSL_riscvcap_P[ (( # include "riscv_arch.def" ) + sizeof(uint32_t) - 1) / sizeof(uint32_t) ]; # endif -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) \ +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) \ static inline int RISCV_HAS_##NAME(void) \ { \ return (OPENSSL_riscvcap_P[INDEX] & (1 << BIT_INDEX)) != 0; \ @@ -36,26 +45,50 @@ struct RISCV_capability_s { const char *name; size_t index; size_t bit_offset; +# ifdef OSSL_RISCV_HWPROBE + int32_t hwprobe_key; + uint64_t hwprobe_value; +# endif }; -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + OSSL_RISCV_HWPROBE_KEY, OSSL_RISCV_HWPROBE_VALUE) +1 extern const struct RISCV_capability_s RISCV_capabilities[ # include "riscv_arch.def" ]; # ifdef OPENSSL_RISCVCAP_IMPL -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) \ +# ifdef OSSL_RISCV_HWPROBE +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) \ + { #NAME, INDEX, BIT_INDEX, HWPROBE_KEY, HWPROBE_VALUE }, +# else +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) \ { #NAME, INDEX, BIT_INDEX }, +# endif const struct RISCV_capability_s RISCV_capabilities[] = { # include "riscv_arch.def" }; # endif -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 +# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX, \ + HWPROBE_KEY, HWPROBE_VALUE) +1 static const size_t kRISCVNumCaps = # include "riscv_arch.def" ; +# ifdef OSSL_RISCV_HWPROBE +/* + * Content is an array of { hwprobe_key, 0 } where + * hwprobe_key is copied from asm/hwprobe.h. + * It should be updated along with riscv_arch.def. + */ +# define OSSL_RISCV_HWPROBE_PAIR_COUNT 1 +# define OSSL_RISCV_HWPROBE_PAIR_CONTENT \ + { 4, 0 }, +# endif + /* Extension combination tests. */ #define RISCV_HAS_ZBB_AND_ZBC() (RISCV_HAS_ZBB() && RISCV_HAS_ZBC()) #define RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE() (RISCV_HAS_ZBKB() && RISCV_HAS_ZKND() && RISCV_HAS_ZKNE()) |