After the dynamic loading function is added, device resource initialization, driver acquisition, and scheduler initialization functions need to be extracted into the public framework.
so that the algorithm can quickly adapt to the dynamic loading function internally.
Signed-off-by: Longfang Liu liulongfang@huawei.com --- include/wd_alg_common.h | 10 + include/wd_util.h | 63 ++++- wd_comp.c | 2 +- wd_util.c | 549 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 620 insertions(+), 4 deletions(-)
diff --git a/include/wd_alg_common.h b/include/wd_alg_common.h index d04b046..31208ad 100644 --- a/include/wd_alg_common.h +++ b/include/wd_alg_common.h @@ -28,6 +28,13 @@ extern "C" { #define CTX_TYPE_INVALID 9999 #define POLL_TIME 1000
+enum alg_task_type { + TASK_MIX = 0x0, + TASK_HW, + TASK_INSTR, + TASK_MAX_TYPE, +}; + enum wd_ctx_mode { CTX_MODE_SYNC = 0, CTX_MODE_ASYNC, @@ -130,6 +137,9 @@ struct wd_sched { handle_t h_sched_ctx; };
+typedef int (*wd_alg_init)(struct wd_ctx_config *config, struct wd_sched *sched); +typedef int (*wd_alg_poll_ctx)(__u32 idx, __u32 expt, __u32 *count); + struct wd_datalist { void *data; __u32 len; diff --git a/include/wd_util.h b/include/wd_util.h index d4b2814..a730f36 100644 --- a/include/wd_util.h +++ b/include/wd_util.h @@ -117,9 +117,12 @@ struct wd_msg_handle { struct wd_init_attrs { __u32 sched_type; char *alg; + struct wd_alg_driver *driver; struct wd_sched *sched; struct wd_ctx_params *ctx_params; struct wd_ctx_config *ctx_config; + wd_alg_init alg_init; + wd_alg_poll_ctx alg_poll_ctx; };
/* @@ -415,13 +418,69 @@ static inline void wd_alg_clear_init(enum wd_status *status) }
/** - * wd_alg_pre_init() - Request the ctxs and initialize the sched_domain + * wd_ctx_param_init() - Initialize the current device driver according + * to the obtained queue resource and the applied driver. + * @config: device resources requested by the current algorithm. + * @driver: device driver for the current algorithm application. + * @drv_priv: the parameter pointer of the current device driver. + * + * Return 0 if succeed and other error number if fail. + */ +int wd_ctx_param_init(struct wd_ctx_params *ctx_params, + struct wd_ctx_params *user_ctx_params, + struct wd_ctx_nums *ctx_set_num, + struct wd_alg_driver *driver, int max_op_type); + +/** + * wd_alg_attrs_init() - Request the ctxs and initialize the sched_domain * with the given devices list, ctxs number and numa mask. * @attrs: the algorithm initialization parameters. * * Return device if succeed and other error number if fail. */ -int wd_alg_pre_init(struct wd_init_attrs *attrs); +int wd_alg_attrs_init(struct wd_init_attrs *attrs); +void wd_alg_attrs_uninit(struct wd_init_attrs *attrs); + +/** + * wd_alg_drv_bind() - Request the ctxs and initialize the sched_domain + * with the given devices list, ctxs number and numa mask. + * @task_type: the type of task specified by the current algorithm. + * @alg_name: the name of the algorithm specified by the task. + * + * Return device driver if succeed and other NULL if fail. + */ +struct wd_alg_driver *wd_alg_drv_bind(int task_type, char *alg_name); +void wd_alg_drv_unbind(struct wd_alg_driver *drv); + +/** + * wd_alg_init_driver() - Initialize the current device driver according + * to the obtained queue resource and the applied driver. + * @config: device resources requested by the current algorithm. + * @driver: device driver for the current algorithm application. + * @drv_priv: the parameter pointer of the current device driver. + * + * Return 0 if succeed and other error number if fail. + */ +int wd_alg_init_driver(struct wd_ctx_config_internal *config, + struct wd_alg_driver *driver, void **drv_priv); +void wd_alg_uninit_driver(struct wd_ctx_config_internal *config, + struct wd_alg_driver *driver, void **drv_priv); + +/** + * wd_dlopen_drv() - Open the dynamic library file of the device driver. + * @cust_lib_dir: the file path of the dynamic library file. + */ +void *wd_dlopen_drv(const char *cust_lib_dir); +void wd_dlclose_drv(void *dlh_list); + +/** + * wd_get_lib_file_path() - Find the path of the dynamic library file in + * the current system. + * @lib_file: the name of the library file. + * @lib_path: the found dynamic library file path. + * @is_dir: Specify whether to query the file dir or the file path. + */ +int wd_get_lib_file_path(char *lib_file, char *lib_path, bool is_dir);
/** * wd_dfx_msg_cnt() - Message counter interface for ctx diff --git a/wd_comp.c b/wd_comp.c index cca6eb9..ecfa573 100644 --- a/wd_comp.c +++ b/wd_comp.c @@ -248,7 +248,7 @@ int wd_comp_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_par wd_comp_sched->name = SCHED_RR_NAME; wd_comp_init_attrs.sched = wd_comp_sched;
- ret = wd_alg_pre_init(&wd_comp_init_attrs); + ret = wd_alg_attrs_init(&wd_comp_init_attrs); if (ret) goto out_freesched;
diff --git a/wd_util.c b/wd_util.c index 433dd56..dab4fc8 100644 --- a/wd_util.c +++ b/wd_util.c @@ -5,6 +5,8 @@ */
#define _GNU_SOURCE +#include <dirent.h> +#include <dlfcn.h> #include <pthread.h> #include <semaphore.h> #include <string.h> @@ -23,6 +25,8 @@ #define WD_INIT_SLEEP_UTIME 1000 #define WD_INIT_RETRY_TIMES 10000
+#define DEF_DRV_LIB_FILE "libwd.so" + struct msg_pool { /* message array allocated dynamically */ void *msgs; @@ -64,6 +68,72 @@ struct async_task_queue { int (*alg_poll_ctx)(__u32, __u32, __u32 *); };
+struct drv_lib_list { + void *dlhandle; + struct drv_lib_list *next; +}; + +struct acc_alg_item { + char *name; + char *algtype; +}; + +static struct acc_alg_item alg_options[] = { + {"zlib", "zlib-deflate"}, + {"gzip", "gzip"}, + {"deflate", "deflate"}, + {"lz77_zstd", "lz77_zstd"}, + + {"rsa", "rsa"}, + {"dh", "dh"}, + {"ecdh", "ecdh"}, + {"x25519", "x25519"}, + {"x448", "x448"}, + {"ecdsa", "ecdsa"}, + {"sm2", "sm2"}, + + {"ecb(aes)", "cipher"}, + {"cbc(aes)", "cipher"}, + {"xts(aes)", "cipher"}, + {"ofb(aes)", "cipher"}, + {"cfb(aes)", "cipher"}, + {"ctr(aes)", "cipher"}, + {"cbc-cs1(aes)", "cipher"}, + {"cbc-cs2(aes)", "cipher"}, + {"cbc-cs3(aes)", "cipher"}, + {"ecb(sm4)", "cipher"}, + {"xts(sm4)", "cipher"}, + {"cbc(sm4)", "cipher"}, + {"ofb(sm4)", "cipher"}, + {"cfb(sm4)", "cipher"}, + {"ctr(sm4)", "cipher"}, + {"cbc-cs1(sm4)", "cipher"}, + {"cbc-cs2(sm4)", "cipher"}, + {"cbc-cs3(sm4)", "cipher"}, + {"ecb(des)", "cipher"}, + {"cbc(des)", "cipher"}, + {"ecb(des3_ede)", "cipher"}, + {"cbc(des3_ede)", "cipher"}, + + {"ccm(aes)", "aead"}, + {"gcm(aes)", "aead"}, + {"ccm(sm4)", "aead"}, + {"gcm(sm4)", "aead"}, + {"authenc(hmac(sha256),cbc(aes))", "aead"}, + {"authenc(hmac(sha256),cbc(sm4))", "aead"}, + + {"sm3", "digest"}, + {"md5", "digest"}, + {"sha1", "digest"}, + {"sha256", "digest"}, + {"sha224", "digest"}, + {"sha384", "digest"}, + {"sha512", "digest"}, + {"sha512-224", "digest"}, + {"sha512-256", "digest"}, + {"", ""} +}; + static void clone_ctx_to_internal(struct wd_ctx *ctx, struct wd_ctx_internal *ctx_in) { @@ -1779,6 +1849,358 @@ int wd_init_param_check(struct wd_ctx_config *config, struct wd_sched *sched) return 0; }
+static void wd_get_alg_type(const char *alg_name, char *alg_type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(alg_options); i++) { + if (strcmp(alg_name, alg_options[i].name) == 0) { + (void)strcpy(alg_type, alg_options[i].algtype); + break; + } + } +} + +/** + * There are many other .so files in this file directory (/root/lib/), + * and it is necessary to screen out valid uadk driver files + * through this function. + */ +static int file_check_valid(char *lib_file) +{ +#define FILE_HEAD_SZ 4 +#define FILE_TAIL_SZ 4 + int file_len = strlen(lib_file); + char file_head[FILE_HEAD_SZ] = "lib"; + char file_tail[FILE_TAIL_SZ] = ".so"; + int i, j; + + /* Lib file name is libxx_xxx.so */ + for (i = 0; i < FILE_HEAD_SZ - 1; i++) { + if (lib_file[i] != file_head[i]) + return -EINVAL; + } + + for (i = file_len - (FILE_TAIL_SZ - 1), j = 0; + i < file_len && j < FILE_TAIL_SZ; i++, j++) { + if (lib_file[i] != file_tail[j]) + return -EINVAL; + } + + return 0; +} + +static int wd_alg_init_fallback(struct wd_alg_driver *fb_driver) +{ + if (!fb_driver->init) { + WD_ERR("soft sec driver have no init interface.\n"); + return -WD_EINVAL; + } + + fb_driver->init(NULL, NULL); + + return 0; +} + +static void wd_alg_uninit_fallback(struct wd_alg_driver *fb_driver) +{ + if (!fb_driver->exit) { + WD_ERR("soft sec driver have no exit interface.\n"); + return; + } + + fb_driver->exit(NULL); +} + +int wd_alg_init_driver(struct wd_ctx_config_internal *config, + struct wd_alg_driver *driver, void **drv_priv) +{ + void *priv; + int ret; + + /* Init ctx related resources in specific driver */ + priv = calloc(1, driver->priv_size); + if (!priv) + return -WD_ENOMEM; + + if (!driver->init) { + driver->fallback = 0; + WD_ERR("driver have no init interface.\n"); + ret = -WD_EINVAL; + goto err_alloc; + } + + ret = driver->init(config, priv); + if (ret < 0) { + WD_ERR("driver init failed.\n"); + goto err_alloc; + } + + if (driver->fallback) { + ret = wd_alg_init_fallback((struct wd_alg_driver *)driver->fallback); + if (ret) { + driver->fallback = 0; + WD_ERR("soft alg driver init failed.\n"); + } + } + *drv_priv = priv; + + return 0; + +err_alloc: + free(priv); + return ret; +} + +void wd_alg_uninit_driver(struct wd_ctx_config_internal *config, + struct wd_alg_driver *driver, void **drv_priv) +{ + void *priv = *drv_priv; + + driver->exit(priv); + /* Ctx config just need clear once */ + if (driver->priority == UADK_ALG_HW) + wd_clear_ctx_config(config); + + if (driver->fallback) + wd_alg_uninit_fallback((struct wd_alg_driver *)driver->fallback); + + if (priv) { + free(priv); + priv = NULL; + } +} + +void wd_dlclose_drv(void *dlh_list) +{ + struct drv_lib_list *dlhead = (struct drv_lib_list *)dlh_list; + struct drv_lib_list *dlnode; + + if (!dlhead) { + WD_INFO("driver so file list is empty.\n"); + return; + } + + while (dlhead) { + dlnode = dlhead; + dlhead = dlhead->next; + dlclose(dlnode); + free(dlnode); + } +} + +static void add_lib_to_list(struct drv_lib_list *head, + struct drv_lib_list *node) +{ + struct drv_lib_list *tmp = head; + + while (tmp->next) + tmp = tmp->next; + + tmp->next = node; +} + +int wd_ctx_param_init(struct wd_ctx_params *ctx_params, + struct wd_ctx_params *user_ctx_params, + struct wd_ctx_nums *ctx_set_num, + struct wd_alg_driver *driver, int max_op_type) +{ + int i; + + if (!user_ctx_params) { + ctx_params->bmp = NULL; + ctx_params->ctx_set_num = ctx_set_num; + ctx_params->op_type_num = driver->op_type_num; + if (ctx_params->op_type_num > max_op_type) { + WD_ERR("fail to check driver op type numbers.\n"); + return -WD_EAGAIN; + } + + for (i = 0; i < ctx_params->op_type_num; i++) { + ctx_set_num[i].sync_ctx_num = driver->queue_num; + ctx_set_num[i].async_ctx_num = driver->queue_num; + } + } else { + ctx_params->bmp = user_ctx_params->bmp; + ctx_params->ctx_set_num = user_ctx_params->ctx_set_num; + ctx_params->op_type_num = user_ctx_params->op_type_num; + if (ctx_params->op_type_num > max_op_type) { + WD_ERR("fail to check user op type numbers.\n"); + return -WD_EINVAL; + } + } + + return 0; +} + +static void dladdr_empty(void) {} +int wd_get_lib_file_path(char *lib_file, char *lib_path, bool is_dir) +{ + char file_path[PATH_STR_SIZE] = {0}; + Dl_info file_info; + int len, rc, i; + + /* Get libwd.so file's system path */ + rc = dladdr((void *)dladdr_empty, &file_info); + if (!rc) { + WD_ERR("fail to get lib file path.\n"); + return -WD_EINVAL; + } + strncpy(file_path, file_info.dli_fname, PATH_STR_SIZE - 1); + + /* Clear the file path's tail file name */ + len = strlen(file_path) - 1; + for (i = len; i >= 0; i--) { + if (file_path[i] == '/') { + memset(&file_path[i], 0, PATH_STR_SIZE - i + 1); + break; + } + } + + if (is_dir) { + (void)snprintf(lib_path, PATH_STR_SIZE, "%s", file_path); + return 0; + } + + len = snprintf(lib_path, PATH_STR_SIZE, "%s/%s", file_path, lib_file); + if (len < 0) + return -WD_EINVAL; + + return 0; +} + +void *wd_dlopen_drv(const char *cust_lib_dir) +{ + typedef int (*alg_ops)(struct wd_alg_driver *drv); + struct drv_lib_list *node, *head = NULL; + char lib_dir_path[PATH_STR_SIZE] = {0}; + char lib_path[PATH_STR_SIZE] = {0}; + struct dirent *lib_dir; + alg_ops dl_func = NULL; + DIR *wd_dir; + int ret; + + if (!cust_lib_dir) { + ret = wd_get_lib_file_path(NULL, lib_dir_path, true); + if (ret) + return NULL; + } else { + (void)snprintf(lib_path, PATH_STR_SIZE, "%s/%s", cust_lib_dir, DEF_DRV_LIB_FILE); + ret = access(lib_path, F_OK); + if (ret) + return NULL; + + strncpy(lib_dir_path, cust_lib_dir, PATH_STR_SIZE - 1); + } + + wd_dir = opendir(lib_dir_path); + if (!wd_dir) { + WD_ERR("UADK driver lib dir: %s not exist!\n", lib_dir_path); + return NULL; + } + + while ((lib_dir = readdir(wd_dir)) != NULL) { + if (!strncmp(lib_dir->d_name, ".", LINUX_CRTDIR_SIZE) || + !strncmp(lib_dir->d_name, "..", LINUX_PRTDIR_SIZE)) + continue; + + ret = file_check_valid(lib_dir->d_name); + if (ret) + continue; + + node = calloc(1, sizeof(*node)); + if (!node) + goto free_list; + + ret = snprintf(lib_path, PATH_STR_SIZE, "%s/%s", lib_dir_path, lib_dir->d_name); + if (ret < 0) + goto free_node; + + node->dlhandle = dlopen(lib_path, RTLD_NOW); + if (!node->dlhandle) { + free(node); + /* there are many other files need to skip */ + continue; + } + + dl_func = dlsym(node->dlhandle, "wd_alg_driver_register"); + if (dl_func == NULL) { + dlclose(node->dlhandle); + free(node); + continue; + } + + if (!head) + head = node; + else + add_lib_to_list(head, node); + } + closedir(wd_dir); + + return (void *)head; + +free_node: + free(node); +free_list: + closedir(wd_dir); + wd_dlclose_drv(head); + return NULL; +} + +struct wd_alg_driver *wd_alg_drv_bind(int task_type, char *alg_name) +{ + struct wd_alg_driver *set_driver = NULL; + struct wd_alg_driver *drv; + + /* Get alg driver and dev name */ + switch (task_type) { + case TASK_INSTR: + drv = wd_request_drv(alg_name, true); + if (!drv) { + WD_ERR("no soft %s driver support\n", alg_name); + return NULL; + } + set_driver = drv; + set_driver->fallback = 0; + break; + case TASK_HW: + case TASK_MIX: + drv = wd_request_drv(alg_name, false); + if (!drv) { + WD_ERR("no HW %s driver support\n", alg_name); + return NULL; + } + set_driver = drv; + set_driver->fallback = 0; + if (task_type == TASK_MIX) { + drv = wd_request_drv(alg_name, true); + if (!drv) { + set_driver->fallback = 0; + WD_ERR("no soft %s driver support\n", alg_name); + } else { + set_driver->fallback = (handle_t)drv; + WD_ERR("successful to get soft driver\n"); + } + } + break; + } + + return set_driver; +} + +void wd_alg_drv_unbind(struct wd_alg_driver *drv) +{ + struct wd_alg_driver *fb_drv = NULL; + + if (!drv) + return; + + fb_drv = (struct wd_alg_driver *)drv->fallback; + if (fb_drv) + wd_release_drv(fb_drv); + wd_release_drv(drv); +} + bool wd_alg_try_init(enum wd_status *status) { enum wd_status expected; @@ -1960,7 +2382,7 @@ free_ctxs: return ret; }
-int wd_alg_pre_init(struct wd_init_attrs *attrs) +static int wd_alg_ctx_init(struct wd_init_attrs *attrs) { struct wd_ctx_config *ctx_config = attrs->ctx_config; struct wd_ctx_params *ctx_params = attrs->ctx_params; @@ -2034,3 +2456,128 @@ out_freelist:
return ret; } + +static void wd_alg_ctx_uninit(struct wd_ctx_config *ctx_config) +{ + int i; + + for (i = 0; i < ctx_config->ctx_num; i++) + if (ctx_config->ctxs[i].ctx) { + wd_release_ctx(ctx_config->ctxs[i].ctx); + ctx_config->ctxs[i].ctx = 0; + } + + free(ctx_config->ctxs); +} + +int wd_alg_attrs_init(struct wd_init_attrs *attrs) +{ + wd_alg_poll_ctx alg_poll_func = attrs->alg_poll_ctx; + wd_alg_init alg_init_func = attrs->alg_init; + __u32 sched_type = attrs->sched_type; + struct wd_ctx_config *ctx_config = NULL; + struct wd_sched *alg_sched = NULL; + char alg_type[WD_NAME_SIZE]; + char *alg = attrs->alg; + int driver_type = UADK_ALG_HW; + int ret; + + if (!attrs->ctx_params) + return -WD_EINVAL; + + if (attrs->driver) + driver_type = attrs->driver->priority; + + switch (driver_type) { + case UADK_ALG_SOFT: + case UADK_ALG_CE_INSTR: + /* No need to alloc resource */ + if (sched_type != SCHED_POLICY_NONE) + return -WD_EINVAL; + + alg_sched = wd_sched_rr_alloc(SCHED_POLICY_NONE, 1, 1, alg_poll_func); + if (!alg_sched) { + WD_ERR("fail to alloc scheduler\n"); + return -WD_EINVAL; + } + attrs->sched = alg_sched; + + ret = wd_sched_rr_instance(alg_sched, NULL); + if (ret) { + WD_ERR("fail to instance scheduler\n"); + goto out_freesched; + } + break; + case UADK_ALG_SVE_INSTR: + /* Todo lock cpu core */ + if (sched_type != SCHED_POLICY_SINGLE) + return -WD_EINVAL; + + alg_sched = wd_sched_rr_alloc(SCHED_POLICY_SINGLE, 1, 1, alg_poll_func); + if (!alg_sched) { + WD_ERR("fail to alloc scheduler\n"); + return -WD_EINVAL; + } + attrs->sched = alg_sched; + + ret = wd_sched_rr_instance(alg_sched, NULL); + if (ret) { + WD_ERR("fail to instance scheduler\n"); + goto out_freesched; + } + break; + case UADK_ALG_HW: + wd_get_alg_type(alg, alg_type); + attrs->alg = alg_type; + + ctx_config = calloc(1, sizeof(*ctx_config)); + if (!ctx_config) { + WD_ERR("fail to alloc ctx config\n"); + return -WD_ENOMEM; + } + attrs->ctx_config = ctx_config; + + alg_sched = wd_sched_rr_alloc(sched_type, attrs->ctx_params->op_type_num, + numa_max_node() + 1, alg_poll_func); + if (!alg_sched) { + WD_ERR("fail to instance scheduler\n"); + ret = -WD_EINVAL; + goto out_ctx_config; + } + attrs->sched = alg_sched; + + ret = wd_alg_ctx_init(attrs); + if (ret) { + WD_ERR("fail to init ctx\n"); + goto out_freesched; + } + + ret = alg_init_func(ctx_config, alg_sched); + if (ret) + goto out_pre_init; + } + + return 0; + +out_pre_init: + wd_alg_ctx_uninit(ctx_config); +out_freesched: + wd_sched_rr_release(alg_sched); +out_ctx_config: + if (ctx_config) + free(ctx_config); + return ret; +} + +void wd_alg_attrs_uninit(struct wd_init_attrs *attrs) +{ + struct wd_ctx_config *ctx_config = attrs->ctx_config; + struct wd_sched *alg_sched = attrs->sched; + + if (ctx_config) { + wd_alg_ctx_uninit(ctx_config); + free(ctx_config); + } + wd_sched_rr_release(alg_sched); +} +