* Re: [Qemu-devel] SPARC iommu mapping
2006-04-07 15:44 [Qemu-devel] SPARC iommu mapping Blue Swirl
@ 2006-04-07 21:33 ` Joerg Platte
2006-04-09 16:31 ` Joerg Platte
2006-04-10 13:18 ` Joerg Platte
2 siblings, 0 replies; 16+ messages in thread
From: Joerg Platte @ 2006-04-07 21:33 UTC (permalink / raw)
To: qemu-devel
Am Freitag, 7. April 2006 17:44 schrieb Blue Swirl:
Hi!
> Thank you for the excellent analysis of the problem! Looks like Qemu
> doesn't handle the case where DMA length and SCSI length are not equal.
Exact.
> So Linux splits the transfer into two parts to use two separate pieces of
> buffers. Funny, I thought this situation was exactly the one which
> virtually addressed DMA would prevent from happening.
I read somewhere, that Solaris and Linux unfortunately do not try to allocate
subsequent virtual addresses.
> Yes, there will be an interrupt. I didn't find this situation in the
> NCR53C9X.txt file documenting the ESP, though.
Me too. I tried to understand what's going wrong, but it is not that easy to
understand the Linux source, if you don't know much about the hardware and
the esp/iommu/dma/sbus architecture.
> There are two cases:
> 1 - DMA length shorter than SCSI (your case)
> 2 - SCSI length shorter (could happen in command replies etc.)
>
> Maybe this patch helps?
Unfortunately not. I tried a similar approach, but it didn't work. Here is the
dump:
First the mapping, similar to the one described in the last mail:
IOMMU: page flush f0039000
IOMMU: page flush f003a000
IOMMU: page flush f003b000
IOMMU: page flush f003c000
IOMMU: page flush f003d000
IOMMU: page flush f003e000
IOMMU: page flush f003f000
IOMMU: page flush f0040000
IOMMU: page flush f0041000
IOMMU: page flush f0042000
IOMMU: page flush f0043000
IOMMU: page flush f0044000
IOMMU: page flush f0045000
IOMMU: page flush f000e000
Then the transfer, which stops after three pages, since the Transfer
information len is 12288:
ESP: Transfer Information len 12288
ESP: DMA Direction: r, addr 0x0bdea000 0000e000
ESP: DMA address p 0bdea000 v f0039000
ESP: DMA address p 0bdeb000 v f003a000
ESP: DMA address p 0bdec000 v f003b000
ESP: Write callback (offset 224 len 112 size 57344 trans_size 12288)
Now I would expect, that "somebody" (maybe the esp inerrupt handler) updates
the dma registers to map the remaining pages. But this does not happen. Linux
simply unmaps the old mapping:
IOMMU: page flush f0039000
IOMMU: page flush f003a000
IOMMU: page flush f003b000
IOMMU: page flush f003c000
IOMMU: page flush f003d000
IOMMU: page flush f003e000
IOMMU: page flush f003f000
IOMMU: page flush f0040000
IOMMU: page flush f0041000
IOMMU: page flush f0042000
IOMMU: page flush f0043000
IOMMU: page flush f0044000
IOMMU: page flush f0045000
IOMMU: page flush f000e000
and configures a new one:
IOMMU: page flush f000f000
IOMMU: page flush f0010000
IOMMU: page flush f0011000
IOMMU: page flush f0012000
IOMMU: page flush f0013000
IOMMU: page flush f0014000
IOMMU: page flush f0015000
IOMMU: page flush f0016000
IOMMU: page flush f0017000
IOMMU: page flush f0018000
IOMMU: page flush f0019000
IOMMU: page flush f001a000
IOMMU: page flush f001b000
IOMMU: page flush f001c000
Then, a few pages of the new mapping are written to disk:
ESP: Transfer Information len 36864
ESP: DMA Direction: r, addr 0x0bdfa000 0000e000
ESP: DMA address p 0bdfa000 v f000f000
ESP: DMA address p 0bdfb000 v f0010000
ESP: DMA address p 0bdfc000 v f0011000
ESP: DMA address p 0bdfd000 v f0012000
ESP: DMA address p 0bdfe000 v f0013000
ESP: DMA address p 0bdff000 v f0014000
ESP: DMA address p 0be00000 v f0015000
ESP: DMA address p 0be01000 v f0016000
ESP: DMA address p 0be02000 v f0017000
ESP: Write callback (offset 336 len 112 size 57344 trans_size 36864)
Then this ara is unmapped, and Linux continues with the next area.
Hence, your patch avoids the zero mapping, but it does not provide the
required information which should result in a new dma addressing to write the
remaining mapped data. Tomorrow, I'll try to enable more debbugging in the
Linux driver to try to find out what's going wrong. But with a real hardware
it's more difficult to get an idea of the internal functions :(
regards,
Jörg
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-07 15:44 [Qemu-devel] SPARC iommu mapping Blue Swirl
2006-04-07 21:33 ` Joerg Platte
@ 2006-04-09 16:31 ` Joerg Platte
2006-04-10 13:18 ` Joerg Platte
2 siblings, 0 replies; 16+ messages in thread
From: Joerg Platte @ 2006-04-09 16:31 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 703 bytes --]
Am Freitag, 7. April 2006 17:44 schrieb Blue Swirl:
Hi!
> Maybe this patch helps?
The attached patch is an updated version of your patch. With whis patch I was
able to copy files from one directory to another on a disk image. After
unmounting the image, e2fsck reported no errors on this image. But
unfortunately, booting from this image was not possible. INIT reported a
segmentation violation. Maybe there is something else wrong. But now writing
works much better than before :-)
regards,
Jörg
PS: Is there any reason, why qemu copies disk data byte by byte? Calling
iommu_translate only once per page and copying a whole page could speed up
disk access significantly...
[-- Attachment #2: qemu-write.patch --]
[-- Type: text/x-diff, Size: 5321 bytes --]
--- esp.c.orig 2006-04-09 18:20:38.000000000 +0200
+++ esp.c 2006-04-09 18:04:15.000000000 +0200
@@ -63,6 +63,8 @@
ESPDMAFunc *dma_cb;
int64_t offset, len;
int target;
+ int blocksize;
+ int ti_bufstart;
};
#define STAT_DO 0x00
@@ -229,12 +231,12 @@
target_phys_addr_t phys_addr,
int transfer_size1)
{
+ int len = transfer_size1/s->blocksize;
DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
s->offset, s->len, s->ti_size, transfer_size1);
- bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
- s->offset = 0;
- s->len = 0;
- s->target = 0;
+
+ bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_bufstart, len);
+ s->offset+=len;
return 0;
}
@@ -265,6 +267,7 @@
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
+ s->ti_bufstart = 0;
if (target >= 4 || !s->bd[target]) { // No such drive
s->rregs[4] = STAT_IN;
@@ -293,6 +296,7 @@
s->ti_buf[3] = 2;
s->ti_buf[4] = 32;
s->ti_dir = 1;
+ s->ti_bufstart = 0;
s->ti_size = 36;
break;
case 0x1a:
@@ -314,6 +318,7 @@
s->ti_buf[6] = 2; // sector size 512
s->ti_buf[7] = 0;
s->ti_dir = 1;
+ s->ti_bufstart = 0;
s->ti_size = 8;
break;
case 0x28:
@@ -336,6 +341,7 @@
bdrv_read(s->bd[target], offset, s->ti_buf, len);
// XXX error handling
s->ti_dir = 1;
+ s->ti_bufstart = 0;
break;
}
case 0x2a:
@@ -346,10 +352,12 @@
offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
len = ((buf[8] << 8) | buf[9]) * 4;
s->ti_size = len * 2048;
+ s->blocksize=2048;
} else {
offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
len = (buf[8] << 8) | buf[9];
s->ti_size = len * 512;
+ s->blocksize=512;
}
DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
if (s->ti_size > TI_BUFSZ) {
@@ -359,6 +367,7 @@
s->offset = offset;
s->len = len;
s->target = target;
+ s->ti_bufstart = 0;
// XXX error handling
s->ti_dir = 0;
break;
@@ -400,6 +409,7 @@
break;
}
s->ti_dir = 1;
+ s->ti_bufstart = 0;
break;
}
default:
@@ -415,10 +425,9 @@
static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr;
- dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer status len %d\n", dmalen);
+ DPRINTF("Transfer status len %d\n", len);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +437,10 @@
s->rregs[6] = SEQ_CD;
} else {
memcpy(s->ti_buf, buf, len);
- s->ti_size = dmalen;
+ s->ti_size = len;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = len;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
@@ -442,34 +451,57 @@
static void handle_ti(ESPState *s)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr, dmalen, minlen;
unsigned int i;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer Information len %d\n", dmalen);
+ if (dmalen==0) {
+ dmalen=0x10000;
+ }
+
+ minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+ DPRINTF("Transfer Information len %d\n", minlen);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
- DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
- for (i = 0; i < s->ti_size; i++) {
+ DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_bufstart, s->ti_dir);
+ for (i = 0; i < minlen; i++) {
dmaptr = iommu_translate(s->espdmaregs[1] + i);
if (s->ti_dir)
- cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_bufstart+i], 1);
else
- cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_bufstart+i], 1);
}
if (s->dma_cb) {
- s->dma_cb(s, s->espdmaregs[1], dmalen);
+ s->dma_cb(s, s->espdmaregs[1], minlen);
+ }
+ if (minlen<s->ti_size) {
+ s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir?STAT_DO:STAT_DI);
+ s->ti_size-=minlen;
+ s->ti_bufstart+=minlen;
+ } else {
+ s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->dma_cb = NULL;
+ s->offset = 0;
+ s->len = 0;
+ s->target = 0;
+ s->ti_bufstart = 0;
}
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
- s->rregs[5] = INTR_BS;
+ s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
+ s->rregs[7] = 0;
s->espdmaregs[0] |= DMA_INTR;
} else {
- s->ti_size = dmalen;
+ s->ti_size = minlen;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = minlen;
}
pic_set_irq(s->irq, 1);
}
@@ -485,8 +517,10 @@
s->ti_rptr = 0;
s->ti_wptr = 0;
s->ti_dir = 0;
+ s->ti_bufstart = 0;
s->dma = 0;
s->dma_cb = NULL;
+ s->blocksize = 0;
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-07 15:44 [Qemu-devel] SPARC iommu mapping Blue Swirl
2006-04-07 21:33 ` Joerg Platte
2006-04-09 16:31 ` Joerg Platte
@ 2006-04-10 13:18 ` Joerg Platte
2006-04-11 19:21 ` Blue Swirl
2 siblings, 1 reply; 16+ messages in thread
From: Joerg Platte @ 2006-04-10 13:18 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 228 bytes --]
Am Freitag, 7. April 2006 17:44 schrieb Blue Swirl:
Hi!
The attached patch is an updated version of my previous patch. Now it applies
cleanly to cvs head and the read and write performance is increased.
regards,
Jörg
[-- Attachment #2: qemu-write2.patch --]
[-- Type: text/x-diff, Size: 5691 bytes --]
--- esp.c 2006-04-10 14:51:37.000000000 +0200
+++ esp.c.new 2006-04-10 14:54:44.000000000 +0200
@@ -63,6 +63,8 @@
ESPDMAFunc *dma_cb;
int64_t offset, len;
int target;
+ int blocksize;
+ int ti_bufstart;
};
#define STAT_DO 0x00
@@ -229,12 +231,12 @@
target_phys_addr_t phys_addr,
int transfer_size1)
{
+ int len = transfer_size1/s->blocksize;
DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
s->offset, s->len, s->ti_size, transfer_size1);
- bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
- s->offset = 0;
- s->len = 0;
- s->target = 0;
+
+ bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_bufstart, len);
+ s->offset+=len;
return 0;
}
@@ -265,6 +267,7 @@
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
+ s->ti_bufstart = 0;
if (target >= 4 || !s->bd[target]) { // No such drive
s->rregs[4] = STAT_IN;
@@ -293,6 +296,7 @@
s->ti_buf[3] = 2;
s->ti_buf[4] = 32;
s->ti_dir = 1;
+ s->ti_bufstart = 0;
s->ti_size = 36;
break;
case 0x1a:
@@ -314,6 +318,7 @@
s->ti_buf[6] = 2; // sector size 512
s->ti_buf[7] = 0;
s->ti_dir = 1;
+ s->ti_bufstart = 0;
s->ti_size = 8;
break;
case 0x28:
@@ -336,6 +341,7 @@
bdrv_read(s->bd[target], offset, s->ti_buf, len);
// XXX error handling
s->ti_dir = 1;
+ s->ti_bufstart = 0;
break;
}
case 0x2a:
@@ -346,10 +352,12 @@
offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
len = ((buf[8] << 8) | buf[9]) * 4;
s->ti_size = len * 2048;
+ s->blocksize=2048;
} else {
offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
len = (buf[8] << 8) | buf[9];
s->ti_size = len * 512;
+ s->blocksize=512;
}
DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
if (s->ti_size > TI_BUFSZ) {
@@ -359,6 +367,7 @@
s->offset = offset;
s->len = len;
s->target = target;
+ s->ti_bufstart = 0;
// XXX error handling
s->ti_dir = 0;
break;
@@ -400,6 +409,7 @@
break;
}
s->ti_dir = 1;
+ s->ti_bufstart = 0;
break;
}
default:
@@ -415,10 +425,9 @@
static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr;
- dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer status len %d\n", dmalen);
+ DPRINTF("Transfer status len %d\n", len);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +437,10 @@
s->rregs[6] = SEQ_CD;
} else {
memcpy(s->ti_buf, buf, len);
- s->ti_size = dmalen;
+ s->ti_size = len;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = len;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
@@ -442,34 +451,58 @@
static void handle_ti(ESPState *s)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr, dmalen, minlen, len, from, to;
unsigned int i;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer Information len %d\n", dmalen);
+ if (dmalen==0) {
+ dmalen=0x10000;
+ }
+
+ minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+ DPRINTF("Transfer Information len %d\n", minlen);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
- DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
- for (i = 0; i < s->ti_size; i++) {
+ DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_bufstart, s->ti_dir);
+ from=s->espdmaregs[1];
+ to=from+minlen;
+ for (i = 0; i < minlen; i+=len, from+=len) {
dmaptr = iommu_translate(s->espdmaregs[1] + i);
+ if ((from&TARGET_PAGE_MASK)!=(to&TARGET_PAGE_MASK)) {
+ len=TARGET_PAGE_SIZE-(from&~TARGET_PAGE_MASK);
+ } else {
+ len=to-from;
+ }
+ DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
if (s->ti_dir)
- cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_bufstart+i], len);
else
- cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_bufstart+i], len);
}
if (s->dma_cb) {
- s->dma_cb(s, s->espdmaregs[1], dmalen);
+ s->dma_cb(s, s->espdmaregs[1], minlen);
+ }
+ if (minlen<s->ti_size) {
+ s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir?STAT_DO:STAT_DI);
+ s->ti_size-=minlen;
+ s->ti_bufstart+=minlen;
+ } else {
+ s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->dma_cb = NULL;
+ s->offset = 0;
+ s->len = 0;
+ s->target = 0;
+ s->ti_bufstart = 0;
}
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
- s->rregs[5] = INTR_BS;
+ s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
+ s->rregs[7] = 0;
s->espdmaregs[0] |= DMA_INTR;
} else {
- s->ti_size = dmalen;
+ s->ti_size = minlen;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = minlen;
}
pic_set_irq(s->irq, 1);
}
@@ -485,8 +518,10 @@
s->ti_rptr = 0;
s->ti_wptr = 0;
s->ti_dir = 0;
+ s->ti_bufstart = 0;
s->dma = 0;
s->dma_cb = NULL;
+ s->blocksize = 0;
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-10 13:18 ` Joerg Platte
@ 2006-04-11 19:21 ` Blue Swirl
2006-04-14 16:07 ` Joerg Platte
0 siblings, 1 reply; 16+ messages in thread
From: Blue Swirl @ 2006-04-11 19:21 UTC (permalink / raw)
To: jplatte, qemu-devel
>The attached patch is an updated version of my previous patch. Now it
>applies
>cleanly to cvs head and the read and write performance is increased.
Great work! Now the Debian 3.0r4 installer with 2.6.11+tcx kernel almost
finishes. Performance is also much better.
There is some problem with CDROM access, the files on CD look corrupt,
whereas the same image used as hdb works perfectly.
Some comments on the code: Instead of adding s->bufstart, maybe you could
use the s->rptr, as it is used for similar purpose for FIFO. Please add more
spaces to conform to general code style.
For even better performance, you could try to avoid the memory to buffer
copy and give bdrv_read pointer to host memory.
_________________________________________________________________
FREE pop-up blocking with the new MSN Toolbar - get it now!
http://toolbar.msn.click-url.com/go/onm00200415ave/direct/01/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-11 19:21 ` Blue Swirl
@ 2006-04-14 16:07 ` Joerg Platte
2006-04-17 8:49 ` Blue Swirl
0 siblings, 1 reply; 16+ messages in thread
From: Joerg Platte @ 2006-04-14 16:07 UTC (permalink / raw)
To: Blue Swirl; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1689 bytes --]
Am Dienstag, 11. April 2006 21:21 schrieb Blue Swirl:
Hi!
> Great work! Now the Debian 3.0r4 installer with 2.6.11+tcx kernel almost
> finishes. Performance is also much better.
I tried to boot a deb-bootstrapped SPARC image. But the first executed script
segfaults when executing another command in backticks. The same happens when
executing the bash and inside the bash another command. When the other
command exits the bash segfaults. Other shells like the csh or the tcsh don't
suffer from this problem.
After replacing the bash in the image with a minimal bourne compatible shell
qemu was able to execute all scripts in rcS.
Then I tried to track down this problem with gdb and strace. But
unfortunately, both are segfaulting, too. This makes debugging somewhat
harder... Now, I'll try to analyze the core files of the crashing programs to
get an idea what's going wrong. Or do you have any idea? What's the
difference between bash compared to other shells?
> There is some problem with CDROM access, the files on CD look corrupt,
> whereas the same image used as hdb works perfectly.
Strange. I started qemu with "-cdrom /dev/cdrom" and could see all contents
without a problem. What exactly did you try?
> Some comments on the code: Instead of adding s->bufstart, maybe you could
> use the s->rptr, as it is used for similar purpose for FIFO. Please add
> more spaces to conform to general code style.
OK, have a look at the attached patch.
> For even better performance, you could try to avoid the memory to buffer
> copy and give bdrv_read pointer to host memory.
Yes, I'll try this in the next patch :-)
regards,
Jörg
[-- Attachment #2: qemu-sparc-write-patch.diff --]
[-- Type: text/x-diff, Size: 4303 bytes --]
--- esp.c 2006-04-14 17:53:09.000000000 +0200
+++ esp.c.new 2006-04-14 17:49:55.000000000 +0200
@@ -229,12 +229,17 @@
target_phys_addr_t phys_addr,
int transfer_size1)
{
+ int len;
+ if (bdrv_get_type_hint(s->bd[s->target]) == BDRV_TYPE_CDROM) {
+ len = transfer_size1/2048;
+ } else {
+ len = transfer_size1/512;
+ }
DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
s->offset, s->len, s->ti_size, transfer_size1);
- bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
- s->offset = 0;
- s->len = 0;
- s->target = 0;
+
+ bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_rptr, len);
+ s->offset+=len;
return 0;
}
@@ -336,6 +341,7 @@
bdrv_read(s->bd[target], offset, s->ti_buf, len);
// XXX error handling
s->ti_dir = 1;
+ s->ti_rptr = 0;
break;
}
case 0x2a:
@@ -359,6 +365,7 @@
s->offset = offset;
s->len = len;
s->target = target;
+ s->ti_rptr = 0;
// XXX error handling
s->ti_dir = 0;
break;
@@ -415,10 +422,9 @@
static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr;
- dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer status len %d\n", dmalen);
+ DPRINTF("Transfer status len %d\n", len);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +434,10 @@
s->rregs[6] = SEQ_CD;
} else {
memcpy(s->ti_buf, buf, len);
- s->ti_size = dmalen;
+ s->ti_size = len;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = len;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
@@ -442,34 +448,58 @@
static void handle_ti(ESPState *s)
{
- uint32_t dmaptr, dmalen;
+ uint32_t dmaptr, dmalen, minlen, len, from, to;
unsigned int i;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
- DPRINTF("Transfer Information len %d\n", dmalen);
+ if (dmalen==0) {
+ dmalen=0x10000;
+ }
+
+ minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+ DPRINTF("Transfer Information len %d\n", minlen);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
- DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
- for (i = 0; i < s->ti_size; i++) {
+ DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_rptr, s->ti_dir);
+ from = s->espdmaregs[1];
+ to = from + minlen;
+ for (i = 0; i < minlen; i += len, from += len) {
dmaptr = iommu_translate(s->espdmaregs[1] + i);
+ if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
+ len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
+ } else {
+ len = to - from;
+ }
+ DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
if (s->ti_dir)
- cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_rptr + i], len);
else
- cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
+ cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_rptr + i], len);
}
if (s->dma_cb) {
- s->dma_cb(s, s->espdmaregs[1], dmalen);
+ s->dma_cb(s, s->espdmaregs[1], minlen);
+ }
+ if (minlen < s->ti_size) {
+ s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir ? STAT_DO : STAT_DI);
+ s->ti_size -= minlen;
+ s->ti_rptr += minlen;
+ } else {
+ s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->dma_cb = NULL;
+ s->offset = 0;
+ s->len = 0;
+ s->target = 0;
+ s->ti_rptr = 0;
}
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
- s->rregs[5] = INTR_BS;
+ s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
+ s->rregs[7] = 0;
s->espdmaregs[0] |= DMA_INTR;
} else {
- s->ti_size = dmalen;
+ s->ti_size = minlen;
s->ti_rptr = 0;
s->ti_wptr = 0;
- s->rregs[7] = dmalen;
+ s->rregs[7] = minlen;
}
pic_set_irq(s->irq, 1);
}
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-14 16:07 ` Joerg Platte
@ 2006-04-17 8:49 ` Blue Swirl
2006-05-03 18:37 ` Joerg Platte
0 siblings, 1 reply; 16+ messages in thread
From: Blue Swirl @ 2006-04-17 8:49 UTC (permalink / raw)
To: jplatte; +Cc: qemu-devel
>Then I tried to track down this problem with gdb and strace. But
>unfortunately, both are segfaulting, too. This makes debugging somewhat
>harder... Now, I'll try to analyze the core files of the crashing programs
>to
>get an idea what's going wrong. Or do you have any idea? What's the
>difference between bash compared to other shells?
I don't know, I noticed the same problem earlier. I think it's something
related to fork or clone.
> > There is some problem with CDROM access, the files on CD look corrupt,
> > whereas the same image used as hdb works perfectly.
>
>Strange. I started qemu with "-cdrom /dev/cdrom" and could see all contents
>without a problem. What exactly did you try?
This command fails when installing kernel and modules:
qemu-system-sparc -kernel vmlinux-2.6.11+tcx -cdrom
debian-30r4-sparc-binary-1.iso -hda hd -initrd debian-30r4-sparc.initrd
-nographic -append 'cdrom ramdisk_size=16384 devfs=mount rw root=/dev/rd/0'
"There was a problem installing the Drivers from
/instmnt/dists/woody/main/disks-sparc/current/sun4cdm/drivers.tgz"
and some errors in background.
Replace -cdrom with -hdb and the installer has no problems until installing
libc6.
>OK, have a look at the attached patch.
Much better, though a few spaces are still missing.
_________________________________________________________________
Dont just search. Find. Check out the new MSN Search!
http://search.msn.click-url.com/go/onm00200636ave/direct/01/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] SPARC iommu mapping
2006-04-17 8:49 ` Blue Swirl
@ 2006-05-03 18:37 ` Joerg Platte
2006-05-03 18:52 ` Blue Swirl
0 siblings, 1 reply; 16+ messages in thread
From: Joerg Platte @ 2006-05-03 18:37 UTC (permalink / raw)
To: Blue Swirl; +Cc: qemu-devel
Am Montag, 17. April 2006 10:49 schrieb Blue Swirl:
Hi!
> This command fails when installing kernel and modules:
> qemu-system-sparc -kernel vmlinux-2.6.11+tcx -cdrom
> debian-30r4-sparc-binary-1.iso -hda hd -initrd debian-30r4-sparc.initrd
> -nographic -append 'cdrom ramdisk_size=16384 devfs=mount rw root=/dev/rd/0'
After spending more time on this issue I tried to reproduce your problems. But
I can't find a suitable initrd. The initrd from ftp.debian.org caused an
Oops:
RAMDISK: ext2 filesystem found at block 0
RAMDISK: Loading 10028KiB [1 disk] into ram disk... done.
VFS: Mounted root (ext2 filesystem).
Root-NFS: No NFS server available, giving up.
Unable to handle kernel NULL pointer dereference
tsk->{mm,active_mm}->context = ffffffff
tsk->{mm,active_mm}->pgd = fc000000
\|/ ____ \|/
"@'/ ,. \`@"
/_| \__/ |_\
\__U_/
swapper(1): Oops [#1]
Which initrd did you use?
regards,
Jörg
^ permalink raw reply [flat|nested] 16+ messages in thread