This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3352: Crypto driver crash

Part Number: AM3352

Tool/software: Linux

Hi,

We are facing a driver crash when trying to use openssl.. Below is the crash dump (similar to the one reported in the link )

Kernel version: 4.9.69

1568.755634] [<c010b790>] (dump_backtrace) from [<c010ba4c>] (show_stack+0x18/0x1c)
[ 1568.773111] r7:00000009 r6:00000000 r5:c099c168 r4:00000000
[ 1568.778888] [<c010ba34>] (show_stack) from [<c03c1cd4>] (dump_stack+0x24/0x28)
[ 1568.801547] [<c03c1cb0>] (dump_stack) from [<c012b5a8>] (__warn+0xe8/0x100)
[ 1568.815231] [<c012b4c0>] (__warn) from [<c012b678>] (warn_slowpath_null+0x28/0x30)
[ 1568.831445] r9:064c10e0 r8:0000000f r7:00000000 r6:c0c13e00 r5:00000000 r4:c0c029c4
[ 1568.843271] [<c012b650>] (warn_slowpath_null) from [<c01c3cf8>] (__alloc_pages_nodemask+0x804/0xbdc)
[ 1568.852498] [<c01c34f4>] (__alloc_pages_nodemask) from [<c01c40e8>] (__get_free_pages+0x18/0x34)
[ 1568.866397] r10:00000000 r9:064c10e0 r8:ca2f6000 r7:00000040 r6:c0080000 r5:cf691710
[ 1568.880361] r4:cf7a3e00
[ 1568.886667] [<c01c40d0>] (__get_free_pages) from [<bf086138>] (omap_sham_handle_queue+0x558/0x9dc [omap_sham])
[ 1568.900624] [<bf085be0>] (omap_sham_handle_queue [omap_sham]) from [<bf086760>] (omap_sham_update+0x68/0xa8 [omap_sham])
[ 1568.915606] r10:00000000 r9:ca2f6000 r8:becac134 r7:c0080000 r6:00000000 r5:ca078d80
[ 1568.927485] r4:cf7a3e00
[ 1568.930197] [<bf0866f8>] (omap_sham_update [omap_sham]) from [<bf003494>] (cryptodev_hash_update+0x40/0xcc [cryptodev])
[ 1568.945936] r5:ca078d80 r4:ca078dd0
[ 1568.949686] [<bf003454>] (cryptodev_hash_update [cryptodev]) from [<bf001f90>] (hash_n_crypt+0xe4/0x140 [cryptodev])
[ 1568.969536] r4:ca078d80
[ 1568.972242] [<bf001eac>] (hash_n_crypt [cryptodev]) from [<bf0024e4>] (crypto_run+0x204/0x4f4 [cryptodev])
[ 1568.986859] r7:ca2f7dcc r6:c8a4e700 r5:ca078d80 r4:ca2f7dcc
[ 1568.992696] [<bf0022e0>] (crypto_run [cryptodev]) from [<bf0018e4>] (cryptodev_ioctl+0x424/0x9ec [cryptodev])
[ 1569.011783] r8:becac134 r7:ca2f7dcc r6:c8a96200 r5:becac134 r4:00000051
[ 1569.022430] [<bf0014c0>] (cryptodev_ioctl [cryptodev]) from [<c0225b68>] (do_vfs_ioctl+0xa8/0x980)
[ 1569.035511] r9:ca2f6000 r8:becac134 r7:00000003 r6:cf690a80 r5:cf572898 r4:becac134
[ 1569.047306] [<c0225ac0>] (do_vfs_ioctl) from [<c022647c>] (SyS_ioctl+0x3c/0x64)
[ 1569.058436] r10:00000000 r9:ca2f6000 r8:becac134 r7:c01c6368 r6:cf690a80 r5:00000003
[ 1569.070028] r4:cf690a80
[ 1569.072661] [<c0226440>] (SyS_ioctl) from [<c0107c80>] (ret_fast_syscall+0x0/0x48)
[ 1569.085285] r9:ca2f6000 r8:c0107e44 r7:00000036 r6:d734a3eb r5:064c10e0 r4:00000000
[ 1569.099025] ---[ end trace f92bc7a3f3a124ee ]---
[ 1569.107484] omap_sham_copy_sgs: Couldn't allocate pages for unaligned cases.
[ 1569.118560] cryptodev: openssl[1281] (waitfor:267): error from async request: -12
[ 1569.129993] cryptodev: openssl[1281] (hash_n_crypt:98): CryptoAPI failure: -12
Verification failure

Is there a fix for this issue available as a patch that we can download and apply?

