forked from OP-TEE/optee_os
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers:implement HiSilicon Security Engine(SEC) module.
HiSilicon SEC is used in security applications such as authentication and data encryption and decryption. This module implement the hardware initialization of the SEC. Signed-off-by: leisen <leisen1@huawei.com> Acked-by: Jens Wiklander <jens.wiklander@linaro.org> Acked-by: Etienne Carriere <etienne.carriere@foss.st.com>
- Loading branch information
1 parent
7950274
commit 9b6221a
Showing
3 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* SPDX-License-Identifier: BSD-2-Clause */ | ||
/* Copyright (c) 2022-2024 HiSilicon Limited. */ | ||
#ifndef __SEC_MAIN_H | ||
#define __SEC_MAIN_H | ||
|
||
#include <hisi_qm.h> | ||
|
||
#ifdef CFG_HISILICON_ACC_V3 | ||
#define SEC_BAR 0x160000000 | ||
#else | ||
#define SEC_BAR 0x141800000 | ||
#endif | ||
#define SEC_SIZE 0x400000 | ||
|
||
#define SEC_SQE_SIZE 128 | ||
#define SEC_SQE_LOG2_SIZE 7 | ||
#define AES_KEYSIZE_128 16 | ||
#define AES_KEYSIZE_192 24 | ||
#define AES_KEYSIZE_256 32 | ||
#define SEC_HW_TASK_DONE 0x1 | ||
#define SEC_DONE_MASK 0x0001 | ||
#define SEC_ICV_MASK 0x000E | ||
#define SEC_HW_ICV_ERR 0x2 | ||
#define SEC_ENCODE_BYTES 4 | ||
#define BYTE_BITS 0x8 | ||
|
||
#define SEC_SCENE_OFFSET 3 | ||
#define SEC_DE_OFFSET 1 | ||
#define SEC_CIPHER_OFFSET 4 | ||
#define SEC_AUTH_OFFSET 6 | ||
#define SEC_CMODE_OFFSET 12 | ||
#define SEC_CKEY_OFFSET 9 | ||
#define SEC_AKEY_OFFSET 5 | ||
#define SEC_AEAD_ALG_OFFSET 11 | ||
#define SEC_HUK_OFFSET 4 | ||
#define SEC_APAD_OFFSET 2 | ||
|
||
#define SEC_DE_OFFSET_V3 9 | ||
#define SEC_SCENE_OFFSET_V3 5 | ||
#define SEC_CKEY_OFFSET_V3 13 | ||
#define SEC_CALG_OFFSET_V3 4 | ||
#define SEC_AKEY_OFFSET_V3 9 | ||
#define SEC_MAC_OFFSET_V3 4 | ||
#define SEC_AUTH_ALG_OFFSET_V3 15 | ||
#define SEC_CIPHER_AUTH_V3 0xbf | ||
#define SEC_AUTH_CIPHER_V3 0x40 | ||
#define SEC_AI_GEN_OFFSET_V3 2 | ||
#define SEC_SEQ_OFFSET_V3 6 | ||
#define SEC_ICV_LEN_OFFSET_V3 4 | ||
#define SEC_DK_LEN_OFFSET_V3 16 | ||
#define SEC_KEY_SEL_OFFSET_V3 21 | ||
|
||
/* | ||
* Create task queue pair for SEC. | ||
* | ||
* @sq_type Task type of the submmission queue. | ||
*/ | ||
struct hisi_qp *sec_create_qp(uint8_t sq_type); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
/* | ||
* Copyright 2022-2024 HiSilicon Limited. | ||
* Kunpeng hardware accelerator SEC module init. | ||
*/ | ||
|
||
#include <initcall.h> | ||
#include <io.h> | ||
#include <malloc.h> | ||
#include <sec_main.h> | ||
#include <sys/queue.h> | ||
#include <trace.h> | ||
#include <util.h> | ||
|
||
#define AM_CFG_SINGLE_PORT_MAX_TRANS 0x300014 | ||
#define SEC_CORE_INT_MASK 0x301000 | ||
#define SEC_CORE_INT_SOURCE 0x301010 | ||
#define SEC_RAS_CE_ENABLE 0x301050 | ||
#define SEC_RAS_FE_ENABLE 0x301054 | ||
#define SEC_RAS_NFE_ENABLE 0x301058 | ||
#define SEC_MEM_START_INIT 0x301100 | ||
#define SEC_MEM_INIT_DONE 0x301104 | ||
#define SEC_CONTROL_REG 0x301200 | ||
#define SEC_INTERFACE_USER_CTRL0 0x301220 | ||
#define SEC_INTERFACE_USER_CTRL1 0x301224 | ||
#define SEC_SAA_EN 0x301270 | ||
#define SEC_BD_ERR_CHK_EN0 0x301380 | ||
#define SEC_BD_ERR_CHK_EN1 0x301384 | ||
#define SEC_BD_ERR_CHK_EN2 0x301388 | ||
#define SEC_BD_ERR_CHK_EN3 0x30138c | ||
#define SEC_DYNAMIC_GATE_V3 0x30121c | ||
#define SEC_BD_ERR_CHK_EN2_V3 0x301508 | ||
#define SEC_CORE_AUTO_GATE_V3 0x30212c | ||
#define SEC_INTERFACE_USER_CTRL0_V3 0x302220 | ||
#define SEC_INTERFACE_USER_CTRL1_V3 0x302224 | ||
#define SEC_SINGLE_PORT_MAX_TRANS 0x2060 | ||
#define SEC_ABNML_INT_DISABLE 0x0 | ||
#define SEC_RAS_CE_ENB_MASK 0x88 | ||
#define SEC_RAS_FE_ENB 0x0 | ||
#define SEC_RAS_NFE_ENB_MASK 0x177 | ||
#define SEC_CLK_GATE_ENABLE BIT(3) | ||
#define SEC_DYNAMIC_GATE_EN 0x7bff | ||
#define SEC_CORE_AUTO_GATE_EN GENMASK_32(3, 0) | ||
#define SEC_TRNG_EN_MASK BIT(8) | ||
#define SEC_SAA_ENABLE 0x17f | ||
#define SEC_SAA_ENABLE_V3 0xf | ||
#define SEC_BD_ERR_CHK0 0xefffffff | ||
#define SEC_BD_ERR_CHK1 0x7ffff7fd | ||
#define SEC_BD_ERR_CHK2 0xffff7fff | ||
#define SEC_BD_ERR_CHK3 0xffffbfff | ||
#define SEC_USER0_CFG 0x20200 | ||
#define SEC_USER0_SMMU_NORMAL (BIT(23) | BIT(15)) | ||
#define SEC_USER1_CFG 0x12141214 | ||
#define SEC_USER1_SMMU_NORMAL (BIT(31) | BIT(23) | BIT(15) | BIT(7)) | ||
#define SEC_USER0_CFG_V3 0x20200 | ||
#define SEC_USER1_CFG_V3 0x8c494 | ||
|
||
static SLIST_HEAD(, acc_device) sec_list = SLIST_HEAD_INITIALIZER(sec_list); | ||
|
||
struct hisi_qp *sec_create_qp(uint8_t sq_type) | ||
{ | ||
struct acc_device *sec_dev = NULL; | ||
struct acc_device *cur_dev = NULL; | ||
uint32_t free_qp_num = 0; | ||
uint32_t max_qp_num = 0; | ||
|
||
/* Find the SEC device with the most remaining qp numbers */ | ||
SLIST_FOREACH(cur_dev, &sec_list, link) { | ||
if (cur_dev->qm.fun_type == HISI_QM_HW_PF) | ||
free_qp_num = HISI_QM_PF_Q_NUM - cur_dev->qm.qp_in_used; | ||
else | ||
free_qp_num = HISI_QM_VF_Q_NUM - cur_dev->qm.qp_in_used; | ||
if (free_qp_num > max_qp_num) { | ||
max_qp_num = free_qp_num; | ||
sec_dev = cur_dev; | ||
} | ||
} | ||
|
||
if (!sec_dev) { | ||
EMSG("No available sec device"); | ||
return NULL; | ||
} | ||
|
||
return hisi_qm_create_qp(&sec_dev->qm, sq_type); | ||
} | ||
|
||
static void sec_enable_clock_gate(struct hisi_qm *qm) | ||
{ | ||
if (qm->version == HISI_QM_HW_V2) | ||
return; | ||
|
||
io_setbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE); | ||
io_write32(qm->io_base + SEC_DYNAMIC_GATE_V3, SEC_DYNAMIC_GATE_EN); | ||
io_write32(qm->io_base + SEC_CORE_AUTO_GATE_V3, SEC_CORE_AUTO_GATE_EN); | ||
} | ||
|
||
static enum hisi_drv_status sec_engine_init(struct acc_device *sec_dev) | ||
{ | ||
struct hisi_qm *qm = &sec_dev->qm; | ||
uint32_t val = 0; | ||
|
||
if (qm->fun_type == HISI_QM_HW_VF) | ||
return HISI_QM_DRVCRYPT_NO_ERR; | ||
|
||
/* QM_HW_V2 version need to close clock gating */ | ||
io_clrbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE); | ||
|
||
hisi_qm_dev_init(qm); | ||
|
||
io_write32(qm->io_base + SEC_MEM_START_INIT, 0x1); | ||
if (IO_READ32_POLL_TIMEOUT(qm->io_base + SEC_MEM_INIT_DONE, val, | ||
val & 0x1, POLL_PERIOD, POLL_TIMEOUT)) { | ||
EMSG("Fail to init sec mem"); | ||
return HISI_QM_DRVCRYPT_ETMOUT; | ||
} | ||
|
||
io_setbits32(qm->io_base + SEC_CONTROL_REG, sec_dev->endian); | ||
|
||
if (qm->version == HISI_QM_HW_V2) { | ||
/* SMMU bypass */ | ||
io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0, | ||
SEC_USER0_CFG); | ||
io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1, | ||
SEC_USER1_CFG); | ||
io_write32(qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS, | ||
SEC_SINGLE_PORT_MAX_TRANS); | ||
io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE); | ||
/* HW V2 enable SM4 extra mode, as CTR/ECB */ | ||
io_write32(qm->io_base + SEC_BD_ERR_CHK_EN0, SEC_BD_ERR_CHK0); | ||
/* Enable SM4 xts mode multiple iv */ | ||
io_write32(qm->io_base + SEC_BD_ERR_CHK_EN1, SEC_BD_ERR_CHK1); | ||
/* disable PBKDF2 len check */ | ||
io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2, SEC_BD_ERR_CHK2); | ||
io_write32(qm->io_base + SEC_BD_ERR_CHK_EN3, SEC_BD_ERR_CHK3); | ||
} else { | ||
/* cmd_type is controlled by HAC subctrl, default normal */ | ||
io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0_V3, | ||
SEC_USER0_CFG_V3); | ||
io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1_V3, | ||
SEC_USER1_CFG_V3); | ||
io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE_V3); | ||
/* disable PBKDF2 salt len check */ | ||
io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2_V3, | ||
SEC_BD_ERR_CHK2); | ||
} | ||
io_write32(qm->io_base + SEC_RAS_CE_ENABLE, SEC_RAS_CE_ENB_MASK); | ||
io_write32(qm->io_base + SEC_RAS_FE_ENABLE, SEC_RAS_FE_ENB); | ||
io_write32(qm->io_base + SEC_RAS_NFE_ENABLE, SEC_RAS_NFE_ENB_MASK); | ||
io_write32(qm->io_base + SEC_CORE_INT_MASK, SEC_ABNML_INT_DISABLE); | ||
|
||
sec_enable_clock_gate(qm); | ||
|
||
return HISI_QM_DRVCRYPT_NO_ERR; | ||
} | ||
|
||
static enum hisi_drv_status sec_dev_status_check(struct hisi_qm *qm) | ||
{ | ||
uint32_t val = 0; | ||
|
||
val = io_read32(qm->io_base + SEC_CORE_INT_SOURCE); | ||
if (val & SEC_RAS_NFE_ENB_MASK) { | ||
EMSG("SEC NFE RAS happened, need to reset"); | ||
return HISI_QM_DRVCRYPT_HW_EACCESS; | ||
} | ||
|
||
val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC); | ||
if (val) { | ||
if (val & HISI_QM_SEC_NFE_INT_MASK) | ||
EMSG("QM NFE RAS happened, need to reset"); | ||
|
||
if (val & HISI_QM_INVALID_DB) { | ||
EMSG("QM invalid db happened, please check"); | ||
io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC, | ||
HISI_QM_INVALID_DB); | ||
} | ||
|
||
return HISI_QM_DRVCRYPT_HW_EACCESS; | ||
} | ||
|
||
return HISI_QM_DRVCRYPT_NO_ERR; | ||
} | ||
|
||
static enum hisi_drv_status sec_qm_init(struct acc_device *sec_dev) | ||
{ | ||
struct hisi_qm *qm = &sec_dev->qm; | ||
|
||
qm->io_base = (vaddr_t)phys_to_virt_io(sec_dev->io_base, | ||
sec_dev->io_size); | ||
if (!qm->io_base) { | ||
EMSG("Fail to get qm io_base"); | ||
return HISI_QM_DRVCRYPT_EFAULT; | ||
} | ||
|
||
qm->fun_type = sec_dev->fun_type; | ||
qm->vfs_num = sec_dev->vfs_num; | ||
qm->sqe_size = SEC_SQE_SIZE; | ||
qm->sqe_log2_size = SEC_SQE_LOG2_SIZE; | ||
if (qm->fun_type == HISI_QM_HW_PF) { | ||
hisi_qm_get_version(qm); | ||
DMSG("SEC hardware version is %#"PRIx32, qm->version); | ||
qm->qp_base = HISI_QM_PF_Q_BASE; | ||
qm->qp_num = HISI_QM_PF_Q_NUM; | ||
qm->dev_status_check = sec_dev_status_check; | ||
} | ||
|
||
return hisi_qm_init(qm); | ||
} | ||
|
||
static struct acc_device *sec_alloc(void) | ||
{ | ||
struct acc_device *sec_dev = NULL; | ||
|
||
sec_dev = calloc(1, sizeof(*sec_dev)); | ||
if (!sec_dev) { | ||
EMSG("Fail to alloc sec_dev"); | ||
return NULL; | ||
} | ||
|
||
sec_dev->io_base = SEC_BAR; | ||
sec_dev->io_size = SEC_SIZE; | ||
sec_dev->fun_type = HISI_QM_HW_PF; | ||
SLIST_INSERT_HEAD(&sec_list, sec_dev, link); | ||
|
||
return sec_dev; | ||
} | ||
|
||
static void sec_free(struct acc_device *sec_dev) | ||
{ | ||
SLIST_REMOVE_HEAD(&sec_list, link); | ||
free(sec_dev); | ||
} | ||
|
||
static TEE_Result sec_probe(void) | ||
{ | ||
enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; | ||
struct acc_device *sec_dev = NULL; | ||
struct hisi_qm *qm = NULL; | ||
|
||
DMSG("SEC driver init start"); | ||
sec_dev = sec_alloc(); | ||
if (!sec_dev) | ||
return TEE_ERROR_OUT_OF_MEMORY; | ||
|
||
qm = &sec_dev->qm; | ||
ret = sec_qm_init(sec_dev); | ||
if (ret) { | ||
EMSG("Fail to init sec qm, ret=%d", ret); | ||
goto err_with_pre_init; | ||
} | ||
|
||
ret = sec_engine_init(sec_dev); | ||
if (ret) { | ||
EMSG("fail to init engine, ret=%d", ret); | ||
goto err_with_qm_init; | ||
} | ||
|
||
ret = hisi_qm_start(qm); | ||
if (ret) { | ||
EMSG("Fail to start qm, ret=%d", ret); | ||
goto err_with_qm_init; | ||
} | ||
|
||
DMSG("SEC driver init done"); | ||
return TEE_SUCCESS; | ||
|
||
err_with_qm_init: | ||
hisi_qm_uninit(qm); | ||
err_with_pre_init: | ||
sec_free(sec_dev); | ||
|
||
return TEE_ERROR_BAD_STATE; | ||
} | ||
|
||
driver_init(sec_probe); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
incdirs-y += include | ||
|
||
srcs-y += hisi_qm.c | ||
srcs-y += sec_main.c | ||
srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c | ||
srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c |