From: Alexander Popov <alex.popov@linux.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>,
Laurent Vivier <lvivier@redhat.com>,
Darren Kenny <darren.kenny@oracle.com>,
sstabellini@kernel.org, pmatouse@redhat.com,
mdroth@linux.vnet.ibm.com, qemu-block@nongnu.org,
"Michael S . Tsirkin" <mst@redhat.com>,
qemu-stable@nongnu.org, qemu-devel@nongnu.org,
Kashyap Chamarthy <kashyap.cv@gmail.com>,
Thomas Huth <thuth@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>, John Snow <jsnow@redhat.com>,
pjp@redhat.com
Subject: Re: [PATCH v2 1/2] tests/ide-test: Create a single unit-test covering more PRDT cases
Date: Thu, 19 Dec 2019 18:33:15 +0300 [thread overview]
Message-ID: <dd64e9c8-c720-6569-c629-3d0c58ee7b43@linux.com> (raw)
In-Reply-To: <20191219151203.GM5230@linux.fritz.box>
Hello Kevin,
Thanks for your review!
On 19.12.2019 18:12, Kevin Wolf wrote:
> Am 16.12.2019 um 19:14 hat Alexander Popov geschrieben:
>> Fuzzing the Linux kernel with syzkaller allowed to find how to crash qemu
>> using a special SCSI_IOCTL_SEND_COMMAND. It hits the assertion in
>> ide_dma_cb() introduced in the commit a718978ed58a in July 2015.
>> Currently this bug is not reproduced by the unit tests.
>>
>> Let's improve the ide-test to cover more PRDT cases including one
>> that causes this particular qemu crash.
>>
>> The test is developed according to the Programming Interface for
>> Bus Master IDE Controller (Revision 1.0 5/16/94).
>>
>> Signed-off-by: Alexander Popov <alex.popov@linux.com>
>
> Looks mostly good to me, but I have a few comments.
>
> First of all, the patch order needs to be reversed to keep the tree
> bisectable (first fix the bug, then test that it's fixed).
Ok, I'll do that.
>> +/*
>> + * This test is developed according to the Programming Interface for
>> + * Bus Master IDE Controller (Revision 1.0 5/16/94)
>> + */
>> +static void test_bmdma_various_prdts(void)
>> {
>> - QTestState *qts;
>> - QPCIDevice *dev;
>> - QPCIBar bmdma_bar, ide_bar;
>> - uint8_t status;
>> -
>> - PrdtEntry prdt[] = {
>> - {
>> - .addr = 0,
>> - .size = cpu_to_le32(0x1000 | PRDT_EOT),
>> - },
>> - };
>> -
>> - qts = test_bmdma_setup();
>> -
>> - dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
>> -
>> - /* Normal request */
>> - status = send_dma_request(qts, CMD_READ_DMA, 0, 1,
>> - prdt, ARRAY_SIZE(prdt), NULL);
>> - g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR);
>> - assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
>> + uint32_t size = 0;
>> + uint32_t prd_size = 0;
>> + int req_sectors = 0;
>> + uint32_t req_size = 0;
>> + uint8_t s1 = 0, s2 = 0;
>> +
>> + for (size = 0; size < 65536; size += 256) {
>
> We're testing 64 * 4 = 256 cases here, each of them starting a new qemu
> process. Do we actually test anything new after the first couple of
> requests or does this just make the test slower than it needs to be?
>
> This test case really takes a long time for me (minutes), whereas all
> other cases in ide-test combined run in like a second.
>
> I would either test much less different sizes or at least run them in
> the same qemu process. Or both, of course.
Yes, it takes 3 minutes to run this test on my laptop.
Thanks for the idea. I'll try to run all the requests in a single qemu process.
>> + /*
>> + * Two bytes specify the count of the region in bytes.
>> + * The bit 0 is always set to 0.
>> + * A value of zero in these two bytes indicates 64K.
>> + */
>> + prd_size = size & 0xfffe;
>> + if (prd_size == 0) {
>> + prd_size = 65536;
>> + }
>>
>> - /* Abort the request before it completes */
>> - status = send_dma_request(qts, CMD_READ_DMA | CMDF_ABORT, 0, 1,
>> - prdt, ARRAY_SIZE(prdt), NULL);
>> - g_assert_cmphex(status, ==, BM_STS_INTR);
>> - assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
>> - free_pci_device(dev);
>> - test_bmdma_teardown(qts);
>> + for (req_sectors = 1; req_sectors <= 256; req_sectors *= 2) {
>> + req_size = req_sectors * 512;
>> +
>> + /*
>> + * 1. If PRDs specified a smaller size than the IDE transfer
>> + * size, then the Interrupt and Active bits in the Controller
>> + * status register are not set (Error Condition).
>> + *
>> + * 2. If the size of the physical memory regions was equal to
>> + * the IDE device transfer size, the Interrupt bit in the
>> + * Controller status register is set to 1, Active bit is set to 0.
>> + *
>> + * 3. If PRDs specified a larger size than the IDE transfer size,
>> + * the Interrupt and Active bits in the Controller status register
>> + * are both set to 1.
>> + */
>> + if (prd_size < req_size) {
>> + s1 = 0;
>> + s2 = 0;
>> + } else if (prd_size == req_size) {
>> + s1 = BM_STS_INTR;
>> + s2 = BM_STS_INTR;
>> + } else {
>> + s1 = BM_STS_ACTIVE | BM_STS_INTR;
>> + s2 = BM_STS_INTR;
>> + }
>> + test_bmdma_prdt(size, req_sectors, s1, s2);
>> + }
>> + }
>> }
>
> And finally, as mentioned in the reply for patch 2, I wonder if we
> should add a case with an empty PRDT (passing 0 as the PRDT size). This
> would be a separate patch, though.
Do you mean zero PRD size here?
The specification says that a value of zero in PRD size indicates 64K.
That's why we have the following code in bmdma_prepare_buf():
len = prd.size & 0xfffe;
if (len == 0)
len = 0x10000;
That case is already tested in my version. Let me quote the code above:
>> + for (size = 0; size < 65536; size += 256) {
Best regards,
Alexander
prev parent reply other threads:[~2019-12-19 15:34 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-16 18:14 [PATCH v2 1/2] tests/ide-test: Create a single unit-test covering more PRDT cases Alexander Popov
2019-12-16 18:14 ` [PATCH v2 2/2] ide: Fix incorrect handling of some PRDTs in ide_dma_cb() Alexander Popov
2019-12-19 15:01 ` Kevin Wolf
2019-12-19 15:46 ` Alexander Popov
2019-12-24 0:20 ` John Snow
2019-12-24 4:18 ` Alexander Popov
2020-01-01 22:45 ` Alexander Popov
2019-12-19 15:12 ` [PATCH v2 1/2] tests/ide-test: Create a single unit-test covering more PRDT cases Kevin Wolf
2019-12-19 15:33 ` Alexander Popov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=dd64e9c8-c720-6569-c629-3d0c58ee7b43@linux.com \
--to=alex.popov@linux.com \
--cc=aarcange@redhat.com \
--cc=darren.kenny@oracle.com \
--cc=jsnow@redhat.com \
--cc=kashyap.cv@gmail.com \
--cc=kwolf@redhat.com \
--cc=lvivier@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=pjp@redhat.com \
--cc=pmatouse@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
--cc=sstabellini@kernel.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).