2019-06-25 11:12:58 +00:00
|
|
|
/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
|
2018-05-15 09:49:22 +00:00
|
|
|
*
|
|
|
|
* Copyright 2008-2016 Freescale Semiconductor Inc.
|
2019-06-25 11:12:58 +00:00
|
|
|
* Copyright 2016 NXP
|
2018-05-15 09:49:22 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __RTA_LOAD_CMD_H__
|
|
|
|
#define __RTA_LOAD_CMD_H__
|
|
|
|
|
|
|
|
extern enum rta_sec_era rta_sec_era;
|
|
|
|
|
|
|
|
/* Allowed length and offset masks for each SEC Era in case DST = DCTRL */
|
|
|
|
static const uint32_t load_len_mask_allowed[] = {
|
|
|
|
0x000000ee,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe,
|
|
|
|
0x000000fe
|
|
|
|
};
|
|
|
|
|
|
|
|
static const uint32_t load_off_mask_allowed[] = {
|
|
|
|
0x0000000f,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff,
|
|
|
|
0x000000ff
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IMM_MUST 0
|
|
|
|
#define IMM_CAN 1
|
|
|
|
#define IMM_NO 2
|
|
|
|
#define IMM_DSNM 3 /* it doesn't matter the src type */
|
|
|
|
|
|
|
|
enum e_lenoff {
|
|
|
|
LENOF_03,
|
|
|
|
LENOF_4,
|
|
|
|
LENOF_48,
|
|
|
|
LENOF_448,
|
|
|
|
LENOF_18,
|
|
|
|
LENOF_32,
|
|
|
|
LENOF_24,
|
|
|
|
LENOF_16,
|
|
|
|
LENOF_8,
|
|
|
|
LENOF_128,
|
|
|
|
LENOF_256,
|
|
|
|
DSNM /* it doesn't matter the length/offset values */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct load_map {
|
|
|
|
uint32_t dst;
|
|
|
|
uint32_t dst_opcode;
|
|
|
|
enum e_lenoff len_off;
|
|
|
|
uint8_t imm_src;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct load_map load_dst[] = {
|
|
|
|
/*1*/ { KEY1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ KEY2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ DATA1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DATASZ_REG,
|
|
|
|
LENOF_448, IMM_MUST },
|
|
|
|
{ DATA2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_DATASZ_REG,
|
|
|
|
LENOF_448, IMM_MUST },
|
|
|
|
{ ICV1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ ICV2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ CCTRL, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CHACTRL,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ DCTRL, LDST_CLASS_DECO | LDST_IMM | LDST_SRCDST_WORD_DECOCTRL,
|
|
|
|
DSNM, IMM_DSNM },
|
|
|
|
{ ICTRL, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_IRQCTRL,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ DPOVRD, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_PCLOVRD,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ CLRW, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CLRW,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ AAD1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DECO_AAD_SZ,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ IV1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_CLASS1_IV_SZ,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ ALTDS1, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ALTDS_CLASS1,
|
|
|
|
LENOF_448, IMM_MUST },
|
|
|
|
{ PKASZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_A_SZ,
|
|
|
|
LENOF_4, IMM_MUST, },
|
|
|
|
{ PKBSZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_B_SZ,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ PKNSZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_N_SZ,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ PKESZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_E_SZ,
|
|
|
|
LENOF_4, IMM_MUST },
|
|
|
|
{ NFIFO, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_INFO_FIFO,
|
|
|
|
LENOF_48, IMM_MUST },
|
|
|
|
{ IFIFO, LDST_SRCDST_BYTE_INFIFO, LENOF_18, IMM_MUST },
|
|
|
|
{ OFIFO, LDST_SRCDST_BYTE_OUTFIFO, LENOF_18, IMM_MUST },
|
|
|
|
{ MATH0, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH0,
|
|
|
|
LENOF_32, IMM_CAN },
|
|
|
|
{ MATH1, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH1,
|
|
|
|
LENOF_24, IMM_CAN },
|
|
|
|
{ MATH2, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH2,
|
|
|
|
LENOF_16, IMM_CAN },
|
|
|
|
{ MATH3, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH3,
|
|
|
|
LENOF_8, IMM_CAN },
|
|
|
|
{ CONTEXT1, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT,
|
|
|
|
LENOF_128, IMM_CAN },
|
|
|
|
{ CONTEXT2, LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT,
|
|
|
|
LENOF_128, IMM_CAN },
|
|
|
|
{ KEY1, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_KEY,
|
|
|
|
LENOF_32, IMM_CAN },
|
|
|
|
{ KEY2, LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY,
|
|
|
|
LENOF_32, IMM_CAN },
|
|
|
|
{ DESCBUF, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF,
|
|
|
|
LENOF_256, IMM_NO },
|
|
|
|
{ DPID, LDST_CLASS_DECO | LDST_SRCDST_WORD_PID,
|
|
|
|
LENOF_448, IMM_MUST },
|
|
|
|
/*32*/ { IDFNS, LDST_SRCDST_WORD_IFNSR, LENOF_18, IMM_MUST },
|
|
|
|
{ ODFNS, LDST_SRCDST_WORD_OFNSR, LENOF_18, IMM_MUST },
|
|
|
|
{ ALTSOURCE, LDST_SRCDST_BYTE_ALTSOURCE, LENOF_18, IMM_MUST },
|
|
|
|
/*35*/ { NFIFO_SZL, LDST_SRCDST_WORD_INFO_FIFO_SZL, LENOF_48, IMM_MUST },
|
|
|
|
{ NFIFO_SZM, LDST_SRCDST_WORD_INFO_FIFO_SZM, LENOF_03, IMM_MUST },
|
|
|
|
{ NFIFO_L, LDST_SRCDST_WORD_INFO_FIFO_L, LENOF_48, IMM_MUST },
|
|
|
|
{ NFIFO_M, LDST_SRCDST_WORD_INFO_FIFO_M, LENOF_03, IMM_MUST },
|
|
|
|
{ SZL, LDST_SRCDST_WORD_SZL, LENOF_48, IMM_MUST },
|
|
|
|
/*40*/ { SZM, LDST_SRCDST_WORD_SZM, LENOF_03, IMM_MUST }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allowed LOAD destinations for each SEC Era.
|
|
|
|
* Values represent the number of entries from load_dst[] that are supported.
|
|
|
|
*/
|
|
|
|
static const unsigned int load_dst_sz[] = { 31, 34, 34, 40, 40, 40, 40, 40 };
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
load_check_len_offset(int pos, uint32_t length, uint32_t offset)
|
|
|
|
{
|
|
|
|
if ((load_dst[pos].dst == DCTRL) &&
|
|
|
|
((length & ~load_len_mask_allowed[rta_sec_era]) ||
|
|
|
|
(offset & ~load_off_mask_allowed[rta_sec_era])))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
switch (load_dst[pos].len_off) {
|
|
|
|
case (LENOF_03):
|
|
|
|
if ((length > 3) || (offset))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_4):
|
|
|
|
if ((length != 4) || (offset != 0))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_48):
|
|
|
|
if (!(((length == 4) && (offset == 0)) ||
|
|
|
|
((length == 8) && (offset == 0))))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_448):
|
|
|
|
if (!(((length == 4) && (offset == 0)) ||
|
|
|
|
((length == 4) && (offset == 4)) ||
|
|
|
|
((length == 8) && (offset == 0))))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_18):
|
|
|
|
if ((length < 1) || (length > 8) || (offset != 0))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_32):
|
|
|
|
if ((length > 32) || (offset > 32) || ((offset + length) > 32))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_24):
|
|
|
|
if ((length > 24) || (offset > 24) || ((offset + length) > 24))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_16):
|
|
|
|
if ((length > 16) || (offset > 16) || ((offset + length) > 16))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_8):
|
|
|
|
if ((length > 8) || (offset > 8) || ((offset + length) > 8))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_128):
|
|
|
|
if ((length > 128) || (offset > 128) ||
|
|
|
|
((offset + length) > 128))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (LENOF_256):
|
|
|
|
if ((length < 1) || (length > 256) || ((length + offset) > 256))
|
|
|
|
goto err;
|
|
|
|
break;
|
|
|
|
case (DSNM):
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
rta_load(struct program *program, uint64_t src, uint64_t dst,
|
|
|
|
uint32_t offset, uint32_t length, uint32_t flags)
|
|
|
|
{
|
|
|
|
uint32_t opcode = 0;
|
|
|
|
int pos = -1, ret = -EINVAL;
|
|
|
|
unsigned int start_pc = program->current_pc, i;
|
|
|
|
|
|
|
|
if (flags & SEQ)
|
|
|
|
opcode = CMD_SEQ_LOAD;
|
|
|
|
else
|
|
|
|
opcode = CMD_LOAD;
|
|
|
|
|
|
|
|
if ((length & 0xffffff00) || (offset & 0xffffff00)) {
|
|
|
|
pr_err("LOAD: Bad length/offset passed. Should be 8 bits\n");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & SGF)
|
|
|
|
opcode |= LDST_SGF;
|
|
|
|
if (flags & VLF)
|
|
|
|
opcode |= LDST_VLF;
|
|
|
|
|
|
|
|
/* check load destination, length and offset and source type */
|
|
|
|
for (i = 0; i < load_dst_sz[rta_sec_era]; i++)
|
|
|
|
if (dst == load_dst[i].dst) {
|
|
|
|
pos = (int)i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (-1 == pos) {
|
|
|
|
pr_err("LOAD: Invalid dst. SEC Program Line: %d\n",
|
|
|
|
program->current_pc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & IMMED) {
|
|
|
|
if (load_dst[pos].imm_src == IMM_NO) {
|
|
|
|
pr_err("LOAD: Invalid source type. SEC Program Line: %d\n",
|
|
|
|
program->current_pc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
opcode |= LDST_IMM;
|
|
|
|
} else if (load_dst[pos].imm_src == IMM_MUST) {
|
|
|
|
pr_err("LOAD IMM: Invalid source type. SEC Program Line: %d\n",
|
|
|
|
program->current_pc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = load_check_len_offset(pos, length, offset);
|
|
|
|
if (ret < 0) {
|
|
|
|
pr_err("LOAD: Invalid length/offset. SEC Program Line: %d\n",
|
|
|
|
program->current_pc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
opcode |= load_dst[pos].dst_opcode;
|
|
|
|
|
|
|
|
/* DESC BUFFER: length / offset values are specified in 4-byte words */
|
|
|
|
if (dst == DESCBUF) {
|
|
|
|
opcode |= (length >> 2);
|
|
|
|
opcode |= ((offset >> 2) << LDST_OFFSET_SHIFT);
|
|
|
|
} else {
|
|
|
|
opcode |= length;
|
|
|
|
opcode |= (offset << LDST_OFFSET_SHIFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
__rta_out32(program, opcode);
|
|
|
|
program->current_instruction++;
|
|
|
|
|
|
|
|
/* DECO CONTROL: skip writing pointer of imm data */
|
|
|
|
if (dst == DCTRL)
|
|
|
|
return (int)start_pc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For data copy, 3 possible ways to specify how to copy data:
|
|
|
|
* - IMMED & !COPY: copy data directly from src( max 8 bytes)
|
|
|
|
* - IMMED & COPY: copy data imm from the location specified by user
|
|
|
|
* - !IMMED and is not SEQ cmd: copy the address
|
|
|
|
*/
|
|
|
|
if (flags & IMMED)
|
|
|
|
__rta_inline_data(program, src, flags & __COPY_MASK, length);
|
|
|
|
else if (!(flags & SEQ))
|
|
|
|
__rta_out64(program, program->ps, src);
|
|
|
|
|
|
|
|
return (int)start_pc;
|
|
|
|
|
|
|
|
err:
|
|
|
|
program->first_error_pc = start_pc;
|
|
|
|
program->current_instruction++;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __RTA_LOAD_CMD_H__*/
|