Regards,

Fariya

  • Please post which Linux version you are using.
  • The kernel version is 4.9.69

  • Hi Fariya,

    can you please share the openssl test case so that I can replicate the issue on my side?
  • Bin,

    Very rarely do I see the openssl command to succeed. Even when it succeeds, I get the below crash dump:

    (Please note I see the crashes the first one reported above and the below one only when I try with big files i.e ~100MB)

    [ 222.396350] openssl: page allocation failure: order:7, mode:0x24040c0(GFP_KERNEL|__GFP_COMP)
    [ 222.409577] CPU: 0 PID: 1112 Comm: openssl Tainted: G W O 4.9.69-g9ce43c71ae #1
    [ 222.443065] Hardware name: Generic AM33XX (Flattened Device Tree)
    [ 222.449259] Backtrace:
    [ 222.451803] [<c010b790>] (dump_backtrace) from [<c010ba4c>] (show_stack+0x18/0x1c)
    [ 222.483084] r7:00000000 r6:c0c13e00 r5:00000001 r4:00000001
    [ 222.488892] [<c010ba34>] (show_stack) from [<c03c1cd4>] (dump_stack+0x24/0x28)
    [ 222.523091] [<c03c1cb0>] (dump_stack) from [<c01c343c>] (warn_alloc+0x100/0x114)
    [ 222.530605] [<c01c3340>] (warn_alloc) from [<c01c3814>] (__alloc_pages_nodemask+0x320/0xbdc)
    [ 222.563915] r3:00000002 r2:00000007 r1:c099c248
    [ 222.569308] r4:ca0a8000
    [ 222.583114] [<c01c34f4>] (__alloc_pages_nodemask) from [<c01dded0>] (kmalloc_order+0x20/0x3c)
    [ 222.591768] r10:ca0a9d88 r9:ca0a9d8c r8:bf00545c r7:024000c0 r6:024000c0 r5:00080000
    [ 222.612139] r4:cf68c000
    [ 222.618723] [<c01ddeb0>] (kmalloc_order) from [<c0203cc4>] (__kmalloc_track_caller+0x15c/0x1b0)
    [ 222.631410] [<c0203b68>] (__kmalloc_track_caller) from [<c01de27c>] (krealloc+0x54/0xc0)
    [ 222.643875] r7:024000c0 r6:00000200 r5:00080000 r4:cf68c000
    [ 222.649721] [<c01de228>] (krealloc) from [<bf00545c>] (adjust_sg_array+0x78/0xe0 [cryptodev])
    [ 222.663052] r9:ca0a9d8c r8:beb1d104 r7:064c10e0 r6:00000068 r5:cf55a240 r4:00008000
    [ 222.671015] [<bf0053e4>] (adjust_sg_array [cryptodev]) from [<bf0057f4>] (get_userbuf+0x238/0x318 [cryptodev])
    [ 222.690802] r6:00000000 r5:00000000 r4:cf55a240
    [ 222.699389] [<bf0055bc>] (get_userbuf [cryptodev]) from [<bf0024c0>] (crypto_run+0x1e0/0x4f4 [cryptodev])
    [ 222.713139] r10:00000000 r9:ca0a8000 r8:beb1d104 r7:ca0a9dcc r6:c8a79700 r5:cf55a240
    [ 222.721065] r4:ca0a9dcc
    [ 222.728390] [<bf0022e0>] (crypto_run [cryptodev]) from [<bf0018e4>] (cryptodev_ioctl+0x424/0x9ec [cryptodev])
    [ 222.744754] r8:beb1d104 r7:ca0a9dcc r6:c8a1ef00 r5:beb1d104 r4:00000051
    [ 222.751666] [<bf0014c0>] (cryptodev_ioctl [cryptodev]) from [<c0225b68>] (do_vfs_ioctl+0xa8/0x980)
    [ 222.765711] r9:ca0a8000 r8:beb1d104 r7:00000003 r6:cf7f56c0 r5:cf59a730 r4:beb1d104
    [ 222.779548] [<c0225ac0>] (do_vfs_ioctl) from [<c022647c>] (SyS_ioctl+0x3c/0x64)
    [ 222.790751] r10:00000000 r9:ca0a8000 r8:beb1d104 r7:c01c6368 r6:cf7f56c0 r5:00000003
    [ 222.802394] r4:cf7f56c0
    [ 222.808849] [<c0226440>] (SyS_ioctl) from [<c0107c80>] (ret_fast_syscall+0x0/0x48)
    [ 222.820385] r9:ca0a8000 r8:c0107e44 r7:00000036 r6:84b513c3 r5:064c10e0 r4:00000000
    [ 222.831978] Mem-Info:
    [ 222.838102] active_anon:53017 inactive_anon:2083 isolated_anon:0
    [ 222.838102] active_file:689 inactive_file:1068 isolated_file:0
    [ 222.838102] unevictable:0 dirty:9 writeback:0 unstable:0
    [ 222.838102] slab_reclaimable:546 slab_unreclaimable:1638
    [ 222.838102] mapped:824 shmem:2182 pagetables:183 bounce:0
    [ 222.838102] free:1227 free_pcp:85 free_cma:164
    [ 222.876148] Node 0 active_anon:212068kB inactive_anon:8332kB active_file:2756kB inactive_file:4272kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:3300kB dirty:36kB writeback:0kB shmem:8728kB writeback_tmp:0kB unstable:0kB pages_scanned:14 all_unreclaimable? no
    [ 222.917631] Normal free:4908kB min:1780kB low:2224kB high:2668kB active_anon:212068kB inactive_anon:8332kB active_file:2756kB inactive_file:4272kB unevictable:0kB writepending:36kB present:262144kB managed:248488kB mlocked:0kB slab_reclaimable:2184kB slab_unreclaimable:6552kB kernel_stack:896kB pagetables:732kB bounce:0kB free_pcp:336kB local_pcp:336kB free_cma:656kB
    [ 222.954440] lowmem_reserve[]: 0 0 0
    [ 222.958035] Normal: 257*4kB (UMEC) 163*8kB (UMEC) 77*16kB (UMEC) 12*32kB (UEC) 5*64kB (ME) 1*128kB (M) 2*256kB (M) 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 4908kB
    3940 total pagecache pages
    [ 222.979991] 0 pages in swap cache
    [ 222.988630] Swap cache stats: add 0, delete 0, find 0/0
    [ 223.000193] Free swap = 0kB
    [ 223.006784] Total swap = 0kB
    [ 223.009747] 65536 pages RAM
    [ 223.012563] 0 pages HighMem/MovableOnly
    [ 223.026562] 3414 pages reserved
    [ 223.029755] 12288 pages cma reserved
    Verification successful



    Regards,
    Fariya
  • Hi Fariya,

    I am wondering if you face the same issue as the one mentioned in the thread "Linux/AM3352: Crypto driver crash on big files" you referred. The fix for that issue is in the latest Processor SDK Linux v5.2 which has kernel v4.14.79.

    I attach the kernel patch to fix that issue below, but I am not sure if it can cleanly apply to kernel 4.9.69. You can try it or test with the latest Processor SDK kernel.

    From 46bb67753612a4b8c33ba9ca6508f5474b57baf5 Mon Sep 17 00:00:00 2001
    From: Tero Kristo <t-kristo@ti.com>
    Date: Fri, 26 Oct 2018 18:08:02 +0300
    Subject: [PATCH] crypto: omap-sham: split up data to multiple sg elements with
     huge data
    
    When using huge data amount, allocating free pages fails as the kernel
    isn't able to process get_free_page requests larger than MAX_ORDER.
    Also, the DMA subsystem has an inherent limitation that data size
    larger than some 2MB can't be handled properly. In these cases,
    split up the data instead to smaller requests so that the kernel
    can allocate the data, and also so that the DMA driver can handle
    the separate SG elements.
    
    Signed-off-by: Tero Kristo <t-kristo@ti.com>
    Tested-by: Bin Liu <b-liu@ti.com>
    ---
     drivers/crypto/omap-sham.c | 81 ++++++++++++++++++++++++++++++--------
     1 file changed, 64 insertions(+), 17 deletions(-)
    
    diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
    index 6c8bc4733f6d..ad26e7b91109 100644
    --- a/drivers/crypto/omap-sham.c
    +++ b/drivers/crypto/omap-sham.c
    @@ -115,6 +115,8 @@
     #define FLAGS_BE32_SHA1		8
     #define FLAGS_SGS_COPIED	9
     #define FLAGS_SGS_ALLOCED	10
    +#define FLAGS_HUGE		11
    +
     /* context flags */
     #define FLAGS_FINUP		16
     
    @@ -139,6 +141,8 @@
     #define BUFLEN			SHA512_BLOCK_SIZE
     #define OMAP_SHA_DMA_THRESHOLD	256
     
    +#define OMAP_SHA_MAX_DMA_LEN	(1024 * 2048)
    +
     struct omap_sham_dev;
     
     struct omap_sham_reqctx {
    @@ -692,21 +696,20 @@ static int omap_sham_copy_sg_lists(struct omap_sham_reqctx *ctx,
     
     	set_bit(FLAGS_SGS_ALLOCED, &ctx->dd->flags);
     
    +	ctx->offset += new_len - ctx->bufcnt;
     	ctx->bufcnt = 0;
     
     	return 0;
     }
     
     static int omap_sham_copy_sgs(struct omap_sham_reqctx *ctx,
    -			      struct scatterlist *sg, int bs, int new_len)
    +			      struct scatterlist *sg, int bs,
    +			      unsigned int new_len)
     {
     	int pages;
     	void *buf;
    -	int len;
    -
    -	len = new_len + ctx->bufcnt;
     
    -	pages = get_order(ctx->total);
    +	pages = get_order(new_len);
     
     	buf = (void *)__get_free_pages(GFP_ATOMIC, pages);
     	if (!buf) {
    @@ -718,14 +721,14 @@ static int omap_sham_copy_sgs(struct omap_sham_reqctx *ctx,
     		memcpy(buf, ctx->dd->xmit_buf, ctx->bufcnt);
     
     	scatterwalk_map_and_copy(buf + ctx->bufcnt, sg, ctx->offset,
    -				 ctx->total - ctx->bufcnt, 0);
    +				 min(new_len, ctx->total) - ctx->bufcnt, 0);
     	sg_init_table(ctx->sgl, 1);
    -	sg_set_buf(ctx->sgl, buf, len);
    +	sg_set_buf(ctx->sgl, buf, new_len);
     	ctx->sg = ctx->sgl;
     	set_bit(FLAGS_SGS_COPIED, &ctx->dd->flags);
     	ctx->sg_len = 1;
    +	ctx->offset += new_len - ctx->bufcnt;
     	ctx->bufcnt = 0;
    -	ctx->offset = 0;
     
     	return 0;
     }
    @@ -744,7 +747,7 @@ static int omap_sham_align_sgs(struct scatterlist *sg,
     	if (!sg || !sg->length || !nbytes)
     		return 0;
     
    -	new_len = nbytes;
    +	new_len = nbytes - offset;
     
     	if (offset)
     		list_ok = false;
    @@ -754,6 +757,9 @@ static int omap_sham_align_sgs(struct scatterlist *sg,
     	else
     		new_len = (new_len - 1) / bs * bs;
     
    +	if (!new_len)
    +		return 0;
    +
     	if (nbytes != new_len)
     		list_ok = false;
     
    @@ -797,10 +803,17 @@ static int omap_sham_align_sgs(struct scatterlist *sg,
     		}
     	}
     
    +	if (new_len > OMAP_SHA_MAX_DMA_LEN) {
    +		new_len = OMAP_SHA_MAX_DMA_LEN;
    +		aligned = false;
    +	}
    +
     	if (!aligned)
     		return omap_sham_copy_sgs(rctx, sg, bs, new_len);
     	else if (!list_ok)
     		return omap_sham_copy_sg_lists(rctx, sg, bs, new_len);
    +	else
    +		rctx->offset += new_len;
     
     	rctx->sg_len = n;
     	rctx->sg = sg;
    @@ -827,7 +840,12 @@ static int omap_sham_prepare_request(struct ahash_request *req, bool update)
     	else
     		nbytes = 0;
     
    -	rctx->total = nbytes + rctx->bufcnt;
    +	rctx->total = nbytes + rctx->bufcnt - rctx->offset;
    +
    +	dev_dbg(rctx->dd->dev,
    +		"%s: nbytes=%d, bs=%d, total=%d, offset=%d, bufcnt=%d\n",
    +		__func__, nbytes, bs, rctx->total, rctx->offset,
    +		rctx->bufcnt);
     
     	if (!rctx->total)
     		return 0;
    @@ -853,12 +871,15 @@ static int omap_sham_prepare_request(struct ahash_request *req, bool update)
     
     	xmit_len = rctx->total;
     
    +	if (xmit_len > OMAP_SHA_MAX_DMA_LEN)
    +		xmit_len = OMAP_SHA_MAX_DMA_LEN;
    +
     	if (!IS_ALIGNED(xmit_len, bs)) {
     		if (final)
     			xmit_len = DIV_ROUND_UP(xmit_len, bs) * bs;
     		else
     			xmit_len = xmit_len / bs * bs;
    -	} else if (!final) {
    +	} else if (!final && rctx->total == xmit_len) {
     		xmit_len -= bs;
     	}
     
    @@ -886,7 +907,7 @@ static int omap_sham_prepare_request(struct ahash_request *req, bool update)
     		rctx->sg_len = 1;
     	}
     
    -	if (hash_later) {
    +	if (hash_later && hash_later <= rctx->buflen) {
     		int offset = 0;
     
     		if (hash_later > req->nbytes) {
    @@ -907,6 +928,9 @@ static int omap_sham_prepare_request(struct ahash_request *req, bool update)
     		rctx->bufcnt = 0;
     	}
     
    +	if (hash_later > rctx->buflen)
    +		set_bit(FLAGS_HUGE, &rctx->dd->flags);
    +
     	if (!final)
     		rctx->total = xmit_len;
     
    @@ -1004,10 +1028,11 @@ static int omap_sham_update_req(struct omap_sham_dev *dd)
     	struct ahash_request *req = dd->req;
     	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
     	int err;
    -	bool final = ctx->flags & BIT(FLAGS_FINUP);
    +	bool final = (ctx->flags & BIT(FLAGS_FINUP)) &&
    +			!(dd->flags & BIT(FLAGS_HUGE));
     
    -	dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
    -		 ctx->total, ctx->digcnt, (ctx->flags & BIT(FLAGS_FINUP)) != 0);
    +	dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, final: %d",
    +		ctx->total, ctx->digcnt, final);
     
     	if (ctx->total < get_block_size(ctx) ||
     	    ctx->total < dd->fallback_sz)
    @@ -1030,6 +1055,9 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
     	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
     	int err = 0, use_dma = 1;
     
    +	if (dd->flags & BIT(FLAGS_HUGE))
    +		return 0;
    +
     	if ((ctx->total <= get_block_size(ctx)) || dd->polling_mode)
     		/*
     		 * faster to handle last block with cpu or
    @@ -1090,7 +1118,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
     
     	if (test_bit(FLAGS_SGS_COPIED, &dd->flags))
     		free_pages((unsigned long)sg_virt(ctx->sg),
    -			   get_order(ctx->sg->length + ctx->bufcnt));
    +			   get_order(ctx->sg->length));
     
     	if (test_bit(FLAGS_SGS_ALLOCED, &dd->flags))
     		kfree(ctx->sg);
    @@ -1099,6 +1127,21 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
     
     	dd->flags &= ~(BIT(FLAGS_SGS_ALLOCED) | BIT(FLAGS_SGS_COPIED));
     
    +	if (dd->flags & BIT(FLAGS_HUGE)) {
    +		dd->flags &= ~(BIT(FLAGS_CPU) | BIT(FLAGS_DMA_READY) |
    +				BIT(FLAGS_OUTPUT_READY) | BIT(FLAGS_HUGE));
    +		omap_sham_prepare_request(req, ctx->op == OP_UPDATE);
    +		if (ctx->op == OP_UPDATE || (dd->flags & BIT(FLAGS_HUGE))) {
    +			err = omap_sham_update_req(dd);
    +			if (err != -EINPROGRESS &&
    +			    (ctx->flags & BIT(FLAGS_FINUP)))
    +				err = omap_sham_final_req(dd);
    +		} else if (ctx->op == OP_FINAL) {
    +			omap_sham_final_req(dd);
    +		}
    +		return;
    +	}
    +
     	if (!err) {
     		dd->pdata->copy_hash(req, 1);
     		if (test_bit(FLAGS_FINAL, &dd->flags))
    @@ -1114,6 +1157,8 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
     	pm_runtime_mark_last_busy(dd->dev);
     	pm_runtime_put_autosuspend(dd->dev);
     
    +	ctx->offset = 0;
    +
     	if (req->base.complete)
     		req->base.complete(&req->base, err);
     }
    @@ -1165,7 +1210,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
     		/* request has changed - restore hash */
     		dd->pdata->copy_hash(req, 0);
     
    -	if (ctx->op == OP_UPDATE) {
    +	if (ctx->op == OP_UPDATE || (dd->flags & BIT(FLAGS_HUGE))) {
     		err = omap_sham_update_req(dd);
     		if (err != -EINPROGRESS && (ctx->flags & BIT(FLAGS_FINUP)))
     			/* no final() after finup() */
    @@ -1750,6 +1795,8 @@ static void omap_sham_done_task(unsigned long data)
     	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
     	int err = 0;
     
    +	dev_dbg(dd->dev, "%s: flags=%lx\n", __func__, dd->flags);
    +
     	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
     		omap_sham_handle_queue(dd, NULL);
     		return;
    -- 
    2.17.1
    
    

  • Hi, I haven’t heard back from you, I’m assuming you were able to resolve your issue. If not, just post a reply below (or create a new thread if the thread has locked due to time-out). thanks.