dma: axi-dmac: integer overflow when DMA_LENGTH_WIDTH is set to 32 in the FPGA design
IsaacJT opened this issue · comments
This issue appears in the axi_dmac_fill_linear_sg function in dma-axi-dmac.c:
linux/drivers/dma/dma-axi-dmac.c
Line 550 in de35cc6
When the DMA_LENGTH_WIDTH is 32, the chan->max_length variable is set to 2^32, and the formula used in the DIV_ROUND_UP macro creates an integer overflow:
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
This results in the macro returning 0 and a divide-by-zero error in the next line of code, causing the following stack trace:
[ 79.624443] divide error: 0000 [#1] PREEMPT SMP PTI
[ 79.624450] CPU: 0 PID: 4225 Comm: iiod Not tainted 4.19.0 #31
[ 79.624455] Hardware name: AMI AM F5x/msd/AM F5x/msd, BIOS 4.09.01 12/06/2019
[ 79.624468] RIP: 0010:axi_dmac_fill_linear_sg.isra.23+0x70/0xe5
[ 79.624474] Code: 48 c7 c7 38 c6 6f b2 42 8d 44 31 ff f7 f1 ba 2c 02 00 00 44 89 f1 41 89 c7 41 89 c0 e8 33 0d b5 ff 43 8d 44 3e ff 31 d2 31 f6 <41> f7 f7 ff c8 41 0b 45 00 44 8d 40 01 48 8b 44 24 38 4c 89 c2 39
[ 79.624485] RSP: 0018:ffffaba281bf3c00 EFLAGS: 00010246
[ 79.624492] RAX: 00000000000fffff RBX: 0000000088100000 RCX: 0000000000000000
[ 79.624497] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000ffffffff
[ 79.624503] RBP: 0000000000000001 R08: ffffffffb1958250 R09: 0000000000000498
[ 79.624508] R10: ffffffffb16f1fc0 R11: ffffffffb30c0f0d R12: 0000000000000002
[ 79.624514] R13: ffffa1761af13684 R14: 0000000000100000 R15: 0000000000000000
[ 79.624520] FS: 00007f04bdc2b640(0000) GS:ffffa1761da00000(0000) knlGS:0000000000000000
[ 79.624527] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 79.624532] CR2: 00007f04b4001db8 CR3: 0000000457b24004 CR4: 00000000003606f0
[ 79.624538] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 79.624543] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 79.624548] Call Trace:
[ 79.624558] axi_dmac_prep_slave_sg.cold.29+0xf5/0x14e
[ 79.624568] iio_dmaengine_buffer_submit_block+0x19f/0x1e0
[ 79.624578] axiadc_hw_submit_block+0x1c/0x50
[ 79.624585] iio_dma_buffer_submit_block.part.9+0x29/0x50
[ 79.624591] iio_dma_buffer_enable+0x8f/0x130
[ 79.624599] __iio_update_buffers+0x3bf/0x8b0
[ 79.624607] iio_buffer_store_enable+0x7f/0xe0
[ 79.624615] kernfs_fop_write+0x107/0x180
[ 79.624624] __vfs_write+0x35/0x180
[ 79.624632] vfs_write+0xa4/0x1a0
[ 79.624638] ksys_write+0x4e/0xb0
[ 79.624646] do_syscall_64+0x47/0xf0
[ 79.624653] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 79.624659] RIP: 0033:0x7f04bf0d94cf
[ 79.624664] Code: 89 54 24 18 48 89 74 24 10 89 7c 24 08 e8 79 3f f9 ff 48 8b 54 24 18 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 31 44 89 c7 48 89 44 24 08 e8 cc 3f f9 ff 48
[ 79.624675] RSP: 002b:00007f04bdc2a2b0 EFLAGS: 00000293 ORIG_RAX: 0000000000000001
[ 79.624682] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f04bf0d94cf
[ 79.624688] RDX: 0000000000000002 RSI: 00007f04b4000e70 RDI: 000000000000000a
[ 79.624693] RBP: 00007f04b4000e70 R08: 0000000000000000 R09: 00007f04b4000000
[ 79.624699] R10: 0000000000000070 R11: 0000000000000293 R12: 0000000000000002
[ 79.624704] R13: 00007f04b4000bd0 R14: 0000000000000002 R15: 00007f04bf1ad720
[ 79.624711] Modules linked in:
[ 79.624743] ---[ end trace 963fe9dc5135c760 ]---
[ 79.624752] RIP: 0010:axi_dmac_fill_linear_sg.isra.23+0x70/0xe5
[ 79.624758] Code: 48 c7 c7 38 c6 6f b2 42 8d 44 31 ff f7 f1 ba 2c 02 00 00 44 89 f1 41 89 c7 41 89 c0 e8 33 0d b5 ff 43 8d 44 3e ff 31 d2 31 f6 <41> f7 f7 ff c8 41 0b 45 00 44 8d 40 01 48 8b 44 24 38 4c 89 c2 39
[ 79.624768] RSP: 0018:ffffaba281bf3c00 EFLAGS: 00010246
[ 79.624777] RAX: 00000000000fffff RBX: 0000000088100000 RCX: 0000000000000000
[ 79.624782] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000ffffffff
[ 79.624788] RBP: 0000000000000001 R08: ffffffffb1958250 R09: 0000000000000498
[ 79.624793] R10: ffffffffb16f1fc0 R11: ffffffffb30c0f0d R12: 0000000000000002
[ 79.624799] R13: ffffa1761af13684 R14: 0000000000100000 R15: 0000000000000000
[ 79.624805] FS: 00007f04bdc2b640(0000) GS:ffffa1761da00000(0000) knlGS:0000000000000000
[ 79.624811] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 79.624816] CR2: 00007f04b4001db8 CR3: 0000000457b24004 CR4: 00000000003606f0
[ 79.624822] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 79.624829] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Hi @IsaacJT,
it looks like you have it all figured 😄 . I can see the problem here but I'm not really that familiarized with our dma driver. Nevertheless, as a quick thought DIV_ROUND_UP_ULL()
should prevent the overflow... Not sure if this would be needed in some other place in the driver. Feel free to try this and if it works, to send a PR...
Was there a particular reason to increase DMA_LENGTH_WIDTH from 24 to 32?
Was there a particular reason to increase DMA_LENGTH_WIDTH from 24 to 32?
No particular reason - I'm mostly doing performance tests and trying out different combinations of settings, and I noticed this while testing DMA transfer sizes (we're doing DMA over PCIe, so a bigger block size is helpful).
Feel free to try this and if it works, to send a PR...
I'll give it a go