All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.