* [Qemu-devel] DMA timeouts running a FreeBSD guest with last CVS snapshot
@ 2007-01-15 9:21 Carlo Marcelo Arenas Belon
2007-01-22 10:23 ` [Qemu-devel] [PATCH] " Carlo Marcelo Arenas Belon
0 siblings, 1 reply; 4+ messages in thread
From: Carlo Marcelo Arenas Belon @ 2007-01-15 9:21 UTC (permalink / raw)
To: qemu-devel
Greetings,
while testing a snapshot from the last CVS tree with a freshly installed amd64
FreeBSD 6.2 guest I noticed the following errors at boot time :
ad0: 2048MB <QEMU HARDDISK 0.8.3> at ata0-master WDMA2
ad0: FAILURE - READ_DMA timed out LBA=4194301
acd0: CDROM <QEMU CD-ROM/0.8.3> at ata1-master WDMA2
acd0: TIMEOUT - READ BIG retrying (1 retry left)
after the system finishes booting there are apparently no more timeouts and
the disk reports it is using UDMA2 through atacontrol but the IO performance is
poor while reads to the virtual disk around the same sector (the disk is 4194304
sectors long) that failed work fine.
# atacontrol mode ad0
current mode = WDMA2
# atacontrol cap ad0
Protocol ATA/ATAPI revision 7
device model QEMU HARDDISK
serial number QM00001
firmware revision 0.8.3
cylinders 4161
heads 16
sectors/track 63
lba supported 4194304 sectors
lba48 supported 4194304 sectors
dma supported
overlap not supported
the same can be reproduced with a FreeBSD 6.1 guest and also with i386 guests
including an old FreeBSD 5.3 guest and even with an amd64 Debian GNU/kFreeBSD
guest but AFAIK not with Linux, OpenBSD or [Open]Solaris.
the following are the details as detected by the FreeBSD kernel at boot from
dmesg (the relevant stuff) :
acpi0: <QEMU QEMURSDT> on motherboard
pcib0: <ACPI Host-PCI bridge> port 0xcf8-0xcff on acpi0
pci0: <ACPI PCI bus> on pcib0
atapci0: <Intel PIIX3 WDMA2 controller> port
0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0xc000-0xc00f at device 1.1 on pci0
ata0: <ATA channel 0> on atapci0
ata1: <ATA channel 1> on atapci0
the ata driver is configured to ask the devide for the available modes and
seems to be getting DMA2 and PIO4 from it, while defaulting to DMA as
configured.
the problem goes away if it is forced to run in PIO4 mode which is the only
possibility for the FreeBSD 5.3 system which otherwise hungs at boot.
the problem doesn't exist in qemu 0.8.2 and is therefore a regression, but
i'd yet to bisect the last changes to find the culprit, and since it seems to
be a FreeBSD only problem I am first adding debugging to the guest kernel,
to track it from the guest side.
nonetheless wanted to send this email, so that you guys had a heads up, and to
see if anyone had any ideas or some similar problems in other platforms (I am
using a Gentoo Linux Host).
Carlo
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH] Re: DMA timeouts running a FreeBSD guest with last CVS snapshot
2007-01-15 9:21 [Qemu-devel] DMA timeouts running a FreeBSD guest with last CVS snapshot Carlo Marcelo Arenas Belon
@ 2007-01-22 10:23 ` Carlo Marcelo Arenas Belon
2007-01-22 10:55 ` Aurelien Jarno
0 siblings, 1 reply; 4+ messages in thread
From: Carlo Marcelo Arenas Belon @ 2007-01-22 10:23 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1712 bytes --]
On Mon, Jan 15, 2007 at 03:21:36AM -0600, Carlo Marcelo Arenas Belon wrote:
> FreeBSD 6.2 guest I noticed the following errors at boot time :
>
> ad0: 2048MB <QEMU HARDDISK 0.8.3> at ata0-master WDMA2
> ad0: FAILURE - READ_DMA timed out LBA=4194301
> acd0: CDROM <QEMU CD-ROM/0.8.3> at ata1-master WDMA2
> acd0: TIMEOUT - READ BIG retrying (1 retry left)
>
The problem is that FreeBSD is sending a WIN_READDMA (0xC8) command to the
emulated PIIX3 controller before it sets the DMA address that will be used and
therefore the code in ide_dma_start is not setting bm->cur_addr to the right
value (it is left set to 0) and then it is failing the validation in
dma_buf_rw where the distance between bm->cur_addr and bm->addr is expected to
be smaller than 1 page (4K) and resulting in an EOT error and a timeout which
FreeBSD handles by resetting the IDE controller.
Apparently all other guests I'd tried (Linux, Solaris, OpenBSD and Windows)
set the address first (bmdma_addr_write) and then send the request for a DMA
command and are therefore not affected by this, but even if FreeBSD behavior
is peculiar, it should be OK if implemented against real hardware as per the
spec in :
http://www.intel.com/design/intarch/datashts/290550.htm
The following patch moves the initialization of bm->cur_addr to match FreeBSD
behavior while being also compatible with all other guests but keeping in
sync closely the values of the memory addresses which will be used for the DMA
in a way that better emulates real hardware.
Tested with guests running FreeBSD 6.2 amd64, OpenBSD 4.0 amd64, Ubuntu Linux
6.06 amd64, OpenSolaris b55b amd64, Windows 2000 Professional i386 and Gentoo
Linux 2006.1 i386.
Carlo
[-- Attachment #2: qemu-dma-freebsd.patch --]
[-- Type: text/plain, Size: 794 bytes --]
Index: hw/ide.c
===================================================================
RCS file: /sources/qemu/qemu/hw/ide.c,v
retrieving revision 1.51
diff -u -r1.51 ide.c
--- hw/ide.c 20 Jan 2007 01:12:17 -0000 1.51
+++ hw/ide.c 22 Jan 2007 09:50:20 -0000
@@ -2230,10 +2230,11 @@
return;
bm->ide_if = s;
bm->dma_cb = dma_cb;
- bm->cur_addr = bm->addr;
bm->cur_prd_last = 0;
bm->cur_prd_addr = 0;
bm->cur_prd_len = 0;
+ if (bm->cur_addr != bm->addr)
+ bm->cur_addr = bm->addr;
if (bm->status & BM_STATUS_DMAING) {
bm->dma_cb(bm, 0);
}
@@ -2363,6 +2364,7 @@
printf("%s: 0x%08x\n", __func__, val);
#endif
bm->addr = val & ~3;
+ bm->cur_addr = bm->addr;
}
static void bmdma_map(PCIDevice *pci_dev, int region_num,
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH] Re: DMA timeouts running a FreeBSD guest with last CVS snapshot
2007-01-22 10:23 ` [Qemu-devel] [PATCH] " Carlo Marcelo Arenas Belon
@ 2007-01-22 10:55 ` Aurelien Jarno
2007-01-23 10:40 ` [Qemu-devel] " Carlo Marcelo Arenas Belon
0 siblings, 1 reply; 4+ messages in thread
From: Aurelien Jarno @ 2007-01-22 10:55 UTC (permalink / raw)
To: qemu-devel
Carlo Marcelo Arenas Belon a écrit :
> On Mon, Jan 15, 2007 at 03:21:36AM -0600, Carlo Marcelo Arenas Belon wrote:
>> FreeBSD 6.2 guest I noticed the following errors at boot time :
>>
>> ad0: 2048MB <QEMU HARDDISK 0.8.3> at ata0-master WDMA2
>> ad0: FAILURE - READ_DMA timed out LBA=4194301
>> acd0: CDROM <QEMU CD-ROM/0.8.3> at ata1-master WDMA2
>> acd0: TIMEOUT - READ BIG retrying (1 retry left)
>>
>
> The problem is that FreeBSD is sending a WIN_READDMA (0xC8) command to the
> emulated PIIX3 controller before it sets the DMA address that will be used and
> therefore the code in ide_dma_start is not setting bm->cur_addr to the right
> value (it is left set to 0) and then it is failing the validation in
> dma_buf_rw where the distance between bm->cur_addr and bm->addr is expected to
> be smaller than 1 page (4K) and resulting in an EOT error and a timeout which
> FreeBSD handles by resetting the IDE controller.
>
> Apparently all other guests I'd tried (Linux, Solaris, OpenBSD and Windows)
> set the address first (bmdma_addr_write) and then send the request for a DMA
> command and are therefore not affected by this, but even if FreeBSD behavior
> is peculiar, it should be OK if implemented against real hardware as per the
> spec in :
>
> http://www.intel.com/design/intarch/datashts/290550.htm
>
> The following patch moves the initialization of bm->cur_addr to match FreeBSD
> behavior while being also compatible with all other guests but keeping in
> sync closely the values of the memory addresses which will be used for the DMA
> in a way that better emulates real hardware.
>
> Tested with guests running FreeBSD 6.2 amd64, OpenBSD 4.0 amd64, Ubuntu Linux
> 6.06 amd64, OpenSolaris b55b amd64, Windows 2000 Professional i386 and Gentoo
> Linux 2006.1 i386.
>
> Carlo
>
>
> ------------------------------------------------------------------------
>
> Index: hw/ide.c
> ===================================================================
> RCS file: /sources/qemu/qemu/hw/ide.c,v
> retrieving revision 1.51
> diff -u -r1.51 ide.c
> --- hw/ide.c 20 Jan 2007 01:12:17 -0000 1.51
> +++ hw/ide.c 22 Jan 2007 09:50:20 -0000
> @@ -2230,10 +2230,11 @@
> return;
> bm->ide_if = s;
> bm->dma_cb = dma_cb;
> - bm->cur_addr = bm->addr;
> bm->cur_prd_last = 0;
> bm->cur_prd_addr = 0;
> bm->cur_prd_len = 0;
> + if (bm->cur_addr != bm->addr)
> + bm->cur_addr = bm->addr;
Why using a condition here? This will probably be slower than doing
bm->cur_addr = bm->addr and the result is the same.
> if (bm->status & BM_STATUS_DMAING) {
> bm->dma_cb(bm, 0);
> }
> @@ -2363,6 +2364,7 @@
> printf("%s: 0x%08x\n", __func__, val);
> #endif
> bm->addr = val & ~3;
> + bm->cur_addr = bm->addr;
> }
>
> static void bmdma_map(PCIDevice *pci_dev, int region_num,
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] Re: DMA timeouts running a FreeBSD guest with last CVS snapshot
2007-01-22 10:55 ` Aurelien Jarno
@ 2007-01-23 10:40 ` Carlo Marcelo Arenas Belon
0 siblings, 0 replies; 4+ messages in thread
From: Carlo Marcelo Arenas Belon @ 2007-01-23 10:40 UTC (permalink / raw)
To: qemu-devel
On Mon, Jan 22, 2007 at 11:55:11AM +0100, Aurelien Jarno wrote:
> Carlo Marcelo Arenas Belon a écrit :
> >
> > The following patch moves the initialization of bm->cur_addr to match
> > FreeBSD behavior while being also compatible with all other guests
> >
the following snippet kept the initialization of bm->cur_addr inside the
ide_dma_start function as a failback as that is where it conceptually belongs.
that is not needed though, as the initialization of bm->addr and also
bm->cur_addr is now done when the address for DMA is send to the emulated
PIIX.
> > Index: hw/ide.c
> > ===================================================================
> > RCS file: /sources/qemu/qemu/hw/ide.c,v
> > retrieving revision 1.51
> > diff -u -r1.51 ide.c
> > --- hw/ide.c 20 Jan 2007 01:12:17 -0000 1.51
> > +++ hw/ide.c 22 Jan 2007 09:50:20 -0000
> > @@ -2230,10 +2230,11 @@
> > return;
> > bm->ide_if = s;
> > bm->dma_cb = dma_cb;
> > - bm->cur_addr = bm->addr;
> > bm->cur_prd_last = 0;
> > bm->cur_prd_addr = 0;
> > bm->cur_prd_len = 0;
> > + if (bm->cur_addr != bm->addr)
> > + bm->cur_addr = bm->addr;
>
> Why using a condition here? This will probably be slower than doing
> bm->cur_addr = bm->addr and the result is the same.
as I mentioned before, this initialization is not even needed, but I
kept it as a way to keep the original logic that used this function to setup
all initial values for the DMA.
in retrospective though I can see why it was a bad idea and confusing, so I'd
prepared version 2 of the patch that removes this and eliminates your concern
as well.
thanks,
Carlo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-01-23 10:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-15 9:21 [Qemu-devel] DMA timeouts running a FreeBSD guest with last CVS snapshot Carlo Marcelo Arenas Belon
2007-01-22 10:23 ` [Qemu-devel] [PATCH] " Carlo Marcelo Arenas Belon
2007-01-22 10:55 ` Aurelien Jarno
2007-01-23 10:40 ` [Qemu-devel] " Carlo Marcelo Arenas Belon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.