Path: blob/main/sys/contrib/openzfs/module/icp/include/generic_impl.c
48529 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (c) 2003, 2010 Oracle and/or its affiliates.24* Copyright (c) 2022 Tino Reichardt <[email protected]>25*/2627/*28* This file gets included by c files for implementing the full set29* of zfs_impl.h defines.30*31* It's ment for easier maintaining multiple implementations of32* algorithms. Look into blake3_impl.c, sha256_impl.c or sha512_impl.c33* for reference.34*/3536#include <sys/zfs_context.h>37#include <sys/zio_checksum.h>38#include <sys/zfs_impl.h>3940/* Two default implementations */41#define IMPL_FASTEST (UINT32_MAX)42#define IMPL_CYCLE (UINT32_MAX - 1)4344#define IMPL_READ(i) (*(volatile uint32_t *) &(i))4546/* Implementation that contains the fastest method */47static IMPL_OPS_T generic_fastest_impl = {48.name = "fastest"49};5051/* Hold all supported implementations */52static const IMPL_OPS_T *generic_supp_impls[ARRAY_SIZE(IMPL_ARRAY)];53static uint32_t generic_supp_impls_cnt = 0;5455/* Currently selected implementation */56static uint32_t generic_impl_chosen = IMPL_FASTEST;5758static struct generic_impl_selector {59const char *name;60uint32_t sel;61} generic_impl_selectors[] = {62{ "cycle", IMPL_CYCLE },63{ "fastest", IMPL_FASTEST }64};6566/* check the supported implementations */67static void68generic_impl_init(void)69{70int i, c;7172/* init only once */73if (likely(generic_supp_impls_cnt != 0))74return;7576/* Move supported implementations into generic_supp_impls */77for (i = 0, c = 0; i < ARRAY_SIZE(IMPL_ARRAY); i++) {78const IMPL_OPS_T *impl = IMPL_ARRAY[i];7980if (impl->is_supported && impl->is_supported())81generic_supp_impls[c++] = impl;82}83generic_supp_impls_cnt = c;8485/* first init generic impl, may be changed via set_fastest() */86memcpy(&generic_fastest_impl, generic_supp_impls[0],87sizeof (generic_fastest_impl));88}8990/* get number of supported implementations */91static uint32_t92generic_impl_getcnt(void)93{94generic_impl_init();95return (generic_supp_impls_cnt);96}9798/* get id of selected implementation */99static uint32_t100generic_impl_getid(void)101{102generic_impl_init();103return (IMPL_READ(generic_impl_chosen));104}105106/* get name of selected implementation */107static const char *108generic_impl_getname(void)109{110uint32_t impl = IMPL_READ(generic_impl_chosen);111112generic_impl_init();113switch (impl) {114case IMPL_FASTEST:115return ("fastest");116case IMPL_CYCLE:117return ("cycle");118default:119return (generic_supp_impls[impl]->name);120}121}122123/* set implementation by id */124static void125generic_impl_setid(uint32_t id)126{127generic_impl_init();128switch (id) {129case IMPL_FASTEST:130atomic_swap_32(&generic_impl_chosen, IMPL_FASTEST);131break;132case IMPL_CYCLE:133atomic_swap_32(&generic_impl_chosen, IMPL_CYCLE);134break;135default:136ASSERT3U(id, <, generic_supp_impls_cnt);137atomic_swap_32(&generic_impl_chosen, id);138break;139}140}141142/* set implementation by name */143static int144generic_impl_setname(const char *val)145{146uint32_t impl = IMPL_READ(generic_impl_chosen);147size_t val_len;148int i, err = -EINVAL;149150generic_impl_init();151val_len = strlen(val);152while ((val_len > 0) && !!isspace(val[val_len-1])) /* trim '\n' */153val_len--;154155/* check mandatory implementations */156for (i = 0; i < ARRAY_SIZE(generic_impl_selectors); i++) {157const char *name = generic_impl_selectors[i].name;158159if (val_len == strlen(name) &&160strncmp(val, name, val_len) == 0) {161impl = generic_impl_selectors[i].sel;162err = 0;163break;164}165}166167/* check all supported implementations */168if (err != 0) {169for (i = 0; i < generic_supp_impls_cnt; i++) {170const char *name = generic_supp_impls[i]->name;171172if (val_len == strlen(name) &&173strncmp(val, name, val_len) == 0) {174impl = i;175err = 0;176break;177}178}179}180181if (err == 0) {182atomic_swap_32(&generic_impl_chosen, impl);183}184185return (err);186}187188/* setup id as fastest implementation */189static void190generic_impl_set_fastest(uint32_t id)191{192generic_impl_init();193memcpy(&generic_fastest_impl, generic_supp_impls[id],194sizeof (generic_fastest_impl));195}196197/* return impl iterating functions */198const zfs_impl_t ZFS_IMPL_OPS = {199.name = IMPL_NAME,200.getcnt = generic_impl_getcnt,201.getid = generic_impl_getid,202.getname = generic_impl_getname,203.set_fastest = generic_impl_set_fastest,204.setid = generic_impl_setid,205.setname = generic_impl_setname206};207208/* get impl ops_t of selected implementation */209const IMPL_OPS_T *210IMPL_GET_OPS(void)211{212const IMPL_OPS_T *ops = NULL;213uint32_t idx, impl = IMPL_READ(generic_impl_chosen);214static uint32_t cycle_count = 0;215216generic_impl_init();217switch (impl) {218case IMPL_FASTEST:219ops = &generic_fastest_impl;220break;221case IMPL_CYCLE:222idx = (++cycle_count) % generic_supp_impls_cnt;223ops = generic_supp_impls[idx];224break;225default:226ASSERT3U(impl, <, generic_supp_impls_cnt);227ops = generic_supp_impls[impl];228break;229}230231ASSERT3P(ops, !=, NULL);232return (ops);233}234235236