mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
crypto: caam - avoid S/G table fetching for AEAD zero-length output
[ Upstream commitdcd9c76e5a] When enabling IOMMU support, the following issue becomes visible in the AEAD zero-length case. Even though the output sequence length is set to zero, the crypto engine tries to prefetch 4 S/G table entries (since SGF bit is set in SEQ OUT PTR command - which is either generated in SW in case of caam/jr or in HW in case of caam/qi, caam/qi2). The DMA read operation will trigger an IOMMU fault since the address in the SEQ OUT PTR is "dummy" (set to zero / not obtained via DMA API mapping). 1. In case of caam/jr, avoid the IOMMU fault by clearing the SGF bit in SEQ OUT PTR command. 2. In case of caam/qi - setting address, bpid, length to zero for output entry in the compound frame has a special meaning (cf. CAAM RM): "Output frame = Unspecified, Input address = Y. A unspecified frame is indicated by an unused SGT entry (an entry in which the Address, Length, and BPID fields are all zero). SEC obtains output buffers from BMan as prescribed by the preheader." Since no output buffers are needed, modify the preheader by setting (ABS = 1, ADDBUF = 0): -"ABS = 1 means obtain the number of buffers in ADDBUF (0 or 1) from the pool POOL ID" -ADDBUF: "If ABS is set, ADD BUF specifies whether to allocate a buffer or not" 3. In case of caam/qi2, since engine: -does not support FLE[FMT]=2'b11 ("unused" entry) mentioned in DPAA2 RM -requires output entry to be present, even if not used the solution chosen is to leave output frame list entry zeroized. Fixes:763069ba49("crypto: caam - handle zero-length AEAD output") Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d58142f19b
commit
cb7da2ba53
@@ -1106,6 +1106,7 @@ static void init_aead_job(struct aead_request *req,
|
||||
if (unlikely(req->src != req->dst)) {
|
||||
if (!edesc->mapped_dst_nents) {
|
||||
dst_dma = 0;
|
||||
out_options = 0;
|
||||
} else if (edesc->mapped_dst_nents == 1) {
|
||||
dst_dma = sg_dma_address(req->dst);
|
||||
out_options = 0;
|
||||
|
||||
@@ -1109,7 +1109,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], qm_sg_dma +
|
||||
(1 + !!ivsize) * sizeof(*sg_table),
|
||||
out_len, 0);
|
||||
} else if (mapped_dst_nents == 1) {
|
||||
} else if (mapped_dst_nents <= 1) {
|
||||
dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(req->dst), out_len,
|
||||
0);
|
||||
} else {
|
||||
|
||||
@@ -559,6 +559,14 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
dpaa2_fl_set_addr(out_fle, qm_sg_dma +
|
||||
(1 + !!ivsize) * sizeof(*sg_table));
|
||||
}
|
||||
} else if (!mapped_dst_nents) {
|
||||
/*
|
||||
* crypto engine requires the output entry to be present when
|
||||
* "frame list" FD is used.
|
||||
* Since engine does not support FMT=2'b11 (unused entry type),
|
||||
* leaving out_fle zeroized is the best option.
|
||||
*/
|
||||
goto skip_out_fle;
|
||||
} else if (mapped_dst_nents == 1) {
|
||||
dpaa2_fl_set_format(out_fle, dpaa2_fl_single);
|
||||
dpaa2_fl_set_addr(out_fle, sg_dma_address(req->dst));
|
||||
@@ -570,6 +578,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
|
||||
dpaa2_fl_set_len(out_fle, out_len);
|
||||
|
||||
skip_out_fle:
|
||||
return edesc;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "desc_constr.h"
|
||||
|
||||
#define PREHDR_RSLS_SHIFT 31
|
||||
#define PREHDR_ABS BIT(25)
|
||||
|
||||
/*
|
||||
* Use a reasonable backlog of frames (per CPU) as congestion threshold,
|
||||
@@ -346,6 +347,7 @@ int caam_drv_ctx_update(struct caam_drv_ctx *drv_ctx, u32 *sh_desc)
|
||||
*/
|
||||
drv_ctx->prehdr[0] = cpu_to_caam32((1 << PREHDR_RSLS_SHIFT) |
|
||||
num_words);
|
||||
drv_ctx->prehdr[1] = cpu_to_caam32(PREHDR_ABS);
|
||||
memcpy(drv_ctx->sh_desc, sh_desc, desc_bytes(sh_desc));
|
||||
dma_sync_single_for_device(qidev, drv_ctx->context_a,
|
||||
sizeof(drv_ctx->sh_desc) +
|
||||
@@ -401,6 +403,7 @@ struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev,
|
||||
*/
|
||||
drv_ctx->prehdr[0] = cpu_to_caam32((1 << PREHDR_RSLS_SHIFT) |
|
||||
num_words);
|
||||
drv_ctx->prehdr[1] = cpu_to_caam32(PREHDR_ABS);
|
||||
memcpy(drv_ctx->sh_desc, sh_desc, desc_bytes(sh_desc));
|
||||
size = sizeof(drv_ctx->prehdr) + sizeof(drv_ctx->sh_desc);
|
||||
hwdesc = dma_map_single(qidev, drv_ctx->prehdr, size,
|
||||
|
||||
Reference in New Issue
Block a user