riscvcap.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright 2022 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. #include <stdlib.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <stdint.h>
  13. #include <openssl/crypto.h>
  14. #include "internal/cryptlib.h"
  15. #define OPENSSL_RISCVCAP_IMPL
  16. #include "crypto/riscv_arch.h"
  17. #ifdef OSSL_RISCV_HWPROBE
  18. # include <unistd.h>
  19. # include <sys/syscall.h>
  20. # include <asm/hwprobe.h>
  21. #endif
  22. extern size_t riscv_vlen_asm(void);
  23. static void parse_env(const char *envstr);
  24. static void strtoupper(char *str);
  25. static size_t vlen = 0;
  26. uint32_t OPENSSL_rdtsc(void)
  27. {
  28. return 0;
  29. }
  30. size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
  31. {
  32. return 0;
  33. }
  34. size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
  35. {
  36. return 0;
  37. }
  38. static void strtoupper(char *str)
  39. {
  40. for (char *x = str; *x; ++x)
  41. *x = toupper(*x);
  42. }
  43. /* parse_env() parses a RISC-V architecture string. An example of such a string
  44. * is "rv64gc_zba_zbb_zbc_zbs". Currently, the rv64gc part is ignored
  45. * and we simply search for "_[extension]" in the arch string to see if we
  46. * should enable a given extension.
  47. */
  48. #define BUFLEN 256
  49. static void parse_env(const char *envstr)
  50. {
  51. char envstrupper[BUFLEN];
  52. char buf[BUFLEN];
  53. /* Convert env str to all uppercase */
  54. OPENSSL_strlcpy(envstrupper, envstr, sizeof(envstrupper));
  55. strtoupper(envstrupper);
  56. for (size_t i = 0; i < kRISCVNumCaps; ++i) {
  57. /* Prefix capability with underscore in preparation for search */
  58. BIO_snprintf(buf, BUFLEN, "_%s", RISCV_capabilities[i].name);
  59. if (strstr(envstrupper, buf) != NULL) {
  60. /* Match, set relevant bit in OPENSSL_riscvcap_P[] */
  61. OPENSSL_riscvcap_P[RISCV_capabilities[i].index] |=
  62. (1 << RISCV_capabilities[i].bit_offset);
  63. }
  64. }
  65. }
  66. #ifdef OSSL_RISCV_HWPROBE
  67. static long riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
  68. size_t cpu_count, unsigned long *cpus,
  69. unsigned int flags)
  70. {
  71. return syscall(__NR_riscv_hwprobe, pairs, pair_count, cpu_count, cpus, flags);
  72. }
  73. static void hwprobe_to_cap(void)
  74. {
  75. long ret;
  76. struct riscv_hwprobe pairs[OSSL_RISCV_HWPROBE_PAIR_COUNT] = {
  77. OSSL_RISCV_HWPROBE_PAIR_CONTENT
  78. };
  79. ret = riscv_hwprobe(pairs, OSSL_RISCV_HWPROBE_PAIR_COUNT, 0, NULL, 0);
  80. /* if hwprobe syscall does not exist, ret would be -ENOSYS */
  81. if (ret == 0) {
  82. for (size_t i = 0; i < kRISCVNumCaps; ++i) {
  83. for (size_t j = 0; j != OSSL_RISCV_HWPROBE_PAIR_COUNT; ++j) {
  84. if (pairs[j].key == RISCV_capabilities[i].hwprobe_key
  85. && (pairs[j].value & RISCV_capabilities[i].hwprobe_value)
  86. != 0)
  87. /* Match, set relevant bit in OPENSSL_riscvcap_P[] */
  88. OPENSSL_riscvcap_P[RISCV_capabilities[i].index] |=
  89. (1 << RISCV_capabilities[i].bit_offset);
  90. }
  91. }
  92. }
  93. }
  94. #endif /* OSSL_RISCV_HWPROBE */
  95. size_t riscv_vlen(void)
  96. {
  97. return vlen;
  98. }
  99. # if defined(__GNUC__) && __GNUC__>=2
  100. __attribute__ ((constructor))
  101. # endif
  102. void OPENSSL_cpuid_setup(void)
  103. {
  104. char *e;
  105. static int trigger = 0;
  106. if (trigger != 0)
  107. return;
  108. trigger = 1;
  109. if ((e = getenv("OPENSSL_riscvcap"))) {
  110. parse_env(e);
  111. }
  112. #ifdef OSSL_RISCV_HWPROBE
  113. else {
  114. hwprobe_to_cap();
  115. }
  116. #endif
  117. if (RISCV_HAS_V()) {
  118. vlen = riscv_vlen_asm();
  119. }
  120. }