|
166 | 166 |
|
167 | 167 | typedef struct { unsigned char bytes[16]; } cpacf_mask_t;
|
168 | 168 |
|
169 |
| -/** |
170 |
| - * cpacf_query() - check if a specific CPACF function is available |
171 |
| - * @opcode: the opcode of the crypto instruction |
172 |
| - * @func: the function code to test for |
173 |
| - * |
174 |
| - * Executes the query function for the given crypto instruction @opcode |
175 |
| - * and checks if @func is available |
176 |
| - * |
177 |
| - * Returns 1 if @func is available for @opcode, 0 otherwise |
178 |
| - */ |
179 |
| -static __always_inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask) |
| 169 | +static __always_inline void __cpacf_query_rre(u32 opc, u8 r1, u8 r2, |
| 170 | + cpacf_mask_t *mask) |
180 | 171 | {
|
181 | 172 | asm volatile(
|
182 |
| - " lghi 0,0\n" /* query function */ |
183 |
| - " lgr 1,%[mask]\n" |
184 |
| - " spm 0\n" /* pckmo doesn't change the cc */ |
185 |
| - /* Parameter regs are ignored, but must be nonzero and unique */ |
186 |
| - "0: .insn rrf,%[opc] << 16,2,4,6,0\n" |
187 |
| - " brc 1,0b\n" /* handle partial completion */ |
188 |
| - : "=m" (*mask) |
189 |
| - : [mask] "d" ((unsigned long)mask), [opc] "i" (opcode) |
190 |
| - : "cc", "0", "1"); |
| 173 | + " la %%r1,%[mask]\n" |
| 174 | + " xgr %%r0,%%r0\n" |
| 175 | + " .insn rre,%[opc] << 16,%[r1],%[r2]\n" |
| 176 | + : [mask] "=R" (*mask) |
| 177 | + : [opc] "i" (opc), |
| 178 | + [r1] "i" (r1), [r2] "i" (r2) |
| 179 | + : "cc", "r0", "r1"); |
| 180 | +} |
| 181 | + |
| 182 | +static __always_inline void __cpacf_query_rrf(u32 opc, |
| 183 | + u8 r1, u8 r2, u8 r3, u8 m4, |
| 184 | + cpacf_mask_t *mask) |
| 185 | +{ |
| 186 | + asm volatile( |
| 187 | + " la %%r1,%[mask]\n" |
| 188 | + " xgr %%r0,%%r0\n" |
| 189 | + " .insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]\n" |
| 190 | + : [mask] "=R" (*mask) |
| 191 | + : [opc] "i" (opc), [r1] "i" (r1), [r2] "i" (r2), |
| 192 | + [r3] "i" (r3), [m4] "i" (m4) |
| 193 | + : "cc", "r0", "r1"); |
| 194 | +} |
| 195 | + |
| 196 | +static __always_inline void __cpacf_query(unsigned int opcode, |
| 197 | + cpacf_mask_t *mask) |
| 198 | +{ |
| 199 | + switch (opcode) { |
| 200 | + case CPACF_KDSA: |
| 201 | + __cpacf_query_rre(CPACF_KDSA, 0, 2, mask); |
| 202 | + break; |
| 203 | + case CPACF_KIMD: |
| 204 | + __cpacf_query_rre(CPACF_KIMD, 0, 2, mask); |
| 205 | + break; |
| 206 | + case CPACF_KLMD: |
| 207 | + __cpacf_query_rre(CPACF_KLMD, 0, 2, mask); |
| 208 | + break; |
| 209 | + case CPACF_KM: |
| 210 | + __cpacf_query_rre(CPACF_KM, 2, 4, mask); |
| 211 | + break; |
| 212 | + case CPACF_KMA: |
| 213 | + __cpacf_query_rrf(CPACF_KMA, 2, 4, 6, 0, mask); |
| 214 | + break; |
| 215 | + case CPACF_KMAC: |
| 216 | + __cpacf_query_rre(CPACF_KMAC, 0, 2, mask); |
| 217 | + break; |
| 218 | + case CPACF_KMC: |
| 219 | + __cpacf_query_rre(CPACF_KMC, 2, 4, mask); |
| 220 | + break; |
| 221 | + case CPACF_KMCTR: |
| 222 | + __cpacf_query_rrf(CPACF_KMCTR, 2, 4, 6, 0, mask); |
| 223 | + break; |
| 224 | + case CPACF_KMF: |
| 225 | + __cpacf_query_rre(CPACF_KMF, 2, 4, mask); |
| 226 | + break; |
| 227 | + case CPACF_KMO: |
| 228 | + __cpacf_query_rre(CPACF_KMO, 2, 4, mask); |
| 229 | + break; |
| 230 | + case CPACF_PCC: |
| 231 | + __cpacf_query_rre(CPACF_PCC, 0, 0, mask); |
| 232 | + break; |
| 233 | + case CPACF_PCKMO: |
| 234 | + __cpacf_query_rre(CPACF_PCKMO, 0, 0, mask); |
| 235 | + break; |
| 236 | + case CPACF_PRNO: |
| 237 | + __cpacf_query_rre(CPACF_PRNO, 2, 4, mask); |
| 238 | + break; |
| 239 | + default: |
| 240 | + BUG(); |
| 241 | + } |
191 | 242 | }
|
192 | 243 |
|
193 | 244 | static __always_inline int __cpacf_check_opcode(unsigned int opcode)
|
@@ -215,6 +266,16 @@ static __always_inline int __cpacf_check_opcode(unsigned int opcode)
|
215 | 266 | }
|
216 | 267 | }
|
217 | 268 |
|
| 269 | +/** |
| 270 | + * cpacf_query() - check if a specific CPACF function is available |
| 271 | + * @opcode: the opcode of the crypto instruction |
| 272 | + * @func: the function code to test for |
| 273 | + * |
| 274 | + * Executes the query function for the given crypto instruction @opcode |
| 275 | + * and checks if @func is available |
| 276 | + * |
| 277 | + * Returns 1 if @func is available for @opcode, 0 otherwise |
| 278 | + */ |
218 | 279 | static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
|
219 | 280 | {
|
220 | 281 | if (__cpacf_check_opcode(opcode)) {
|
|
0 commit comments