polyval.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * POLYVAL library functions, arm64 optimized
  4. *
  5. * Copyright 2025 Google LLC
  6. */
  7. #include <asm/simd.h>
  8. #include <linux/cpufeature.h>
  9. #define NUM_H_POWERS 8
  10. static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_pmull);
  11. asmlinkage void polyval_mul_pmull(struct polyval_elem *a,
  12. const struct polyval_elem *b);
  13. asmlinkage void polyval_blocks_pmull(struct polyval_elem *acc,
  14. const struct polyval_key *key,
  15. const u8 *data, size_t nblocks);
  16. static void polyval_preparekey_arch(struct polyval_key *key,
  17. const u8 raw_key[POLYVAL_BLOCK_SIZE])
  18. {
  19. static_assert(ARRAY_SIZE(key->h_powers) == NUM_H_POWERS);
  20. memcpy(&key->h_powers[NUM_H_POWERS - 1], raw_key, POLYVAL_BLOCK_SIZE);
  21. if (static_branch_likely(&have_pmull) && may_use_simd()) {
  22. scoped_ksimd() {
  23. for (int i = NUM_H_POWERS - 2; i >= 0; i--) {
  24. key->h_powers[i] = key->h_powers[i + 1];
  25. polyval_mul_pmull(
  26. &key->h_powers[i],
  27. &key->h_powers[NUM_H_POWERS - 1]);
  28. }
  29. }
  30. } else {
  31. for (int i = NUM_H_POWERS - 2; i >= 0; i--) {
  32. key->h_powers[i] = key->h_powers[i + 1];
  33. polyval_mul_generic(&key->h_powers[i],
  34. &key->h_powers[NUM_H_POWERS - 1]);
  35. }
  36. }
  37. }
  38. static void polyval_mul_arch(struct polyval_elem *acc,
  39. const struct polyval_key *key)
  40. {
  41. if (static_branch_likely(&have_pmull) && may_use_simd()) {
  42. scoped_ksimd()
  43. polyval_mul_pmull(acc, &key->h_powers[NUM_H_POWERS - 1]);
  44. } else {
  45. polyval_mul_generic(acc, &key->h_powers[NUM_H_POWERS - 1]);
  46. }
  47. }
  48. static void polyval_blocks_arch(struct polyval_elem *acc,
  49. const struct polyval_key *key,
  50. const u8 *data, size_t nblocks)
  51. {
  52. if (static_branch_likely(&have_pmull) && may_use_simd()) {
  53. do {
  54. /* Allow rescheduling every 4 KiB. */
  55. size_t n = min_t(size_t, nblocks,
  56. 4096 / POLYVAL_BLOCK_SIZE);
  57. scoped_ksimd()
  58. polyval_blocks_pmull(acc, key, data, n);
  59. data += n * POLYVAL_BLOCK_SIZE;
  60. nblocks -= n;
  61. } while (nblocks);
  62. } else {
  63. polyval_blocks_generic(acc, &key->h_powers[NUM_H_POWERS - 1],
  64. data, nblocks);
  65. }
  66. }
  67. #define polyval_mod_init_arch polyval_mod_init_arch
  68. static void polyval_mod_init_arch(void)
  69. {
  70. if (cpu_have_named_feature(PMULL))
  71. static_branch_enable(&have_pmull);
  72. }