From: Hongren Zheng Date: Wed, 17 Apr 2024 09:21:53 +0000 (+0800) Subject: riscv: use hwprobe syscall for capability detection X-Git-Tag: openssl-3.4.0-alpha1~574 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=66ad636b979554ddde5cd5908feabda79d07317b;p=thirdparty%2Fopenssl.git riscv: use hwprobe syscall for capability detection Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24172) --- diff --git a/crypto/riscvcap.c b/crypto/riscvcap.c index db75c21b289..7683bf0fb86 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 +# include +# include +#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 70b0647ae2a..23d46b4a8b1 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 6950137f451..6712cdc6598 100644 --- a/include/crypto/riscv_arch.h +++ b/include/crypto/riscv_arch.h @@ -13,19 +13,28 @@ # include # include -# define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 +# if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) +# if __has_include() +# 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())