s390/cpacf: Split and rework cpacf query functions
Rework the cpacf query functions to use the correct RRE or RRF instruction formats and set register fields within instructions correctly. Fixes: 1afd43e0fbba ("s390/crypto: allow to query all known cpacf functions") Reported-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> Suggested-by: Heiko Carstens <hca@linux.ibm.com> Suggested-by: Juergen Christ <jchrist@linux.ibm.com> Suggested-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Reviewed-by: Juergen Christ <jchrist@linux.ibm.com> Cc: <stable@vger.kernel.org> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
24bf80f78e
commit
830999bd7e
@ -166,28 +166,79 @@
|
||||
|
||||
typedef struct { unsigned char bytes[16]; } cpacf_mask_t;
|
||||
|
||||
/**
|
||||
* cpacf_query() - check if a specific CPACF function is available
|
||||
* @opcode: the opcode of the crypto instruction
|
||||
* @func: the function code to test for
|
||||
*
|
||||
* Executes the query function for the given crypto instruction @opcode
|
||||
* and checks if @func is available
|
||||
*
|
||||
* Returns 1 if @func is available for @opcode, 0 otherwise
|
||||
*/
|
||||
static __always_inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
|
||||
static __always_inline void __cpacf_query_rre(u32 opc, u8 r1, u8 r2,
|
||||
cpacf_mask_t *mask)
|
||||
{
|
||||
asm volatile(
|
||||
" lghi 0,0\n" /* query function */
|
||||
" lgr 1,%[mask]\n"
|
||||
" spm 0\n" /* pckmo doesn't change the cc */
|
||||
/* Parameter regs are ignored, but must be nonzero and unique */
|
||||
"0: .insn rrf,%[opc] << 16,2,4,6,0\n"
|
||||
" brc 1,0b\n" /* handle partial completion */
|
||||
: "=m" (*mask)
|
||||
: [mask] "d" ((unsigned long)mask), [opc] "i" (opcode)
|
||||
: "cc", "0", "1");
|
||||
" la %%r1,%[mask]\n"
|
||||
" xgr %%r0,%%r0\n"
|
||||
" .insn rre,%[opc] << 16,%[r1],%[r2]\n"
|
||||
: [mask] "=R" (*mask)
|
||||
: [opc] "i" (opc),
|
||||
[r1] "i" (r1), [r2] "i" (r2)
|
||||
: "cc", "r0", "r1");
|
||||
}
|
||||
|
||||
static __always_inline void __cpacf_query_rrf(u32 opc,
|
||||
u8 r1, u8 r2, u8 r3, u8 m4,
|
||||
cpacf_mask_t *mask)
|
||||
{
|
||||
asm volatile(
|
||||
" la %%r1,%[mask]\n"
|
||||
" xgr %%r0,%%r0\n"
|
||||
" .insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]\n"
|
||||
: [mask] "=R" (*mask)
|
||||
: [opc] "i" (opc), [r1] "i" (r1), [r2] "i" (r2),
|
||||
[r3] "i" (r3), [m4] "i" (m4)
|
||||
: "cc", "r0", "r1");
|
||||
}
|
||||
|
||||
static __always_inline void __cpacf_query(unsigned int opcode,
|
||||
cpacf_mask_t *mask)
|
||||
{
|
||||
switch (opcode) {
|
||||
case CPACF_KDSA:
|
||||
__cpacf_query_rre(CPACF_KDSA, 0, 2, mask);
|
||||
break;
|
||||
case CPACF_KIMD:
|
||||
__cpacf_query_rre(CPACF_KIMD, 0, 2, mask);
|
||||
break;
|
||||
case CPACF_KLMD:
|
||||
__cpacf_query_rre(CPACF_KLMD, 0, 2, mask);
|
||||
break;
|
||||
case CPACF_KM:
|
||||
__cpacf_query_rre(CPACF_KM, 2, 4, mask);
|
||||
break;
|
||||
case CPACF_KMA:
|
||||
__cpacf_query_rrf(CPACF_KMA, 2, 4, 6, 0, mask);
|
||||
break;
|
||||
case CPACF_KMAC:
|
||||
__cpacf_query_rre(CPACF_KMAC, 0, 2, mask);
|
||||
break;
|
||||
case CPACF_KMC:
|
||||
__cpacf_query_rre(CPACF_KMC, 2, 4, mask);
|
||||
break;
|
||||
case CPACF_KMCTR:
|
||||
__cpacf_query_rrf(CPACF_KMCTR, 2, 4, 6, 0, mask);
|
||||
break;
|
||||
case CPACF_KMF:
|
||||
__cpacf_query_rre(CPACF_KMF, 2, 4, mask);
|
||||
break;
|
||||
case CPACF_KMO:
|
||||
__cpacf_query_rre(CPACF_KMO, 2, 4, mask);
|
||||
break;
|
||||
case CPACF_PCC:
|
||||
__cpacf_query_rre(CPACF_PCC, 0, 0, mask);
|
||||
break;
|
||||
case CPACF_PCKMO:
|
||||
__cpacf_query_rre(CPACF_PCKMO, 0, 0, mask);
|
||||
break;
|
||||
case CPACF_PRNO:
|
||||
__cpacf_query_rre(CPACF_PRNO, 2, 4, mask);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline int __cpacf_check_opcode(unsigned int opcode)
|
||||
@ -215,6 +266,16 @@ static __always_inline int __cpacf_check_opcode(unsigned int opcode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cpacf_query() - check if a specific CPACF function is available
|
||||
* @opcode: the opcode of the crypto instruction
|
||||
* @func: the function code to test for
|
||||
*
|
||||
* Executes the query function for the given crypto instruction @opcode
|
||||
* and checks if @func is available
|
||||
*
|
||||
* Returns 1 if @func is available for @opcode, 0 otherwise
|
||||
*/
|
||||
static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
|
||||
{
|
||||
if (__cpacf_check_opcode(opcode)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user