* [Qemu-devel] [PATCH 0/2] ide/hw/core: fix bug# 1777315, crash on short PRDs @ 2018-06-20 4:29 Amol Surati 2018-06-20 4:29 ` [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer Amol Surati 2018-06-20 4:29 ` [Qemu-devel] [PATCH 2/2] tests/ide-test: test case for crash when processing short PRDs Amol Surati 0 siblings, 2 replies; 5+ messages in thread From: Amol Surati @ 2018-06-20 4:29 UTC (permalink / raw) To: qemu-devel; +Cc: jsnow, Amol Surati The fix utilizes the existing policy QEMU has about short PRDs, and considers the transfers that cause the crash as generated through short PRDS. It - continues to allow QEMU to support multiple calls to prepare_buf/ide_dma_cb, - so, continues to keep QEMU free from needing the entire sglist in one go; - avoids the crash; - but, treats the affected transfers as short, instead of allowing them to continue. Amol Surati (1): ide/hw/core: fix crash on processing a partial-sector-size DMA xfer John Snow (1): tests/ide-test: test case for crash when processing short PRDs hw/ide/core.c | 5 ++++- tests/ide-test.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) -- 2.17.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer 2018-06-20 4:29 [Qemu-devel] [PATCH 0/2] ide/hw/core: fix bug# 1777315, crash on short PRDs Amol Surati @ 2018-06-20 4:29 ` Amol Surati 2018-06-25 21:10 ` John Snow 2018-06-20 4:29 ` [Qemu-devel] [PATCH 2/2] tests/ide-test: test case for crash when processing short PRDs Amol Surati 1 sibling, 1 reply; 5+ messages in thread From: Amol Surati @ 2018-06-20 4:29 UTC (permalink / raw) To: qemu-devel; +Cc: jsnow, Amol Surati, open list:IDE Fixes: https://bugs.launchpad.net/qemu/+bug/1777315 QEMU's short PRD policy applies to a DMA transfer of size < 512 bytes. But it fails to consider transfers which are >= 512 bytes, but are not a multiple of 512 bytes. Such transfers are not subject to the short PRD policy. They end up violating the assumptions about the granularity of the IO sizes, upon which depend the verification of the completion of the previous transfer, and the advancement of the offset in preparation of the next. Those violations result in the crash. By forcing each transfer to be a multiple of sector size, such transfers are subjected to the policy, and therefore culled before they cause the crash. Signed-off-by: Amol Surati <suratiamol@gmail.com> --- hw/ide/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 2c62efc536..14d135224b 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -836,6 +836,7 @@ static void ide_dma_cb(void *opaque, int ret) { IDEState *s = opaque; int n; + int32_t size_prepared; int64_t sector_num; uint64_t offset; bool stay_active = false; @@ -886,7 +887,9 @@ static void ide_dma_cb(void *opaque, int ret) n = s->nsector; s->io_buffer_index = 0; s->io_buffer_size = n * 512; - if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) { + size_prepared = s->bus->dma->ops->prepare_buf(s->bus->dma, + s->io_buffer_size); + if (size_prepared <= 0 || size_prepared % 512) { /* The PRDs were too short. Reset the Active bit, but don't raise an * interrupt. */ s->status = READY_STAT | SEEK_STAT; -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer 2018-06-20 4:29 ` [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer Amol Surati @ 2018-06-25 21:10 ` John Snow 2018-06-26 1:30 ` Amol Surati 0 siblings, 1 reply; 5+ messages in thread From: John Snow @ 2018-06-25 21:10 UTC (permalink / raw) To: Amol Surati, qemu-devel; +Cc: open list:IDE On 06/20/2018 12:29 AM, Amol Surati wrote: > Fixes: https://bugs.launchpad.net/qemu/+bug/1777315 > > QEMU's short PRD policy applies to a DMA transfer of size < 512 bytes. > But it fails to consider transfers which are >= 512 bytes, but are > not a multiple of 512 bytes. > > Such transfers are not subject to the short PRD policy. They end up > violating the assumptions about the granularity of the IO sizes, > upon which depend the verification of the completion of the previous > transfer, and the advancement of the offset in preparation of the next. > > Those violations result in the crash. > > By forcing each transfer to be a multiple of sector size, such > transfers are subjected to the policy, and therefore culled before they > cause the crash. > So now even if the PRDT we get is greater than a sector is not an even multiple of 512, we reject it as too short. That doesn't seem correct to me. > Signed-off-by: Amol Surati <suratiamol@gmail.com> > --- > hw/ide/core.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/hw/ide/core.c b/hw/ide/core.c > index 2c62efc536..14d135224b 100644 > --- a/hw/ide/core.c > +++ b/hw/ide/core.c > @@ -836,6 +836,7 @@ static void ide_dma_cb(void *opaque, int ret) > { > IDEState *s = opaque; > int n; > + int32_t size_prepared; > int64_t sector_num; > uint64_t offset; > bool stay_active = false; > @@ -886,7 +887,9 @@ static void ide_dma_cb(void *opaque, int ret) > n = s->nsector; > s->io_buffer_index = 0; > s->io_buffer_size = n * 512; > - if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) { > + size_prepared = s->bus->dma->ops->prepare_buf(s->bus->dma, > + s->io_buffer_size); > + if (size_prepared <= 0 || size_prepared % 512) { > /* The PRDs were too short. Reset the Active bit, but don't raise an > * interrupt. */ > s->status = READY_STAT | SEEK_STAT; > -- —js ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer 2018-06-25 21:10 ` John Snow @ 2018-06-26 1:30 ` Amol Surati 0 siblings, 0 replies; 5+ messages in thread From: Amol Surati @ 2018-06-26 1:30 UTC (permalink / raw) To: John Snow; +Cc: Amol Surati, qemu-devel, open list:IDE On Mon, Jun 25, 2018 at 05:10:23PM -0400, John Snow wrote: > > > On 06/20/2018 12:29 AM, Amol Surati wrote: > > Fixes: https://bugs.launchpad.net/qemu/+bug/1777315 > > > > QEMU's short PRD policy applies to a DMA transfer of size < 512 bytes. > > But it fails to consider transfers which are >= 512 bytes, but are > > not a multiple of 512 bytes. > > > > Such transfers are not subject to the short PRD policy. They end up > > violating the assumptions about the granularity of the IO sizes, > > upon which depend the verification of the completion of the previous > > transfer, and the advancement of the offset in preparation of the next. > > > > Those violations result in the crash. > > > > By forcing each transfer to be a multiple of sector size, such > > transfers are subjected to the policy, and therefore culled before they > > cause the crash. > > > > So now even if the PRDT we get is greater than a sector is not an even > multiple of 512, we reject it as too short. Yes. When PRDT is greater than a sector but non an even multiple of 512, we used to crash. Now we do not. The reason for this patch is to maintain backward compatibility with the current split-completion design that QEMU adopts, while still avoiding the crash. The cover letter has the reasons for this patch. > > That doesn't seem correct to me. https://github.com/asurati/1777315/blob/master/v2.diff has a different patch, which aligns with what Kevin had suggested. It allows the IO which you described above, but then it completes the command as soon as it detects a partial transfer which is larger than 512. The patch where s->sg.size is used as the offset to start the next IO would require the dma IOs to be misaligned and of non-512 sizes. Will that be okay? Else, one needs to change each implementation of prepare_buf to ensure that it always ALIGNS_UP to the sector size any partial read/write/trim, in anticipation of the next PRDT which can cover the difference. > > > Signed-off-by: Amol Surati <suratiamol@gmail.com> > > --- > > hw/ide/core.c | 5 ++++- > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > diff --git a/hw/ide/core.c b/hw/ide/core.c > > index 2c62efc536..14d135224b 100644 > > --- a/hw/ide/core.c > > +++ b/hw/ide/core.c > > @@ -836,6 +836,7 @@ static void ide_dma_cb(void *opaque, int ret) > > { > > IDEState *s = opaque; > > int n; > > + int32_t size_prepared; > > int64_t sector_num; > > uint64_t offset; > > bool stay_active = false; > > @@ -886,7 +887,9 @@ static void ide_dma_cb(void *opaque, int ret) > > n = s->nsector; > > s->io_buffer_index = 0; > > s->io_buffer_size = n * 512; > > - if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) { > > + size_prepared = s->bus->dma->ops->prepare_buf(s->bus->dma, > > + s->io_buffer_size); > > + if (size_prepared <= 0 || size_prepared % 512) { > > /* The PRDs were too short. Reset the Active bit, but don't raise an > > * interrupt. */ > > s->status = READY_STAT | SEEK_STAT; > > > > -- > —js ^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/2] tests/ide-test: test case for crash when processing short PRDs 2018-06-20 4:29 [Qemu-devel] [PATCH 0/2] ide/hw/core: fix bug# 1777315, crash on short PRDs Amol Surati 2018-06-20 4:29 ` [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer Amol Surati @ 2018-06-20 4:29 ` Amol Surati 1 sibling, 0 replies; 5+ messages in thread From: Amol Surati @ 2018-06-20 4:29 UTC (permalink / raw) To: qemu-devel; +Cc: jsnow, Amol Surati, open list:IDE From: John Snow <jsnow@redhat.com> Related Bug: https://bugs.launchpad.net/qemu/+bug/1777315 Signed-off-by: Amol Surati <suratiamol@gmail.com> --- tests/ide-test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/ide-test.c b/tests/ide-test.c index f39431b1a9..382c29a174 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -473,6 +473,32 @@ static void test_bmdma_one_sector_short_prdt(void) free_pci_device(dev); } +static void test_bmdma_partial_sector_short_prdt(void) +{ + QPCIDevice *dev; + QPCIBar bmdma_bar, ide_bar; + uint8_t status; + + /* Read 2 sectors but only give 1 sector in PRDT */ + PrdtEntry prdt[] = { + { + .addr = 0, + .size = cpu_to_le32(0x200), + }, + { + .addr = 512, + .size = cpu_to_le32(0x44 | PRDT_EOT), + } + }; + + dev = get_pci_device(&bmdma_bar, &ide_bar); + status = send_dma_request(CMD_READ_DMA, 0, 2, + prdt, ARRAY_SIZE(prdt), NULL); + g_assert_cmphex(status, ==, 0); + assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR); + free_pci_device(dev); +} + static void test_bmdma_long_prdt(void) { QPCIDevice *dev; @@ -1037,6 +1063,8 @@ int main(int argc, char **argv) qtest_add_func("/ide/bmdma/short_prdt", test_bmdma_short_prdt); qtest_add_func("/ide/bmdma/one_sector_short_prdt", test_bmdma_one_sector_short_prdt); + qtest_add_func("/ide/bmdma/partial_sector_short_prdt", + test_bmdma_partial_sector_short_prdt); qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt); qtest_add_func("/ide/bmdma/no_busmaster", test_bmdma_no_busmaster); qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown); -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-06-26 1:28 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-06-20 4:29 [Qemu-devel] [PATCH 0/2] ide/hw/core: fix bug# 1777315, crash on short PRDs Amol Surati 2018-06-20 4:29 ` [Qemu-devel] [PATCH 1/2] ide/hw/core: fix crash on processing a partial-sector-size DMA xfer Amol Surati 2018-06-25 21:10 ` John Snow 2018-06-26 1:30 ` Amol Surati 2018-06-20 4:29 ` [Qemu-devel] [PATCH 2/2] tests/ide-test: test case for crash when processing short PRDs Amol Surati
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).