Branch data Line data Source code
1 : : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 : : *
3 : : * Copyright 2008-2016 Freescale Semiconductor Inc.
4 : : * Copyright 2016,2019 NXP
5 : : */
6 : :
7 : : #ifndef __RTA_LOAD_CMD_H__
8 : : #define __RTA_LOAD_CMD_H__
9 : :
10 : : extern enum rta_sec_era rta_sec_era;
11 : :
12 : : /* Allowed length and offset masks for each SEC Era in case DST = DCTRL */
13 : : static const uint32_t load_len_mask_allowed[] = {
14 : : 0x000000ee,
15 : : 0x000000fe,
16 : : 0x000000fe,
17 : : 0x000000fe,
18 : : 0x000000fe,
19 : : 0x000000fe,
20 : : 0x000000fe,
21 : : 0x000000fe,
22 : : 0x000000fe,
23 : : 0x000000fe
24 : : };
25 : :
26 : : static const uint32_t load_off_mask_allowed[] = {
27 : : 0x0000000f,
28 : : 0x000000ff,
29 : : 0x000000ff,
30 : : 0x000000ff,
31 : : 0x000000ff,
32 : : 0x000000ff,
33 : : 0x000000ff,
34 : : 0x000000ff,
35 : : 0x000000ff,
36 : : 0x000000ff
37 : : };
38 : :
39 : : #define IMM_MUST 0
40 : : #define IMM_CAN 1
41 : : #define IMM_NO 2
42 : : #define IMM_DSNM 3 /* it doesn't matter the src type */
43 : :
44 : : enum e_lenoff {
45 : : LENOF_03,
46 : : LENOF_4,
47 : : LENOF_48,
48 : : LENOF_448,
49 : : LENOF_18,
50 : : LENOF_32,
51 : : LENOF_24,
52 : : LENOF_16,
53 : : LENOF_8,
54 : : LENOF_128,
55 : : LENOF_256,
56 : : DSNM /* it doesn't matter the length/offset values */
57 : : };
58 : :
59 : : struct load_map {
60 : : uint32_t dst;
61 : : uint32_t dst_opcode;
62 : : enum e_lenoff len_off;
63 : : uint8_t imm_src;
64 : :
65 : : };
66 : :
67 : : static const struct load_map load_dst[] = {
68 : : /*1*/ { KEY1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
69 : : LENOF_4, IMM_MUST },
70 : : { KEY2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
71 : : LENOF_4, IMM_MUST },
72 : : { DATA1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DATASZ_REG,
73 : : LENOF_448, IMM_MUST },
74 : : { DATA2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_DATASZ_REG,
75 : : LENOF_448, IMM_MUST },
76 : : { ICV1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
77 : : LENOF_4, IMM_MUST },
78 : : { ICV2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
79 : : LENOF_4, IMM_MUST },
80 : : { CCTRL, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CHACTRL,
81 : : LENOF_4, IMM_MUST },
82 : : { DCTRL, LDST_CLASS_DECO | LDST_IMM | LDST_SRCDST_WORD_DECOCTRL,
83 : : DSNM, IMM_DSNM },
84 : : { ICTRL, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_IRQCTRL,
85 : : LENOF_4, IMM_MUST },
86 : : { DPOVRD, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_PCLOVRD,
87 : : LENOF_4, IMM_MUST },
88 : : { CLRW, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CLRW,
89 : : LENOF_4, IMM_MUST },
90 : : { AAD1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DECO_AAD_SZ,
91 : : LENOF_4, IMM_MUST },
92 : : { IV1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_CLASS1_IV_SZ,
93 : : LENOF_4, IMM_MUST },
94 : : { ALTDS1, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ALTDS_CLASS1,
95 : : LENOF_448, IMM_MUST },
96 : : { PKASZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_A_SZ,
97 : : LENOF_4, IMM_MUST, },
98 : : { PKBSZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_B_SZ,
99 : : LENOF_4, IMM_MUST },
100 : : { PKNSZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_N_SZ,
101 : : LENOF_4, IMM_MUST },
102 : : { PKESZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_E_SZ,
103 : : LENOF_4, IMM_MUST },
104 : : { NFIFO, LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_INFO_FIFO,
105 : : LENOF_48, IMM_MUST },
106 : : { IFIFO, LDST_SRCDST_BYTE_INFIFO, LENOF_18, IMM_MUST },
107 : : { OFIFO, LDST_SRCDST_BYTE_OUTFIFO, LENOF_18, IMM_MUST },
108 : : { MATH0, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH0,
109 : : LENOF_32, IMM_CAN },
110 : : { MATH1, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH1,
111 : : LENOF_24, IMM_CAN },
112 : : { MATH2, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH2,
113 : : LENOF_16, IMM_CAN },
114 : : { MATH3, LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH3,
115 : : LENOF_8, IMM_CAN },
116 : : { CONTEXT1, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT,
117 : : LENOF_128, IMM_CAN },
118 : : { CONTEXT2, LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT,
119 : : LENOF_128, IMM_CAN },
120 : : { KEY1, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_KEY,
121 : : LENOF_32, IMM_CAN },
122 : : { KEY2, LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY,
123 : : LENOF_32, IMM_CAN },
124 : : { DESCBUF, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF,
125 : : LENOF_256, IMM_NO },
126 : : { DPID, LDST_CLASS_DECO | LDST_SRCDST_WORD_PID,
127 : : LENOF_448, IMM_MUST },
128 : : /*32*/ { IDFNS, LDST_SRCDST_WORD_IFNSR, LENOF_18, IMM_MUST },
129 : : { ODFNS, LDST_SRCDST_WORD_OFNSR, LENOF_18, IMM_MUST },
130 : : { ALTSOURCE, LDST_SRCDST_BYTE_ALTSOURCE, LENOF_18, IMM_MUST },
131 : : /*35*/ { NFIFO_SZL, LDST_SRCDST_WORD_INFO_FIFO_SZL, LENOF_48, IMM_MUST },
132 : : { NFIFO_SZM, LDST_SRCDST_WORD_INFO_FIFO_SZM, LENOF_03, IMM_MUST },
133 : : { NFIFO_L, LDST_SRCDST_WORD_INFO_FIFO_L, LENOF_48, IMM_MUST },
134 : : { NFIFO_M, LDST_SRCDST_WORD_INFO_FIFO_M, LENOF_03, IMM_MUST },
135 : : { SZL, LDST_SRCDST_WORD_SZL, LENOF_48, IMM_MUST },
136 : : /*40*/ { SZM, LDST_SRCDST_WORD_SZM, LENOF_03, IMM_MUST }
137 : : };
138 : :
139 : : /*
140 : : * Allowed LOAD destinations for each SEC Era.
141 : : * Values represent the number of entries from load_dst[] that are supported.
142 : : */
143 : : static const unsigned int load_dst_sz[] = { 31, 34, 34, 40, 40,
144 : : 40, 40, 40, 40, 40};
145 : :
146 : : static inline int
147 : 0 : load_check_len_offset(int pos, uint32_t length, uint32_t offset)
148 : : {
149 [ # # ]: 0 : if ((load_dst[pos].dst == DCTRL) &&
150 [ # # ]: 0 : ((length & ~load_len_mask_allowed[rta_sec_era]) ||
151 [ # # ]: 0 : (offset & ~load_off_mask_allowed[rta_sec_era])))
152 : 0 : goto err;
153 : :
154 [ # # # # : 0 : switch (load_dst[pos].len_off) {
# # # # #
# # # # ]
155 : 0 : case (LENOF_03):
156 [ # # ]: 0 : if ((length > 3) || (offset))
157 : 0 : goto err;
158 : : break;
159 : 0 : case (LENOF_4):
160 [ # # ]: 0 : if ((length != 4) || (offset != 0))
161 : 0 : goto err;
162 : : break;
163 : 0 : case (LENOF_48):
164 : 0 : if (!(((length == 4) && (offset == 0)) ||
165 [ # # ]: 0 : ((length == 8) && (offset == 0))))
166 : 0 : goto err;
167 : : break;
168 : 0 : case (LENOF_448):
169 : 0 : if (!(((length == 4) && (offset == 0)) ||
170 [ # # ]: 0 : ((length == 4) && (offset == 4)) ||
171 [ # # ]: 0 : ((length == 8) && (offset == 0))))
172 : 0 : goto err;
173 : : break;
174 : 0 : case (LENOF_18):
175 [ # # # # ]: 0 : if ((length < 1) || (length > 8) || (offset != 0))
176 : 0 : goto err;
177 : : break;
178 : 0 : case (LENOF_32):
179 [ # # # # ]: 0 : if ((length > 32) || (offset > 32) || ((offset + length) > 32))
180 : 0 : goto err;
181 : : break;
182 : 0 : case (LENOF_24):
183 [ # # # # ]: 0 : if ((length > 24) || (offset > 24) || ((offset + length) > 24))
184 : 0 : goto err;
185 : : break;
186 : 0 : case (LENOF_16):
187 [ # # # # ]: 0 : if ((length > 16) || (offset > 16) || ((offset + length) > 16))
188 : 0 : goto err;
189 : : break;
190 : 0 : case (LENOF_8):
191 [ # # # # ]: 0 : if ((length > 8) || (offset > 8) || ((offset + length) > 8))
192 : 0 : goto err;
193 : : break;
194 : 0 : case (LENOF_128):
195 [ # # ]: 0 : if ((length > 128) || (offset > 128) ||
196 [ # # ]: 0 : ((offset + length) > 128))
197 : 0 : goto err;
198 : : break;
199 : 0 : case (LENOF_256):
200 [ # # # # ]: 0 : if ((length < 1) || (length > 256) || ((length + offset) > 256))
201 : 0 : goto err;
202 : : break;
203 : : case (DSNM):
204 : : break;
205 : 0 : default:
206 : 0 : goto err;
207 : : }
208 : :
209 : : return 0;
210 : 0 : err:
211 : : return -EINVAL;
212 : : }
213 : :
214 : : static inline int
215 : 0 : rta_load(struct program *program, uint64_t src, uint64_t dst,
216 : : uint32_t offset, uint32_t length, uint32_t flags)
217 : : {
218 : : uint32_t opcode = 0;
219 : : int pos = -1, ret = -EINVAL;
220 : 0 : unsigned int start_pc = program->current_pc, i;
221 : :
222 [ # # ]: 0 : if (flags & SEQ)
223 : : opcode = CMD_SEQ_LOAD;
224 : : else
225 : : opcode = CMD_LOAD;
226 : :
227 [ # # # # ]: 0 : if ((length & 0xffffff00) || (offset & 0xffffff00)) {
228 : 0 : pr_err("LOAD: Bad length/offset passed. Should be 8 bits\n");
229 : 0 : goto err;
230 : : }
231 : :
232 [ # # ]: 0 : if (flags & SGF)
233 : 0 : opcode |= LDST_SGF;
234 [ # # ]: 0 : if (flags & VLF)
235 : 0 : opcode |= LDST_VLF;
236 : :
237 : : /* check load destination, length and offset and source type */
238 [ # # ]: 0 : for (i = 0; i < load_dst_sz[rta_sec_era]; i++)
239 [ # # ]: 0 : if (dst == load_dst[i].dst) {
240 : 0 : pos = (int)i;
241 : 0 : break;
242 : : }
243 [ # # ]: 0 : if (-1 == pos) {
244 : 0 : pr_err("LOAD: Invalid dst. SEC Program Line: %d\n",
245 : : program->current_pc);
246 : 0 : goto err;
247 : : }
248 : :
249 [ # # ]: 0 : if (flags & IMMED) {
250 [ # # ]: 0 : if (load_dst[pos].imm_src == IMM_NO) {
251 : 0 : pr_err("LOAD: Invalid source type. SEC Program Line: %d\n",
252 : : program->current_pc);
253 : 0 : goto err;
254 : : }
255 : 0 : opcode |= LDST_IMM;
256 [ # # ]: 0 : } else if (load_dst[pos].imm_src == IMM_MUST) {
257 : 0 : pr_err("LOAD IMM: Invalid source type. SEC Program Line: %d\n",
258 : : program->current_pc);
259 : 0 : goto err;
260 : : }
261 : :
262 : 0 : ret = load_check_len_offset(pos, length, offset);
263 [ # # ]: 0 : if (ret < 0) {
264 : 0 : pr_err("LOAD: Invalid length/offset. SEC Program Line: %d\n",
265 : : program->current_pc);
266 : 0 : goto err;
267 : : }
268 : :
269 : 0 : opcode |= load_dst[pos].dst_opcode;
270 : :
271 : : /* DESC BUFFER: length / offset values are specified in 4-byte words */
272 [ # # ]: 0 : if (dst == DESCBUF) {
273 : 0 : opcode |= (length >> 2);
274 : 0 : opcode |= ((offset >> 2) << LDST_OFFSET_SHIFT);
275 : : } else {
276 : 0 : opcode |= length;
277 : 0 : opcode |= (offset << LDST_OFFSET_SHIFT);
278 : : }
279 : :
280 : 0 : __rta_out32(program, opcode);
281 : 0 : program->current_instruction++;
282 : :
283 : : /* DECO CONTROL: skip writing pointer of imm data */
284 [ # # ]: 0 : if (dst == DCTRL)
285 : 0 : return (int)start_pc;
286 : :
287 : : /*
288 : : * For data copy, 3 possible ways to specify how to copy data:
289 : : * - IMMED & !COPY: copy data directly from src( max 8 bytes)
290 : : * - IMMED & COPY: copy data imm from the location specified by user
291 : : * - !IMMED and is not SEQ cmd: copy the address
292 : : */
293 [ # # ]: 0 : if (flags & IMMED)
294 : 0 : __rta_inline_data(program, src, flags & __COPY_MASK, length);
295 [ # # ]: 0 : else if (!(flags & SEQ))
296 : 0 : __rta_out64(program, program->ps, src);
297 : :
298 : 0 : return (int)start_pc;
299 : :
300 : 0 : err:
301 : 0 : program->first_error_pc = start_pc;
302 : 0 : program->current_instruction++;
303 : 0 : return ret;
304 : : }
305 : :
306 : : #endif /* __RTA_LOAD_CMD_H__*/
|