[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] Re: DMA timeouts running a FreeBSD guest with l
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH] Re: DMA timeouts running a FreeBSD guest with last CVS snapshot |
Date: |
Mon, 22 Jan 2007 11:55:11 +0100 |
User-agent: |
IceDove 1.5.0.9 (X11/20061220) |
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
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net