161f66c52SEric Biggers /* SPDX-License-Identifier: GPL-2.0-or-later */ 261f66c52SEric Biggers /* 3a336c01fSEric Biggers * GHASH and POLYVAL, arm64 optimized 461f66c52SEric Biggers * 561f66c52SEric Biggers * Copyright 2025 Google LLC 661f66c52SEric Biggers */ 761f66c52SEric Biggers #include <asm/simd.h> 861f66c52SEric Biggers #include <linux/cpufeature.h> 961f66c52SEric Biggers 1061f66c52SEric Biggers #define NUM_H_POWERS 8 1161f66c52SEric Biggers 12a336c01fSEric Biggers static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_asimd); 1361f66c52SEric Biggers static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_pmull); 1461f66c52SEric Biggers 15a336c01fSEric Biggers asmlinkage void pmull_ghash_update_p8(size_t blocks, struct polyval_elem *dg, 16a336c01fSEric Biggers const u8 *src, 17a336c01fSEric Biggers const struct polyval_elem *h); 1861f66c52SEric Biggers asmlinkage void polyval_mul_pmull(struct polyval_elem *a, 1961f66c52SEric Biggers const struct polyval_elem *b); 2061f66c52SEric Biggers asmlinkage void polyval_blocks_pmull(struct polyval_elem *acc, 2161f66c52SEric Biggers const struct polyval_key *key, 2261f66c52SEric Biggers const u8 *data, size_t nblocks); 2361f66c52SEric Biggers 24b3b6e8f9SEric Biggers #define polyval_preparekey_arch polyval_preparekey_arch 2561f66c52SEric Biggers static void polyval_preparekey_arch(struct polyval_key *key, 2661f66c52SEric Biggers const u8 raw_key[POLYVAL_BLOCK_SIZE]) 2761f66c52SEric Biggers { 2861f66c52SEric Biggers static_assert(ARRAY_SIZE(key->h_powers) == NUM_H_POWERS); 2961f66c52SEric Biggers memcpy(&key->h_powers[NUM_H_POWERS - 1], raw_key, POLYVAL_BLOCK_SIZE); 3061f66c52SEric Biggers if (static_branch_likely(&have_pmull) && may_use_simd()) { 3161f66c52SEric Biggers scoped_ksimd() { 3261f66c52SEric Biggers for (int i = NUM_H_POWERS - 2; i >= 0; i--) { 3361f66c52SEric Biggers key->h_powers[i] = key->h_powers[i + 1]; 3461f66c52SEric Biggers polyval_mul_pmull( 3561f66c52SEric Biggers &key->h_powers[i], 3661f66c52SEric Biggers &key->h_powers[NUM_H_POWERS - 1]); 3761f66c52SEric Biggers } 3861f66c52SEric Biggers } 3961f66c52SEric Biggers } else { 4061f66c52SEric Biggers for (int i = NUM_H_POWERS - 2; i >= 0; i--) { 4161f66c52SEric Biggers key->h_powers[i] = key->h_powers[i + 1]; 4261f66c52SEric Biggers polyval_mul_generic(&key->h_powers[i], 4361f66c52SEric Biggers &key->h_powers[NUM_H_POWERS - 1]); 4461f66c52SEric Biggers } 4561f66c52SEric Biggers } 4661f66c52SEric Biggers } 4761f66c52SEric Biggers 48a336c01fSEric Biggers static void polyval_mul_arm64(struct polyval_elem *a, 49a336c01fSEric Biggers const struct polyval_elem *b) 50a336c01fSEric Biggers { 51a336c01fSEric Biggers if (static_branch_likely(&have_asimd) && may_use_simd()) { 52a336c01fSEric Biggers static const u8 zeroes[GHASH_BLOCK_SIZE]; 53a336c01fSEric Biggers 54a336c01fSEric Biggers scoped_ksimd() { 55a336c01fSEric Biggers if (static_branch_likely(&have_pmull)) { 56a336c01fSEric Biggers polyval_mul_pmull(a, b); 57a336c01fSEric Biggers } else { 58a336c01fSEric Biggers /* 59a336c01fSEric Biggers * Note that this is indeed equivalent to a 60a336c01fSEric Biggers * POLYVAL multiplication, since it takes the 61a336c01fSEric Biggers * accumulator and key in POLYVAL format, and 62a336c01fSEric Biggers * byte-swapping a block of zeroes is a no-op. 63a336c01fSEric Biggers */ 64a336c01fSEric Biggers pmull_ghash_update_p8(1, a, zeroes, b); 65a336c01fSEric Biggers } 66a336c01fSEric Biggers } 67a336c01fSEric Biggers } else { 68a336c01fSEric Biggers polyval_mul_generic(a, b); 69a336c01fSEric Biggers } 70a336c01fSEric Biggers } 71a336c01fSEric Biggers 72a336c01fSEric Biggers #define ghash_mul_arch ghash_mul_arch 73a336c01fSEric Biggers static void ghash_mul_arch(struct polyval_elem *acc, 74a336c01fSEric Biggers const struct ghash_key *key) 75a336c01fSEric Biggers { 76a336c01fSEric Biggers polyval_mul_arm64(acc, &key->h); 77a336c01fSEric Biggers } 78a336c01fSEric Biggers 79b3b6e8f9SEric Biggers #define polyval_mul_arch polyval_mul_arch 8061f66c52SEric Biggers static void polyval_mul_arch(struct polyval_elem *acc, 8161f66c52SEric Biggers const struct polyval_key *key) 8261f66c52SEric Biggers { 83a336c01fSEric Biggers polyval_mul_arm64(acc, &key->h_powers[NUM_H_POWERS - 1]); 84a336c01fSEric Biggers } 85a336c01fSEric Biggers 86a336c01fSEric Biggers #define ghash_blocks_arch ghash_blocks_arch 87a336c01fSEric Biggers static void ghash_blocks_arch(struct polyval_elem *acc, 88a336c01fSEric Biggers const struct ghash_key *key, 89a336c01fSEric Biggers const u8 *data, size_t nblocks) 90a336c01fSEric Biggers { 91a336c01fSEric Biggers if (static_branch_likely(&have_asimd) && may_use_simd()) { 9261f66c52SEric Biggers scoped_ksimd() 93*d3a5cc5cSEric Biggers pmull_ghash_update_p8(nblocks, acc, data, &key->h); 9461f66c52SEric Biggers } else { 95a336c01fSEric Biggers ghash_blocks_generic(acc, &key->h, data, nblocks); 9661f66c52SEric Biggers } 9761f66c52SEric Biggers } 9861f66c52SEric Biggers 99b3b6e8f9SEric Biggers #define polyval_blocks_arch polyval_blocks_arch 10061f66c52SEric Biggers static void polyval_blocks_arch(struct polyval_elem *acc, 10161f66c52SEric Biggers const struct polyval_key *key, 10261f66c52SEric Biggers const u8 *data, size_t nblocks) 10361f66c52SEric Biggers { 10461f66c52SEric Biggers if (static_branch_likely(&have_pmull) && may_use_simd()) { 10561f66c52SEric Biggers scoped_ksimd() 106*d3a5cc5cSEric Biggers polyval_blocks_pmull(acc, key, data, nblocks); 10761f66c52SEric Biggers } else { 10861f66c52SEric Biggers polyval_blocks_generic(acc, &key->h_powers[NUM_H_POWERS - 1], 10961f66c52SEric Biggers data, nblocks); 11061f66c52SEric Biggers } 11161f66c52SEric Biggers } 11261f66c52SEric Biggers 11361f66c52SEric Biggers #define gf128hash_mod_init_arch gf128hash_mod_init_arch 11461f66c52SEric Biggers static void gf128hash_mod_init_arch(void) 11561f66c52SEric Biggers { 116a336c01fSEric Biggers if (cpu_have_named_feature(ASIMD)) { 117a336c01fSEric Biggers static_branch_enable(&have_asimd); 11861f66c52SEric Biggers if (cpu_have_named_feature(PMULL)) 11961f66c52SEric Biggers static_branch_enable(&have_pmull); 12061f66c52SEric Biggers } 121a336c01fSEric Biggers } 122