Am Mittwoch, 5. April 2006 19:36 schrieb Blue Swirl: Hi! > I don't have any better documentation either, I just coded against what > Proll and Linux expect. But the theory of operation is simple. Much like
OK, I thought I was just too stupid to find good documentation :-) > how the MMU translates CPU's virtual addresses to physical addresses for > memory, IOMMU translates device virtual memory accesses to physical > addresses. The VA to PA entries are found in a simple page table. That's what I read from qemu's iommu functions. > In the case of not finding a valid translation entry, IOMMU can't fault the > device like normal MMU can easily fault the CPU. I don't know what should > happen then, probably put the address to AFAR register and raise some > interrupt, while the device (for example Ethernet controller) waiting for > the data suffers in limbo. I think it would be strange for an OS to rely on > this, so I guess it's a bug somewhere else. My guess for the valid bit is > that it's used in a real IOMMU to select the entries that will be loaded to > its internal translation buffer. Maybe. > The DMA controllers for both ESP and Lance are within the same page. This > means that in Qemu, DMA controller register accesses for either of them go > to just one of these. It just happens to work, but maybe this causes the > problem. You could try to confirm this by enabling also DEBUG_LANCE and see > if there is troublesome activity in the Lance direction near the bad > accesses. Hmmm, I don't use the network. Just disk access. But I'll check this. > Can you provide a test case so that I could try it as well? I'm using the two attached programs. writetest is used inside qemu to directly write to /dev/sda (with "writetest /dev/sda"). readtest can then be used outside qemu to check the written data ("readtest imagefile"). Additionally, I logged the translated virtual address as mentioned in my first mail. The kernel is 2.6.13. regards, Jörg
#include <stdio.h> int main(int argc, char**argv) { FILE *fp; unsigned char buffer[4]; unsigned int i,j; unsigned int doprint=1; unsigned int d=0; if ((fp=fopen(argv[1], "r"))) { for (i=0; i<10000000; i+=4) { if (fread(&buffer, 4, 1, fp)!=1) { printf("error writing at byte %d\n", i); break; } d=0; for(j=0;j<4; j++) { if (buffer[3-j]!=((i>>(j*8))&0xff)) { if (doprint) { printf("data differs at address %08x\n", i); } d=1; break; } } if (d) { doprint=0; } else { doprint=1; } } fclose(fp); } }
#include <stdio.h> int main(int argc, char**argv) { FILE *fp; unsigned int i; if ((fp=fopen(argv[1], "w"))) { for (i=0; i<10000000; i+=4) { if (fwrite(&i, 4, 1, fp)!=1) { printf("error writing at byte %d\n", i); break; } } fclose(fp); } }
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel