1*73f315c1SEric Biggers /* SPDX-License-Identifier: GPL-2.0 */ 2*73f315c1SEric Biggers /* 3*73f315c1SEric Biggers * GHASH routines supporting VMX instructions on the Power 8 4*73f315c1SEric Biggers * 5*73f315c1SEric Biggers * Copyright (C) 2015, 2019 International Business Machines Inc. 6*73f315c1SEric Biggers * Copyright (C) 2014 - 2018 Linaro Ltd. 7*73f315c1SEric Biggers * Copyright 2026 Google LLC 8*73f315c1SEric Biggers */ 9*73f315c1SEric Biggers 10*73f315c1SEric Biggers #include <asm/simd.h> 11*73f315c1SEric Biggers #include <asm/switch_to.h> 12*73f315c1SEric Biggers #include <linux/cpufeature.h> 13*73f315c1SEric Biggers #include <linux/jump_label.h> 14*73f315c1SEric Biggers #include <linux/preempt.h> 15*73f315c1SEric Biggers #include <linux/uaccess.h> 16*73f315c1SEric Biggers 17*73f315c1SEric Biggers static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_vec_crypto); 18*73f315c1SEric Biggers 19*73f315c1SEric Biggers void gcm_init_p8(u64 htable[4][2], const u8 h[16]); 20*73f315c1SEric Biggers void gcm_gmult_p8(u8 Xi[16], const u64 htable[4][2]); 21*73f315c1SEric Biggers void gcm_ghash_p8(u8 Xi[16], const u64 htable[4][2], const u8 *in, size_t len); 22*73f315c1SEric Biggers 23*73f315c1SEric Biggers #define ghash_preparekey_arch ghash_preparekey_arch 24*73f315c1SEric Biggers static void ghash_preparekey_arch(struct ghash_key *key, 25*73f315c1SEric Biggers const u8 raw_key[GHASH_BLOCK_SIZE]) 26*73f315c1SEric Biggers { 27*73f315c1SEric Biggers ghash_key_to_polyval(raw_key, &key->h); 28*73f315c1SEric Biggers 29*73f315c1SEric Biggers if (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) { 30*73f315c1SEric Biggers preempt_disable(); 31*73f315c1SEric Biggers pagefault_disable(); 32*73f315c1SEric Biggers enable_kernel_vsx(); 33*73f315c1SEric Biggers gcm_init_p8(key->htable, raw_key); 34*73f315c1SEric Biggers disable_kernel_vsx(); 35*73f315c1SEric Biggers pagefault_enable(); 36*73f315c1SEric Biggers preempt_enable(); 37*73f315c1SEric Biggers } else { 38*73f315c1SEric Biggers /* This reproduces gcm_init_p8() on both LE and BE systems. */ 39*73f315c1SEric Biggers key->htable[0][0] = 0; 40*73f315c1SEric Biggers key->htable[0][1] = 0xc200000000000000; 41*73f315c1SEric Biggers 42*73f315c1SEric Biggers key->htable[1][0] = 0; 43*73f315c1SEric Biggers key->htable[1][1] = le64_to_cpu(key->h.lo); 44*73f315c1SEric Biggers 45*73f315c1SEric Biggers key->htable[2][0] = le64_to_cpu(key->h.lo); 46*73f315c1SEric Biggers key->htable[2][1] = le64_to_cpu(key->h.hi); 47*73f315c1SEric Biggers 48*73f315c1SEric Biggers key->htable[3][0] = le64_to_cpu(key->h.hi); 49*73f315c1SEric Biggers key->htable[3][1] = 0; 50*73f315c1SEric Biggers } 51*73f315c1SEric Biggers } 52*73f315c1SEric Biggers 53*73f315c1SEric Biggers #define ghash_mul_arch ghash_mul_arch 54*73f315c1SEric Biggers static void ghash_mul_arch(struct polyval_elem *acc, 55*73f315c1SEric Biggers const struct ghash_key *key) 56*73f315c1SEric Biggers { 57*73f315c1SEric Biggers if (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) { 58*73f315c1SEric Biggers u8 ghash_acc[GHASH_BLOCK_SIZE]; 59*73f315c1SEric Biggers 60*73f315c1SEric Biggers polyval_acc_to_ghash(acc, ghash_acc); 61*73f315c1SEric Biggers 62*73f315c1SEric Biggers preempt_disable(); 63*73f315c1SEric Biggers pagefault_disable(); 64*73f315c1SEric Biggers enable_kernel_vsx(); 65*73f315c1SEric Biggers gcm_gmult_p8(ghash_acc, key->htable); 66*73f315c1SEric Biggers disable_kernel_vsx(); 67*73f315c1SEric Biggers pagefault_enable(); 68*73f315c1SEric Biggers preempt_enable(); 69*73f315c1SEric Biggers 70*73f315c1SEric Biggers ghash_acc_to_polyval(ghash_acc, acc); 71*73f315c1SEric Biggers memzero_explicit(ghash_acc, sizeof(ghash_acc)); 72*73f315c1SEric Biggers } else { 73*73f315c1SEric Biggers polyval_mul_generic(acc, &key->h); 74*73f315c1SEric Biggers } 75*73f315c1SEric Biggers } 76*73f315c1SEric Biggers 77*73f315c1SEric Biggers #define ghash_blocks_arch ghash_blocks_arch 78*73f315c1SEric Biggers static void ghash_blocks_arch(struct polyval_elem *acc, 79*73f315c1SEric Biggers const struct ghash_key *key, 80*73f315c1SEric Biggers const u8 *data, size_t nblocks) 81*73f315c1SEric Biggers { 82*73f315c1SEric Biggers if (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) { 83*73f315c1SEric Biggers u8 ghash_acc[GHASH_BLOCK_SIZE]; 84*73f315c1SEric Biggers 85*73f315c1SEric Biggers polyval_acc_to_ghash(acc, ghash_acc); 86*73f315c1SEric Biggers 87*73f315c1SEric Biggers preempt_disable(); 88*73f315c1SEric Biggers pagefault_disable(); 89*73f315c1SEric Biggers enable_kernel_vsx(); 90*73f315c1SEric Biggers gcm_ghash_p8(ghash_acc, key->htable, data, 91*73f315c1SEric Biggers nblocks * GHASH_BLOCK_SIZE); 92*73f315c1SEric Biggers disable_kernel_vsx(); 93*73f315c1SEric Biggers pagefault_enable(); 94*73f315c1SEric Biggers preempt_enable(); 95*73f315c1SEric Biggers 96*73f315c1SEric Biggers ghash_acc_to_polyval(ghash_acc, acc); 97*73f315c1SEric Biggers memzero_explicit(ghash_acc, sizeof(ghash_acc)); 98*73f315c1SEric Biggers } else { 99*73f315c1SEric Biggers ghash_blocks_generic(acc, &key->h, data, nblocks); 100*73f315c1SEric Biggers } 101*73f315c1SEric Biggers } 102*73f315c1SEric Biggers 103*73f315c1SEric Biggers #define gf128hash_mod_init_arch gf128hash_mod_init_arch 104*73f315c1SEric Biggers static void gf128hash_mod_init_arch(void) 105*73f315c1SEric Biggers { 106*73f315c1SEric Biggers if (cpu_has_feature(CPU_FTR_ARCH_207S) && 107*73f315c1SEric Biggers (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_VEC_CRYPTO)) 108*73f315c1SEric Biggers static_branch_enable(&have_vec_crypto); 109*73f315c1SEric Biggers } 110