Re: [Qemu-devel] [PATCH] qemu: generate signals on tap I/O
Aurelien Jarno [EMAIL PROTECTED] writes: The patch below from KVM improves network transfers in a huge way. wget in a MIPS target now gives me a transfer speed of up to 120 Mbits/s with an e1000 emulated card. Without I/O signals, qemu is relying on periodic timer events to poll the I/O. That seems wrong, even though it works reasonably well because timers are so frequent. In KVM, timers are less frequent, and it does not work quite as well. Here is a quick try at a more elaborate patch. It attaches a signal to all[1] file descriptors that will be used in select(). Also, it uses a dedicated SIGIO handler rather than piggybacking on the alarm handler, so alarm I/O is changed to use SIGALRM. I copied the handler function from the alarm case, quite frankly I do not quite understand what is going on. Also, I left _WIN32 out, since I have no idea how signals work there. [1] The slirp file descriptors are not included yet. Anders. diff --git a/vl.c b/vl.c index c87e8bc..ff8ceef 100644 --- a/vl.c +++ b/vl.c @@ -1148,6 +1148,25 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) return 0; } +#ifndef _WIN32 +static void host_io_handler(int host_signum) +{ +CPUState *env = next_cpu; + +if (env) { +/* stop the currently executing cpu because io occured */ +cpu_interrupt(env, CPU_INTERRUPT_EXIT); +#ifdef USE_KQEMU +if (env-kqemu_enabled) { +kqemu_cpu_interrupt(env); +} +#endif +} + +event_pending = 1; +} +#endif + #ifdef _WIN32 void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) @@ -1240,7 +1259,20 @@ static uint64_t qemu_next_deadline(void) #define RTC_FREQ 1024 -static void enable_sigio_timer(int fd) +static void enable_sigio(int fd) +{ +struct sigaction act; + +sigfillset(act.sa_mask); +act.sa_flags = 0; +act.sa_handler = host_io_handler; + +sigaction(SIGIO, act, NULL); +fcntl(fd, F_SETFL, O_ASYNC); +fcntl(fd, F_SETOWN, getpid()); +} + +static void enable_sigalrm(int fd) { struct sigaction act; @@ -1249,8 +1281,9 @@ static void enable_sigio_timer(int fd) act.sa_flags = 0; act.sa_handler = host_alarm_handler; -sigaction(SIGIO, act, NULL); +sigaction(SIGALRM, act, NULL); fcntl(fd, F_SETFL, O_ASYNC); +fcntl(fd, F_SETSIG, SIGALRM); fcntl(fd, F_SETOWN, getpid()); } @@ -1287,7 +1320,7 @@ static int hpet_start_timer(struct qemu_alarm_timer *t) if (r 0) goto fail; -enable_sigio_timer(fd); +enable_sigalrm(fd); t-priv = (void *)(long)fd; return 0; @@ -1325,7 +1358,7 @@ static int rtc_start_timer(struct qemu_alarm_timer *t) return -1; } -enable_sigio_timer(rtc_fd); +enable_sigalrm(rtc_fd); t-priv = (void *)(long)rtc_fd; @@ -5481,6 +5514,10 @@ int qemu_set_fd_handler2(int fd, return -1; ioh-next = first_io_handler; first_io_handler = ioh; +#ifndef _WIN32 +enable_sigio(fd); +#endif + found: ioh-fd = fd; ioh-fd_read_poll = fd_read_poll;
[Qemu-devel] Patch for compiling with GCC 4
Hi all, I tried to compile qemu cvs head on my x86_64 linux with gcc 4.1.2 using --disable-gcc-check, I found compile fails as stated in configure before i disabled gcc check.. Error message, points to a problem of dyngen not correctly detecting function ends on i386 when last instruction is a jump. I applied following change and successfully compiled/run qemu i386. This extra test check for a relative backward jump to function exit ret, gcc 4 apparently generates a few of these. My small change to cvs head is : --- dyngen.c 2008-02-13 18:54:36.0 +0100 +++ dyngen.c2008-02-13 19:10:14.0 +0100 @@ -1474,7 +1474,7 @@ len = p_end - p_start; if (len == 0) error(empty code for %s, name); -if (p_end[-1] == 0xc3) { +if (p_end[-1] == 0xc3 || p_end[-2] == 0xeb) { len--; } else { error(ret or jmp expected at the end of %s, name); Bye Chris.
[Qemu-devel] Qemu emulation for PXA320 based board
Hello list! I am a newbie to QEMU. I have a PXA320 based target board and linux kernel which runs on it. I want to emulate the board on QEMU. Kindly, let me know how I can go about. Your help in this regard is highly appreciated. Any pointer, guidelines even direction to right path will be very helpful. Thanks in advance. Regards Devel.
Re: [Qemu-devel] BOCHS update with DMI functional
Ryan Harper wrote: I've already built the latest BOCHS and tested it myself, what I'm Oh, I see. looking for is what other testing and such needs to be done prior to getting QEMU to pull in a newer version of BOCHS. Sorry, that nobody else seems to be interested. :-( Robert Riebisch -- BTTR Software http://www.bttr-software.de/
Re: [Qemu-devel] How to extract content of a raw image on host?
On Sat, Feb 16, 2008 at 08:55:06AM +0100, Laurent Vivier wrote: Loop is not able to manage partition. You could use kpartx (from util-linux), which will create device nodes for each partition. Cheers, -- Stuart Brady
[Qemu-devel] [PATCH] KQEMU error checking
Hello, in recent days I've been able to consistently panic an OpenSolaris kernel (build 79b, 64-bit on dual-core Opteron with 4GB of RAM) by using KQEMU and running qemu with a -m (memory) parameter greater than about 1750. The panic would be due to a NULL pointer dereference and happen mainly in kqemu_init(). On Linux this does not seem to be a problem for some reason. Anyway, while nowhere near understanding root cause yet, I did sweep the code and came up with a patch to check for errors of certain internal functions - particularly errors that could eventually lead to NULL pointer dereferences, etc. So now either the kernel call will fail (and userspace will deal with it accordingly), or the monitor will just crash the running qemu process rather than panic the kernel if one of these error situations happens. What I discovered is that almost, if not all of these error situations come from the return value of the function get_vaddr() in common/common.c not being checked by its callers. get_vaddr() can return -1 if there is no virtual address available, but its callers were often assuming the return value was valid. Particularly common/mon_get_ptep_l3() would ignore it, and quickly lead to a kernel panic. I did not try the non-PAE version but I addressed it anyway with my patch. I was able to identify 2 distinct situations that would lead to a kernel panic, driven by the -m parameter from userspace. The first, if -m 1750, was likely due to mon_user_map() in common/kernel.c ignoring the return from get_vaddr(). I am not 100% sure about that as it was very difficult to debug this with the Solaris kernel debugger, but that's what I believe right now. The second and more traceable problem came when using a value greater than or equal to about 1800 for -m. That would crash consistently in kqemu_init() in common/kernel.c around line 564 where the monitor PTE pages are cloned in each address space. The result was that mon_get_ptep_l3() was ignoring a -1 return value from get_vaddr(), and in turn, kqemu_init() was also ignoring a potential NULL return value from mon_get_ptep_l3(), leading to a dereference of a NULL pointer. My patch below may have detected one condition that is not really an error, in phys_page_find() of common/monitor.c. The return of get_vaddr() there is not actually dereferenced, so I'm not sure that when it gets passed into set_vaddr_page_index() it's okay for it to be -1. Still, this situation does happen (the monitor panic) if you run qemu -m 1500 or so (I didn't compute exact values that trigger it, sorry), and the guest (i.e. Windows 2000) runs for a while. Note that the errors do not seem to be related to using -m values that are powers of 10 instead of powers of 2 - I tried either. While it's important that a userspace process never panic a kernel, I'm sure some of the error checking below is not accurate or may mask another problem that should be fixed rather than detected. If someone who understands the KQEMU code better than me can take a look, I would appreciate it. Note that I have both inlined and attached the patch for easy handling. The patch is against the latest KQEMU, and applies to either the one on www.qemu.org or the one from the OpenSolaris project cleanly. Special thanks to Juergen Keil for helping me with the Solaris kernel debugger (off list). Best regards, Leo Reiter diff -Naur kqemu_1.0.3pre11-20070520/common/common.c kqemu_1.0.3pre11-20070520.new/common/common.c --- kqemu_1.0.3pre11-20070520/common/common.c 2007-05-20 07:35:07.0 -0400 +++ kqemu_1.0.3pre11-20070520.new/common/common.c 2008-02-15 16:29:21.0 -0500 @@ -252,6 +252,8 @@ pdp_page_index = pml4e PAGE_SHIFT; } pdp_page = page_index_to_addr(s, pdp_page_index); +if (!pdp_page) +return NULL; pdpe_index = (vaddr 30) 0x1ff; pdpe = pdp_page[pdpe_index]; @@ -267,6 +269,8 @@ pde_page_index = pdpe PAGE_SHIFT; } pde_page = page_index_to_addr(s, pde_page_index); +if (!pde_page) +return NULL; pde_index = (vaddr 21) 0x1ff; if (alloc == 2) @@ -284,6 +288,8 @@ pte_page_index = pde PAGE_SHIFT; } pte_page = page_index_to_addr(s, pte_page_index); +if (!pte_page) +return NULL;/* XXX - ?? we don't dereference pte_page here */ pte_index = (vaddr 12) 0x1ff; #ifndef IN_MONITOR @@ -331,6 +337,8 @@ pde_page_index = pdpe PAGE_SHIFT; } pde_page = page_index_to_addr(s, pde_page_index); +if (!pde_page) +return NULL; pde_index = (vaddr 21) 0x1ff; if (alloc == 2) @@ -348,6 +356,8 @@ pte_page_index = pde PAGE_SHIFT; } pte_page = page_index_to_addr(s, pte_page_index); +if (!pte_page) +return NULL;/* XXX - ?? we don't dereference pte_page here */ pte_index = (vaddr 12) 0x1ff; #ifndef IN_MONITOR @@ -387,6 +397,9 @@ pte_page_index = pde PAGE_SHIFT; }
[Qemu-devel] qemu-system-amd64 (0.9.1) and freebsd guest - irq patch (pointer)
Hi! I received the following posting and patch, sent to the freebsd-emulation list, can anyone here say if it is correct, and if yes, apply? http://docs.freebsd.org/cgi/mid.cgi?20080216164331.GJ57756 (You can use the `Raw E-Mail' link to get the unmangled patch out.) Thanx, Juergen
Re: [Qemu-devel] Patch for compiling with GCC 4
On Saturday 16 February 2008, Christian Roue wrote: Hi all, I tried to compile qemu cvs head on my x86_64 linux with gcc 4.1.2 using --disable-gcc-check, I found compile fails as stated in configure before i disabled gcc check.. Error message, points to a problem of dyngen not correctly detecting function ends on i386 when last instruction is a jump. I applied following change and successfully compiled/run qemu i386. This extra test check for a relative backward jump to function exit ret, gcc 4 apparently generates a few of these. You patch is wrong. The dyngen error is correct. Paul
[Qemu-devel] [PATCH] mmap.c: Reuse unmapped memory areas.
Try to rewind mmap_next_start when unmapping memory. Simple tests in test-mmap.c now pass. Best regards -- Edgar E. Iglesias Axis Communications AB diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6292826..78a8162 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -385,6 +385,9 @@ int target_munmap(abi_ulong start, abi_ulong len) real_end -= qemu_host_page_size; } +if (start mmap_next_start) + mmap_next_start = start; + /* unmap what we can */ if (real_start real_end) { ret = munmap(g2h(real_start), real_end - real_start);
Re: [Qemu-devel] [PATCH] possible mmap regression
On Tue, Feb 12, 2008 at 09:42:15PM +0200, Felipe Contreras wrote: Hi, I don't know what I'm doing but this seems to fix the weird issue I was having. http://article.gmane.org/gmane.comp.emulators.qemu/23314 I've found out that this happens on linux 2.6.23, but not 2.6.24. Cheers. -- Felipe Contreras diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6292826..3050ad9 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -251,7 +251,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, especially important if qemu_host_page_size qemu_real_host_page_size */ p = mmap(g2h(mmap_start), - host_len, prot, flags | MAP_FIXED, fd, host_offset); + host_len, prot, flags, fd, host_offset); if (p == MAP_FAILED) return -1; /* update start so that it points to the file position at 'offset' */ Hello, Sorry, but I beleive your patch will break simulations where the targets pagesize is larger than the hosts. Would you mind trying the attach patched and let us know if it helps for you? If not, it would be great if you could provide a small test case that trigs the bug you are seeing so we can debug the problem. Best regards -- Edgar E. Iglesias Axis Communications AB diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6292826..78a8162 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -385,6 +385,9 @@ int target_munmap(abi_ulong start, abi_ulong len) real_end -= qemu_host_page_size; } +if (start mmap_next_start) + mmap_next_start = start; + /* unmap what we can */ if (real_start real_end) { ret = munmap(g2h(real_start), real_end - real_start);
[Qemu-devel] [PATCH] linux-user/mmap: Testsuite + bugfixes
Hi again, I spent some more time creating more mmap test-cases and managed to trig a few more bugs. Luckily, most of them were straight forward to fix. A few are related to the funny semantics of MAP_FILE mmaps beyond EOF. This posts elaborates a bit more on the issue: http://lists.gnu.org/archive/html/qemu-devel/2008-01/msg00163.html Tested on my intel centrino duo as host, for CRIS, MIPS and i386 targets. Used the -p flag to simulate 8K, 16K and 32K page-sizes. To run the tests for i386 just do a 'make -C tests test-mmap'. I hope this is helpful to somebody. Best regards -- Edgar E. Iglesias Axis Communications AB diff --git a/configure b/configure index bbda3f7..3df08ab 100755 --- a/configure +++ b/configure @@ -1244,6 +1244,7 @@ if test $source_path_used = yes ; then DIRS=tests tests/cris slirp audio FILES=Makefile tests/Makefile FILES=$FILES tests/cris/Makefile tests/cris/.gdbinit +FILES=$FILES tests/test-mmap.c for dir in $DIRS ; do mkdir -p $dir done diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6292826..3c77cc9 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -23,6 +23,8 @@ #include string.h #include unistd.h #include errno.h +#include sys/types.h +#include sys/stat.h #include sys/mman.h #include qemu.h @@ -153,10 +155,12 @@ static int mmap_frag(abi_ulong real_start, #if defined(__CYGWIN__) /* Cygwin doesn't have a whole lot of address space. */ -static abi_ulong mmap_next_start = 0x1800; +#define MMAP_BASE 0x1800 #else -static abi_ulong mmap_next_start = 0x4000; +#define MMAP_BASE 0x4000 #endif +static abi_ulong mmap_next_start = MMAP_BASE; + /* find a free memory area of size 'size'. The search starts at 'start'. If 'start' == 0, then a default start address is used. @@ -234,8 +238,40 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, len = TARGET_PAGE_ALIGN(len); if (len == 0) return start; -real_start = start qemu_host_page_mask; +/* When mapping files into a memory area larger than the file, accesses + to pages beyond the file size will cause a SIGBUS. + + For example, if mmaping a file of 100 bytes on a host with 4K pages + emulating a target with 8K pages, the target expects to be able to + access the first 8K. But the host will trap us on any access beyond + 4K. + + When emulating a target with a larger page-size than the hosts, we + may need to truncate file maps at EOF and add extra anonymous pages + up to the targets page boundary. */ + +if (!(flags MAP_ANONYMOUS)) { +struct stat sb; + + if (fstat (fd, sb) == -1) + return -1; + + /* Are trying to create a map beyond the EOF?. */ + if (offset + len sb.st_size) { + /* If so, truncate the file map at eof aligned with + the hosts real pagesize. Additional anonymous maps + will be created beyond EOF. */ + len = (sb.st_size - offset); + len += qemu_real_host_page_size - 1; + len = ~(qemu_real_host_page_size - 1); + } +} + +real_start = start qemu_host_page_mask; +end = start + len; +real_end = HOST_PAGE_ALIGN(end); + if (!(flags MAP_FIXED)) { abi_ulong mmap_start; void *p; @@ -251,9 +287,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, especially important if qemu_host_page_size qemu_real_host_page_size */ p = mmap(g2h(mmap_start), - host_len, prot, flags | MAP_FIXED, fd, host_offset); + len, prot, flags | MAP_FIXED, fd, host_offset); if (p == MAP_FAILED) return -1; + + /* If we are dealing with truncated file maps due to pagesize +* differences between host and target we may need to append +* an anonymous mapping. */ + if (len host_len) + mmap(g2h(mmap_start) + len, qemu_host_page_size, +prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + /* update start so that it points to the file position at 'offset' */ host_start = (unsigned long)p; if (!(flags MAP_ANONYMOUS)) @@ -264,8 +308,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, errno = EINVAL; return -1; } -end = start + len; -real_end = HOST_PAGE_ALIGN(end); /* worst case: we cannot map the file because the offset is not aligned, so we read it */ @@ -337,7 +379,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, page_set_flags(start, start + len, prot | PAGE_VALID); the_end: #ifdef DEBUG_MMAP -printf(ret=0x%llx\n, start); +printf(ret=0x TARGET_FMT_lx \n, start); page_dump(stdout); printf(\n); #endif @@ -385,6 +427,8 @@ int target_munmap(abi_ulong start, abi_ulong len)