0.7.2-alt1 0.7.2-alt1
authorKachalov Anton <mouse@altlinux.ru>
Tue, 20 Sep 2005 08:06:25 +0000 (08:06 +0000)
committerKirill A. Shutemov <k.shutemov@gmail.com>
Tue, 20 Sep 2005 08:06:25 +0000 (08:06 +0000)
- 0.7.2
- Updated Kqemu to 0.7.2

49 files changed:
.gear-rules
kqemu/Changelog
kqemu/LICENSE
kqemu/Makefile
kqemu/kqemu-doc.html
kqemu/kqemu-doc.texi
kqemu/kqemu-freebsd.c
kqemu/kqemu-kernel.h [new file with mode: 0644]
kqemu/kqemu-linux.c
kqemu/kqemu-mod-i386-win32.o
kqemu/kqemu-mod-i386.o
kqemu/kqemu-mod-x86_64.o
kqemu/kqemu-win32.c
kqemu/kqemu.h
kqemu/kqemu.inf [new file with mode: 0644]
kqemu/kqemu.reg [deleted file]
kqemu/kqemu.sys
qemu-0.7.2-gtk.patch [new file with mode: 0644]
qemu-gtk/qemu-gtk-patch.diff [deleted file]
qemu.spec
qemu/Changelog
qemu/Makefile
qemu/Makefile.target
qemu/VERSION
qemu/configure
qemu/cpu-all.h
qemu/cpu-defs.h
qemu/cpu-exec.c
qemu/exec-all.h
qemu/exec.c
qemu/hw/ide.c
qemu/hw/mips_r4k.c
qemu/hw/sb16.c
qemu/kqemu.c
qemu/linux-user/arm-semi.c
qemu/linux-user/elfload.c
qemu/monitor.c
qemu/qemu-doc.html
qemu/qemu-doc.texi
qemu/qemu-img.1
qemu/qemu-tech.html
qemu/qemu.1
qemu/slirp/slirp.c
qemu/target-arm/translate.c
qemu/target-i386/helper.c
qemu/target-i386/op.c
qemu/target-i386/translate.c
qemu/vl.c
qemu/vl.h

index 50182cf..78e9dd3 100644 (file)
@@ -1,5 +1,5 @@
 copy: *.patch
-tar.bz2: kqemu name=kqemu-@version@.1 base=kqemu
+tar.gz: kqemu base=kqemu
 copy: kqemu-permission
 tar.bz2: qemu
 tar.bz2: qemu-gtk name=qemu-gtk-20050716 base=
index 610c29b..22ac275 100644 (file)
@@ -1,3 +1,14 @@
+version 0.7.2:
+
+- more precise segmentation support (aka Win98 support)
+- new API to track dirty RAM pages
+- CR4.TSD support
+- SYSENTER fix for x86_64
+- (Linux) added 'max_instances' module parameter
+- (win32) cpu interruption support (Filip Navara)
+- (win32) kqemu.inf installation file (Filip Navara)
+- IOPL restore fix (aka xen bug)
+
 version 0.7.1-1:
 
 - FreeBSD compile fixes - added x86_64 support
index 186b2cf..169cda1 100644 (file)
@@ -11,6 +11,9 @@
    implied warranty. In no event will the author be held liable for
    any damages arising from the use of this software.
 
-2) QEMU is a trademark of Fabrice Bellard.
+2) The header file "kqemu.h" can be freely used and distributed so
+   that it is possible to distribute QEMU binaries ready to use KQEMU.
+
+3) QEMU is a trademark of Fabrice Bellard.
 
 Fabrice Bellard.
\ No newline at end of file
index e28e5ea..f1d28c5 100644 (file)
@@ -25,11 +25,11 @@ clean:
        rm -f kqemu.o kqemu.ko kqemu-linux.o kqemu-mod.o kqemu.mod.c *~
 
 FILES=Makefile README Changelog LICENSE install.sh kqemu-linux.c kqemu.h \
-      kqemu-mod-i386.o kqemu-mod-x86_64.o \
+      kqemu-kernel.h kqemu-mod-i386.o kqemu-mod-x86_64.o \
       kqemu-freebsd.c Makefile.freebsd \
-      kqemu-win32.c kqemu.sys kqemu.reg kqemu-mod-i386-win32.o Makefile.winnt \
+      kqemu-win32.c kqemu.sys kqemu.inf kqemu-mod-i386-win32.o Makefile.winnt \
       kqemu-doc.texi kqemu-doc.html
-VERSION=0.7.1-1
+VERSION=0.7.2
 
 tar:
        cd .. ; tar zcvf /tmp/kqemu-$(VERSION).tar.gz $(addprefix kqemu/, $(FILES))
index 275511a..82d2599 100644 (file)
@@ -1,6 +1,6 @@
 <HTML>
 <HEAD>
-<!-- Created by texi2html 1.56k from kqemu-doc.texi on 24 July 2005 -->
+<!-- Created by texi2html 1.56k from kqemu-doc.texi on 4 September 2005 -->
 
 <TITLE>QEMU Accelerator User Documentation</TITLE>
 </HEAD>
@@ -93,7 +93,12 @@ If you use x86 Linux, the compilation of the QEMU Accelerator Kernel
 Module (KQEMU) is automatically activated provided you have the
 necessary kernel headers. If nonetheless the compilation fails, you
 can disable its compilation with the <SAMP>`--disable-kqemu'</SAMP>
-configure option.
+configure option. 
+
+
+<P>
+Note that KQEMU cannot currently work if the Xen virtualizer is
+running on your host.
 
 
 <P>
@@ -147,6 +152,11 @@ in <TT>`/etc/rc.d/rc.local'</TT>.
 
 
 <P>
+If the major number 250 is already used by another driver, you can use
+the option <CODE>major=N</CODE> to set an alternate major number.
+
+
+<P>
 If your distribution uses udev (like Fedora), use the kqemu module
 option <CODE>major=0</CODE> to have the device <TT>`/dev/kqemu'</TT> automatically
 created:
@@ -159,29 +169,20 @@ created:
 </PRE>
 
 <P>
-It is usually necessary to change the device access rights by doing as
-root: <CODE>chmod 666 /dev/kqemu</CODE>.
-
-
-<P>
-If the major number 250 is already used by another driver, you can use
-the option <CODE>major=N</CODE> to set an alternate major number.
+It is usually necessary to change the device access rights set by
+udev. Edit <TT>`/etc/udev/permissions.d/50-udev.permissions'</TT> and add:
 
+<PRE>
+# kqemu
+kqemu:root:root:0666
+</PRE>
 
 
 
 <H2><A NAME="SEC5" HREF="kqemu-doc.html#TOC5">2.3 QEMU Accelerator Installation for Windows</A></H2>
 
 <P>
-Copy the kqemu driver <TT>`kqemu.sys'</TT> to
-<TT>`c:\winnt\system32\drivers'</TT>.  Then do:
-
-<PRE>
-regedit kqemu.reg 
-</PRE>
-
-<P>
-Now kqemu is installed and you must restart your system.
+Right click on <TT>`kqemu.inf'</TT> in Explorer and choose Install.
 
 
 <P>
@@ -210,14 +211,14 @@ emulation problems are coming from KQEMU.
 </DL>
 
 <P>
-When using KQEMU, QEMU will create a big hidden file containing the
-RAM of the virtual machine. For best performance, it is important that
-this file is kept in RAM and not on the hard disk. QEMU uses the
-<TT>`/dev/shm'</TT> directory to create this file because <CODE>tmpfs</CODE> is
-usually mounted on it (check with the shell command
-<CODE>df</CODE>). Otherwise <TT>`/tmp'</TT> is used as fallback. You can use the
-<VAR>QEMU_TMPDIR</VAR> shell variable to set a new directory for the QEMU
-RAM file.
+When using KQEMU on a Linux or FreeBSD host, QEMU will create a big
+hidden file containing the RAM of the virtual machine. For best
+performance, it is important that this file is kept in RAM and not on
+the hard disk. QEMU uses the <TT>`/dev/shm'</TT> directory to create this
+file because <CODE>tmpfs</CODE> is usually mounted on it (check with the
+shell command <CODE>df</CODE>). Otherwise <TT>`/tmp'</TT> is used as
+fallback. You can use the <VAR>QEMU_TMPDIR</VAR> shell variable to set a
+new directory for the QEMU RAM file.
 
 
 <P>
@@ -240,7 +241,7 @@ info kqemu
 </PRE>
 
 <P><HR><P>
-This document was generated on 24 July 2005 using
+This document was generated on 4 September 2005 using
 <A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A>&nbsp;1.56k.
 </BODY>
 </HTML>
index e245a36..2196454 100644 (file)
@@ -54,7 +54,10 @@ If you use x86 Linux, the compilation of the QEMU Accelerator Kernel
 Module (KQEMU) is automatically activated provided you have the
 necessary kernel headers. If nonetheless the compilation fails, you
 can disable its compilation with the @option{--disable-kqemu}
-configure option.
+configure option. 
+
+Note that KQEMU cannot currently work if the Xen virtualizer is
+running on your host.
 
 If you are using a 2.6 host kernel, then all the necessary kernel
 headers should be already installed. If you are using a 2.4 kernel,
@@ -95,6 +98,9 @@ If you want that KQEMU is installed automatically at boot time, you can add
 
 in @file{/etc/rc.d/rc.local}.
 
+If the major number 250 is already used by another driver, you can use
+the option @code{major=N} to set an alternate major number.
+
 If your distribution uses udev (like Fedora), use the kqemu module
 option @code{major=0} to have the device @file{/dev/kqemu} automatically
 created:
@@ -104,21 +110,16 @@ created:
 /sbin/modprobe kqemu major=0
 @end example
 
-It is usually necessary to change the device access rights by doing as
-root: @code{chmod 666 /dev/kqemu}.
-
-If the major number 250 is already used by another driver, you can use
-the option @code{major=N} to set an alternate major number.
-
-@section QEMU Accelerator Installation for Windows
-
-Copy the kqemu driver @file{kqemu.sys} to
-@file{c:\winnt\system32\drivers}.  Then do:
+It is usually necessary to change the device access rights set by
+udev. Edit @file{/etc/udev/permissions.d/50-udev.permissions} and add:
 @example
-regedit kqemu.reg 
+# kqemu
+kqemu:root:root:0666
 @end example
 
-Now kqemu is installed and you must restart your system.
+@section QEMU Accelerator Installation for Windows
+
+Right click on @file{kqemu.inf} in Explorer and choose Install.
 
 In order to start kqemu, you must do:
 @example
@@ -137,14 +138,14 @@ usual but will be slower. This option can be useful to determine if
 emulation problems are coming from KQEMU.
 @end table
 
-When using KQEMU, QEMU will create a big hidden file containing the
-RAM of the virtual machine. For best performance, it is important that
-this file is kept in RAM and not on the hard disk. QEMU uses the
-@file{/dev/shm} directory to create this file because @code{tmpfs} is
-usually mounted on it (check with the shell command
-@code{df}). Otherwise @file{/tmp} is used as fallback. You can use the
-@var{QEMU_TMPDIR} shell variable to set a new directory for the QEMU
-RAM file.
+When using KQEMU on a Linux or FreeBSD host, QEMU will create a big
+hidden file containing the RAM of the virtual machine. For best
+performance, it is important that this file is kept in RAM and not on
+the hard disk. QEMU uses the @file{/dev/shm} directory to create this
+file because @code{tmpfs} is usually mounted on it (check with the
+shell command @code{df}). Otherwise @file{/tmp} is used as
+fallback. You can use the @var{QEMU_TMPDIR} shell variable to set a
+new directory for the QEMU RAM file.
 
 KQEMU has only been tested with Linux 2.4, Linux 2.6 and Windows 2000
 as guest OSes. If your guest OS do not work with KQEMU, you can
index a25f24f..88bd960 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: kqemu-freebsd.c,v 1.3 2005/07/28 21:43:47 bellard Exp $ */
+/* $Id: kqemu-freebsd.c,v 1.4 2005/08/14 16:34:06 bellard Exp $ */
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -20,9 +20,7 @@
 #include <machine/vmparam.h>
 #include <machine/stdarg.h>
 
-#define __KERNEL__
-
-#include "kqemu.h"
+#include "kqemu-kernel.h"
 
 MALLOC_DECLARE(M_KQEMU);
 MALLOC_DEFINE(M_KQEMU, "kqemu", "kqemu buffers");
diff --git a/kqemu/kqemu-kernel.h b/kqemu/kqemu-kernel.h
new file mode 100644 (file)
index 0000000..d1e9584
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * KQEMU kernel API
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ */
+#ifndef KQEMU_KERNEL_H
+#define KQEMU_KERNEL_H
+
+#include "kqemu.h"
+
+struct kqemu_state;
+
+#define CDECL __attribute__((regparm(0)))
+
+struct kqemu_state * CDECL kqemu_init(struct kqemu_init *d, int max_locked_pages);
+struct kqemu_cpu_state * CDECL kqemu_get_cpu_state(struct kqemu_state *s);
+long CDECL kqemu_exec(struct kqemu_state *s);
+void CDECL kqemu_delete(struct kqemu_state *s);
+
+/* callbacks */
+struct kqemu_page; /* opaque data for host page */
+struct kqemu_user_page; /* opaque data for host user page */
+
+struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
+                                                   unsigned long user_addr);
+void CDECL kqemu_unlock_user_page(struct kqemu_user_page *page);
+
+struct kqemu_page *CDECL kqemu_alloc_zeroed_page(unsigned long *ppage_index);
+void CDECL kqemu_free_page(struct kqemu_page *page);
+void * CDECL kqemu_page_kaddr(struct kqemu_page *page);
+
+void * CDECL kqemu_vmalloc(unsigned int size);
+void CDECL kqemu_vfree(void *ptr);
+unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr);
+
+void * CDECL kqemu_io_map(unsigned long page_index, unsigned int size);
+void CDECL kqemu_io_unmap(void *ptr, unsigned int size);
+
+int CDECL kqemu_schedule(void);
+
+void CDECL kqemu_log(const char *fmt, ...);
+
+#endif /* KQEMU_KERNEL_H */
index 0f18ec5..136aaa2 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "kqemu.h"
+#include "kqemu-kernel.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
 #error "Linux 2.4.19 or above needed"
@@ -50,6 +50,10 @@ int page_alloc_count;
 int major = 250;
 MODULE_PARM(major,"i");
 
+/* configurable max_instances */
+int max_instances = 4;
+MODULE_PARM(max_instances,"i");
+
 /* lock the page at virtual address 'user_addr' and return its
    page index. Return -1 if error */
 struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
@@ -183,8 +187,6 @@ void CDECL kqemu_log(const char *fmt, ...)
 
 /*********************************************************/
 
-#define KQEMU_MAX_INSTANCES 4
-
 static int kqemu_nb_instances = 0;
 static spinlock_t kqemu_lock = SPIN_LOCK_UNLOCKED;
 static int max_locked_pages;
@@ -199,7 +201,7 @@ static int kqemu_open(struct inode *inode, struct file *filp)
     struct kqemu_instance *ks;
     
     spin_lock(&kqemu_lock);
-    if (kqemu_nb_instances >= KQEMU_MAX_INSTANCES) {
+    if (kqemu_nb_instances >= max_instances) {
         spin_unlock(&kqemu_lock);
         return -ENOMEM;
     }
@@ -333,7 +335,7 @@ int init_module(void)
            (KQEMU_VERSION >> 8) & 0xff,
            (KQEMU_VERSION) & 0xff);
     si_meminfo(&si);
-    max_locked_pages = si.totalram / (2 * KQEMU_MAX_INSTANCES);
+    max_locked_pages = si.totalram / (2 * max_instances);
     if (max_locked_pages > 32768)
         max_locked_pages = 32768;
 
@@ -351,7 +353,7 @@ int init_module(void)
         }
     }
     printk("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
-           KQEMU_MAX_INSTANCES, 
+           max_instances, 
            max_locked_pages * 4);
     return 0;
 }
index 05a31a8..141bd8a 100644 (file)
Binary files a/kqemu/kqemu-mod-i386-win32.o and b/kqemu/kqemu-mod-i386-win32.o differ
index 6c97b76..52bbf10 100644 (file)
Binary files a/kqemu/kqemu-mod-i386.o and b/kqemu/kqemu-mod-i386.o differ
index 67df14e..9049540 100644 (file)
Binary files a/kqemu/kqemu-mod-x86_64.o and b/kqemu/kqemu-mod-x86_64.o differ
index d8c662e..7077848 100644 (file)
@@ -30,12 +30,19 @@ typedef unsigned int uint32_t;
 typedef unsigned long long uint64_t;
 
 #undef CDECL
-#define __KERNEL__
-#include "kqemu.h"
+#include "kqemu-kernel.h"
 
 /* XXX: make it dynamic according to available RAM */
 #define MAX_LOCKED_PAGES (16386 / 4)
 
+struct kqemu_instance {
+    struct kqemu_state *state;
+    PIRP current_irp;
+};
+
+FAST_MUTEX instance_lock;
+struct kqemu_instance *active_instance;
+
 /* lock the page at virtual address 'user_addr' and return its
    page index. Return -1 if error */
 struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
@@ -57,6 +64,7 @@ struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
     mdl_pages = (PPFN_NUMBER)(mdl + 1);
 
     MmInitializeMdl(mdl, user_addr, PAGE_SIZE);
+    /* XXX: Protect with SEH. */
     MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);
     *ppage_index = mdl_pages[0];
     return (struct kqemu_user_page *)mdl;
@@ -150,19 +158,19 @@ void CDECL kqemu_io_unmap(void *ptr, unsigned int size)
    execution) */
 int CDECL kqemu_schedule(void)
 {
-    /* XXX: do it */
-    return TRUE;
+    return active_instance->current_irp->Cancel;
 }
 
 void CDECL kqemu_log(const char *fmt, ...)
 {
-    /* XXX: format parameters */
-    DbgPrint("%s", fmt);
-}
+    char log_buf[1024];
+    va_list ap;
 
-struct kqemu_instance {
-    struct kqemu_state *state;
-};
+    va_start(ap, fmt);
+    _vsnprintf(log_buf, sizeof(log_buf), fmt, ap);
+    DbgPrint("kqemu: %s", log_buf);
+    va_end(ap);
+}
 
 NTSTATUS STDCALL
 KQemuCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
@@ -256,12 +264,19 @@ KQemuDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
                     break;
                 }
                 
+                ExAcquireFastMutex(&instance_lock);
+                active_instance = State;
+                State->current_irp = Irp;
+
                 ctx = kqemu_get_cpu_state(State->state);
                 
                 RtlCopyMemory(ctx, Irp->AssociatedIrp.SystemBuffer, 
                               sizeof(*ctx));
                 ret = kqemu_exec(State->state);
                 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, ctx, sizeof(*ctx));
+
+                ExReleaseFastMutex(&instance_lock);
+                
                 Irp->IoStatus.Information = sizeof(*ctx);
                 Status = STATUS_SUCCESS;
             }
@@ -294,6 +309,10 @@ KQemuDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 VOID STDCALL
 KQemuUnload(PDRIVER_OBJECT DriverObject)
 {
+    UNICODE_STRING SymlinkName;
+
+    RtlInitUnicodeString(&SymlinkName, L"\\??\\kqemu");
+    IoDeleteSymbolicLink(&SymlinkName);
     IoDeleteDevice(DriverObject->DeviceObject);
 }
 
@@ -312,6 +331,8 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
 
     MmLockPagableCodeSection(DriverEntry);
 
+    ExInitializeFastMutex(&instance_lock);
+
     DriverObject->MajorFunction[IRP_MJ_CREATE] = KQemuCreate;
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = KQemuClose;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KQemuDeviceControl;
@@ -324,10 +345,17 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
                             &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE,
                             &DeviceObject);
     if (!NT_SUCCESS(Status))
+    {
         return Status;
+    }
 
     /* Create the dos device link */
-    IoCreateSymbolicLink(&SymlinkName, &DeviceName);
+    Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
+    if (!NT_SUCCESS(Status))
+    {
+        IoDeleteDevice(DeviceObject);
+        return Status;
+    }
 
     return STATUS_SUCCESS;
 }
index f92933b..2355e7a 100644 (file)
@@ -1,7 +1,30 @@
+/*
+ * KQEMU header
+ * 
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
 #ifndef KQEMU_H
 #define KQEMU_H
 
-#define KQEMU_VERSION 0x010100
+#define KQEMU_VERSION 0x010200
 
 struct kqemu_segment_cache {
     uint32_t selector;
@@ -43,7 +66,8 @@ struct kqemu_cpu_state {
     unsigned long dr6;
     unsigned long dr7;
 
-    int cpl; /* currently only 3 */
+    uint8_t cpl;
+    uint8_t user_only;
 
     uint32_t error_code; /* error_code when exiting with an exception */
     unsigned long next_eip; /* next eip value when exiting with an interrupt */
@@ -53,6 +77,11 @@ struct kqemu_cpu_state {
 #define KQEMU_FLUSH_ALL (KQEMU_MAX_PAGES_TO_FLUSH + 1)
 
     long retval;
+
+    /* number of ram_dirty entries to update */
+    unsigned int nb_ram_pages_to_update; 
+#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
+#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
 };
 
 struct kqemu_init {
@@ -61,6 +90,7 @@ struct kqemu_init {
     uint8_t *ram_dirty; /* must be page aligned */
     uint32_t **phys_to_ram_map; /* must be page aligned */
     unsigned long *pages_to_flush; /* must be page aligned */
+    unsigned long *ram_pages_to_update; /* must be page aligned */
 };
 
 #define KQEMU_RET_ABORT    (-1)
@@ -81,39 +111,4 @@ struct kqemu_init {
 #define KQEMU_GET_VERSION    _IOR('q', 3, int)
 #endif
 
-#ifdef __KERNEL__
-struct kqemu_state;
-
-#define CDECL __attribute__((regparm(0)))
-
-struct kqemu_state * CDECL kqemu_init(struct kqemu_init *d, int max_locked_pages);
-struct kqemu_cpu_state * CDECL kqemu_get_cpu_state(struct kqemu_state *s);
-long CDECL kqemu_exec(struct kqemu_state *s);
-void CDECL kqemu_delete(struct kqemu_state *s);
-
-/* callbacks */
-struct kqemu_page; /* opaque data for host page */
-struct kqemu_user_page; /* opaque data for host user page */
-
-struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
-                                                   unsigned long user_addr);
-void CDECL kqemu_unlock_user_page(struct kqemu_user_page *page);
-
-struct kqemu_page *CDECL kqemu_alloc_zeroed_page(unsigned long *ppage_index);
-void CDECL kqemu_free_page(struct kqemu_page *page);
-void * CDECL kqemu_page_kaddr(struct kqemu_page *page);
-
-void * CDECL kqemu_vmalloc(unsigned int size);
-void CDECL kqemu_vfree(void *ptr);
-unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr);
-
-void * CDECL kqemu_io_map(unsigned long page_index, unsigned int size);
-void CDECL kqemu_io_unmap(void *ptr, unsigned int size);
-
-int CDECL kqemu_schedule(void);
-
-void CDECL kqemu_log(const char *fmt, ...);
-
-#endif
-
 #endif /* KQEMU_H */
diff --git a/kqemu/kqemu.inf b/kqemu/kqemu.inf
new file mode 100644 (file)
index 0000000..906e434
--- /dev/null
@@ -0,0 +1,64 @@
+; Copyright (C) 2005 Filip Navara, Damien Mascord
+
+[Version]
+Signature   = "$Windows NT$"
+Class       = System
+ClassGuid   = {4D36E97D-E325-11CE-BFC1-08002BE10318}
+Provider    = %Author%
+DriverVer   = 04/28/2005,1.0
+
+[DestinationDirs]
+DefaultDestDir    = 12
+KQemu.DriverFiles = 12
+KQemu.InfFiles    = 10,inf
+
+[SourceDisksNames]
+1 = %InstDisk%
+   
+[SourceDisksFiles]
+kqemu.sys = 1
+
+[Manufacturer]
+%Author% = KQemu.Manufacturer
+
+[KQemu.Manufacturer]
+%Description% = DefaultInstall,kqemu
+
+[DefaultInstall.NT]
+CopyFiles = KQemu.DriverFiles, KQemu.InfFiles
+AddReg = KQemu.UninstallRegistry
+
+[DefaultInstall.NT.Services]
+AddService = kqemu,,KQemuService_Inst
+
+[Uninstall.NT]
+DelFiles = KQemu.DriverFiles, KQemu.InfFiles
+DelReg = KQemu.UninstallRegistry
+
+[Uninstall.NT.Services]
+DelService = kqemu,0x00000200
+
+[KQemu.DriverFiles]
+kqemu.sys
+
+[KQemu.InfFiles]
+kqemu.inf
+
+[KQemu.UninstallRegistry]
+HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\KQEMU,"DisplayName",,%Description%
+HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\KQEMU,"UninstallString",0x20000,"RunDll32 setupapi.dll,InstallHinfSection Uninstall 132 %SystemRoot%\inf\kqemu.inf"
+
+[KQemuService_Inst]
+DisplayName   = %Description%
+ServiceType   = %SERVICE_KERNEL_DRIVER%
+StartType     = %SERVICE_DEMAND_START%
+ErrorControl  = %SERVICE_ERROR_NORMAL%
+ServiceBinary = %12%\kqemu.sys
+
+[Strings]
+Author = "Fabrice Bellard"
+Description = "KQEMU virtualisation module for QEMU"
+InstDisk = "KQEMU Install Disk"
+SERVICE_KERNEL_DRIVER = 1
+SERVICE_DEMAND_START = 3
+SERVICE_ERROR_NORMAL = 1
diff --git a/kqemu/kqemu.reg b/kqemu/kqemu.reg
deleted file mode 100644 (file)
index 73c05ab..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-REGEDIT4\r
-\r
-[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\kqemu]\r
-"Type"=dword:00000001\r
-"Start"=dword:00000003\r
-"ErrorControl"=dword:00000001\r
-"DisplayName"="kqemu"\r
index d33177c..afb0916 100755 (executable)
Binary files a/kqemu/kqemu.sys and b/kqemu/kqemu.sys differ
diff --git a/qemu-0.7.2-gtk.patch b/qemu-0.7.2-gtk.patch
new file mode 100644 (file)
index 0000000..8c2de78
--- /dev/null
@@ -0,0 +1,259 @@
+diff -Naur qemu-0.7.2/configure qemu-0.7.2-gtk/configure
+--- qemu-0.7.2/configure       2005-09-20 11:35:05 +0400
++++ qemu-0.7.2-gtk/configure   2005-09-20 11:34:49 +0400
+@@ -15,6 +15,7 @@
+ TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
+ TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
+ TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
++TMPF="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}-conf"
+ # default parameters
+ prefix=""
+@@ -171,6 +172,10 @@
+   ;;
+   --disable-sdl) sdl="no"
+   ;;
++  --enable-gtk) gtk="yes"
++  ;;
++  --set-fs-driver=*) fsdrv=`echo $opt | cut -d '=' -f 2`
++  ;;
+   --enable-fmod) fmod="yes"
+   ;;
+   --fmod-lib=*) fmod_lib=${opt#--fmod-lib=}
+@@ -319,6 +324,64 @@
+ fi # cross compilation
+ fi # -z $sdl
++##########################################
++# GTK probe
++
++gtk_too_old=no
++
++if test -z "$gtk" ; then
++
++gtk=no
++
++# normal GTK probe
++cat > $TMPC << EOF
++#include <stdlib.h>
++#include <gtk/gtk.h>
++int main(int argc, char **argv) { gtk_init(&argc, &argv); return EXIT_SUCCESS; }
++EOF
++
++if $cc -o $TMPE `pkg-config --cflags --libs gtk+-2.0 2> /dev/null` $TMPC 2> /dev/null ; then
++_gtkversion=`pkg-config --modversion gtk+-2.0 | sed 's/[^0-9]//g'`
++if test "$_sdlversion" -lt 240 ; then
++  gtk_too_old=yes
++else
++  gtk=yes
++
++fi
++
++fi # gtk compile test
++
++fi # -z $gtk
++
++if [ "$gtk" = "yes" ]; then
++
++if [ "$fsdrv" = "" ] ; then
++
++if [ "$bsd" = "yes" -o "$linux" = "yes" ]; then
++  fsdrv=xvid_fs.c
++else
++  fsdrv=null_fs.c
++fi
++
++fi # fsdrv test
++
++if [ "$fsdrv" = "xvid_fs.c" -o "$fsdrv" = "null_fs.c" ]; then
++  echo "fsdrv=$fsdrv" >> $TMPF
++else
++  echo "Warning: unknown gtk fullscreen driver: $fsdrv - using null driver"
++  echo 'fsdrv=null_fs.c' >> $TMPF
++  fsdrv=null_fs.c
++fi
++
++if [ "$fsdrv" = "xvid_fs.c" ]; then
++  FS_LIBS="-lX11 -lXxf86vm -lXext"
++  [ "$cpu" = "x86_64" ] && lib=lib64
++  FS_LIBS="$FS_LIBS -L/usr/X11R6/${lib:-lib}"
++  echo FS_LIBS=\"$FS_LIBS\" >> $TMPF
++fi
++
++fi # gtk=yes test
++
+ if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
+ cat << EOF
+@@ -408,6 +471,8 @@
+ if test "$sdl" != "no" ; then
+     echo "SDL static link   $sdl_static"
+ fi
++echo "GTK support       $gtk"
++echo "GTK FS driver     $fsdrv"
+ echo "mingw32 support   $mingw32"
+ echo "Adlib support     $adlib"
+ echo -n "FMOD support      $fmod"
+@@ -624,6 +689,8 @@
+ interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
+ echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
++. $TMPF
++
+ if test "$target_cpu" = "i386" ; then
+   echo "TARGET_ARCH=i386" >> $config_mak
+   echo "#define TARGET_ARCH \"i386\"" >> $config_h
+@@ -710,6 +777,17 @@
+     fi
+ fi
++if test "$gtk" = "yes" ; then
++    . $TMPF
++    echo "#define CONFIG_GTK 1" >> $config_h
++    echo "CONFIG_GTK=yes" >> $config_mak
++    echo "GTK_LIBS=`pkg-config --libs gtk+-2.0`" >> $config_mak
++    echo "GTK_CFLAGS=`pkg-config --cflags gtk+-2.0`" >> $config_mak
++    echo "FSDRV=$fsdrv" >> $config_mak
++    echo "FS_LIBS=$FS_LIBS" >> $config_mak
++    echo "" >> $config_mak
++fi
++
+ if test "$cocoa" = "yes" ; then
+     echo "#define CONFIG_COCOA 1" >> $config_h
+     echo "CONFIG_COCOA=yes" >> $config_mak
+@@ -729,4 +807,4 @@
+     done
+ fi
+-rm -f $TMPO $TMPC $TMPE $TMPS
++rm -f $TMPO $TMPC $TMPE $TMPS $TMPF
+diff -Naur qemu-0.7.2/Makefile.target qemu-0.7.2-gtk/Makefile.target
+--- qemu-0.7.2/Makefile.target 2005-09-20 11:35:05 +0400
++++ qemu-0.7.2-gtk/Makefile.target     2005-09-20 11:34:49 +0400
+@@ -314,6 +314,13 @@
+ ifdef CONFIG_SDL
+ VL_OBJS+=sdl.o
+ endif
++ifdef CONFIG_GTK
++VL_OBJS+=gtk2.o
++VL_OBJS+=callbacks.o
++VL_OBJS+=interface.o
++VL_OBJS+=support.o
++VL_OBJS+=fullscreen.o
++endif
+ ifdef CONFIG_COCOA
+ VL_OBJS+=cocoa.o
+ COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
+@@ -350,7 +357,7 @@
+ endif
+ $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+-      $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
++      $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(GTK_LIBS) $(FS_LIBS) $(VL_LIBS)
+ cocoa.o: cocoa.m
+       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+@@ -358,6 +365,21 @@
+ sdl.o: sdl.c keymaps.c sdl_keysym.h
+       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
++gtk2.o: gtk2gui.c keymaps.c gdk_keysym.h fullscreen.h interface.h callbacks.h support.h
++      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
++
++callbacks.o: callbacks.c callbacks.h interface.h support.h
++      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
++
++support.o: support.c callbacks.h interface.h support.h
++      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
++
++interface.o: interface.c callbacks.h interface.h support.h
++      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
++
++fullscreen.o: $(FSDRV) fullscreen.h
++      $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
++
+ sdlaudio.o: sdlaudio.c
+       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+diff -Naur qemu-0.7.2/vl.c qemu-0.7.2-gtk/vl.c
+--- qemu-0.7.2/vl.c    2005-09-04 21:11:31 +0400
++++ qemu-0.7.2-gtk/vl.c        2005-09-20 11:34:49 +0400
+@@ -147,10 +147,13 @@
+ TextConsole *vga_console;
+ CharDriverState *serial_hds[MAX_SERIAL_PORTS];
+ CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
++int use_gtk = 0;
+ #ifdef TARGET_I386
+ int win2k_install_hack = 0;
+ #endif
++void gui_checkargs(int *, char ***);
++
+ /***********************************************************/
+ /* x86 ISA bus support */
+@@ -2966,6 +2969,7 @@
+     QEMU_OPTION_cirrusvga,
+     QEMU_OPTION_g,
+     QEMU_OPTION_std_vga,
++    QEMU_OPTION_use_gtk,
+     QEMU_OPTION_monitor,
+     QEMU_OPTION_serial,
+     QEMU_OPTION_parallel,
+@@ -3037,6 +3041,7 @@
+     { "localtime", 0, QEMU_OPTION_localtime },
+     { "isa", 0, QEMU_OPTION_isa },
+     { "std-vga", 0, QEMU_OPTION_std_vga },
++    { "use-gtk", 0, QEMU_OPTION_use_gtk },
+     { "monitor", 1, QEMU_OPTION_monitor },
+     { "serial", 1, QEMU_OPTION_serial },
+     { "parallel", 1, QEMU_OPTION_parallel },
+@@ -3471,6 +3476,9 @@
+             case QEMU_OPTION_std_vga:
+                 cirrus_vga_enabled = 0;
+                 break;
++            case QEMU_OPTION_use_gtk:
++                use_gtk = 1;
++                break;
+             case QEMU_OPTION_g:
+                 {
+                     const char *p;
+@@ -3565,6 +3573,7 @@
+             boot_device = 'd';
+     }
++    gui_checkargs(&argc, &argv);
+ #if !defined(CONFIG_SOFTMMU)
+     /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
+     {
+@@ -3727,7 +3736,17 @@
+     if (nographic) {
+         dumb_display_init(ds);
+     } else {
++#if defined(CONFIG_GTK)
+ #if defined(CONFIG_SDL)
++      /* so we can choose */
++      if (use_gtk)
++        gtk2_display_init(ds, full_screen);
++      else
++        sdl_display_init(ds, full_screen);
++#else
++        gtk2_display_init(ds, full_screen);
++#endif
++#elif defined(CONFIG_SDL)
+         sdl_display_init(ds, full_screen);
+ #elif defined(CONFIG_COCOA)
+         cocoa_display_init(ds, full_screen);
+diff -Naur qemu-0.7.2/vl.h qemu-0.7.2-gtk/vl.h
+--- qemu-0.7.2/vl.h    2005-09-04 21:11:31 +0400
++++ qemu-0.7.2-gtk/vl.h        2005-09-20 11:34:49 +0400
+@@ -612,6 +612,9 @@
+ /* sdl.c */
+ void sdl_display_init(DisplayState *ds, int full_screen);
++/* gtk2.c */
++void gtk2_display_init(DisplayState *ds, int full_screen);
++
+ /* cocoa.m */
+ void cocoa_display_init(DisplayState *ds, int full_screen);
diff --git a/qemu-gtk/qemu-gtk-patch.diff b/qemu-gtk/qemu-gtk-patch.diff
deleted file mode 100644 (file)
index e30e9bb..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-diff -u qemu.orig/Makefile.target qemu/Makefile.target
---- qemu.orig/Makefile.target  Sat Jul 16 18:00:05 2005
-+++ qemu/Makefile.target       Sat Jul 16 17:58:18 2005
-@@ -361,6 +361,13 @@
- ifdef CONFIG_SDL
- VL_OBJS+=sdl.o
- endif
-+ifdef CONFIG_GTK
-+VL_OBJS+=gtk2.o
-+VL_OBJS+=callbacks.o
-+VL_OBJS+=interface.o
-+VL_OBJS+=support.o
-+VL_OBJS+=fullscreen.o
-+endif
- ifdef CONFIG_COCOA
- VL_OBJS+=cocoa.o
- COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
-@@ -396,13 +403,28 @@
- endif
- $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
--      $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
-+      $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(GTK_LIBS) $(FS_LIBS) $(VL_LIBS)
- cocoa.o: cocoa.m
-       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
- sdl.o: sdl.c keymaps.c sdl_keysym.h
-       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
-+
-+gtk2.o: gtk2gui.c keymaps.c gdk_keysym.h fullscreen.h interface.h callbacks.h support.h
-+      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
-+
-+callbacks.o: callbacks.c callbacks.h interface.h support.h
-+      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
-+
-+support.o: support.c callbacks.h interface.h support.h
-+      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
-+
-+interface.o: interface.c callbacks.h interface.h support.h
-+      $(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
-+
-+fullscreen.o: $(FSDRV) fullscreen.h
-+      $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
- sdlaudio.o: sdlaudio.c
-       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
-diff -u qemu.orig/configure qemu/configure
---- qemu.orig/configure        Mon May 30 19:40:14 2005
-+++ qemu/configure     Mon May 30 20:10:11 2005
-@@ -15,6 +15,7 @@
- TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
- TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
- TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
-+TMPF="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}-conf"
- # default parameters
- prefix=""
-@@ -171,6 +172,10 @@
-   ;;
-   --disable-sdl) sdl="no"
-   ;;
-+  --enable-gtk) gtk="yes"
-+  ;;
-+  --set-fs-driver=*) fsdrv=`echo $opt | cut -d '=' -f 2`
-+  ;;
-   --enable-fmod) fmod="yes"
-   ;;
-   --fmod-lib=*) fmod_lib=${opt#--fmod-lib=}
-@@ -311,6 +316,64 @@
- fi # cross compilation
- fi # -z $sdl
-+##########################################
-+# GTK probe
-+
-+gtk_too_old=no
-+
-+if test -z "$gtk" ; then
-+
-+gtk=no
-+
-+# normal GTK probe
-+cat > $TMPC << EOF
-+#include <stdlib.h>
-+#include <gtk/gtk.h>
-+int main(int argc, char **argv) { gtk_init(&argc, &argv); return EXIT_SUCCESS; }
-+EOF
-+
-+if $cc -o $TMPE `pkg-config --cflags --libs gtk+-2.0 2> /dev/null` $TMPC 2> /dev/null ; then
-+_gtkversion=`pkg-config --modversion gtk+-2.0 | sed 's/[^0-9]//g'`
-+if test "$_sdlversion" -lt 240 ; then
-+  gtk_too_old=yes
-+else
-+  gtk=yes
-+
-+fi
-+
-+fi # gtk compile test
-+
-+fi # -z $gtk
-+
-+if [ "$gtk" = "yes" ]; then
-+
-+if [ "$fsdrv" = "" ] ; then
-+
-+if [ "$bsd" = "yes" -o "$linux" = "yes" ]; then
-+  fsdrv=xvid_fs.c
-+else
-+  fsdrv=null_fs.c
-+fi
-+
-+fi # fsdrv test
-+
-+if [ "$fsdrv" = "xvid_fs.c" -o "$fsdrv" = "null_fs.c" ]; then
-+  echo "fsdrv=$fsdrv" >> $TMPF
-+else
-+  echo "Warning: unknown gtk fullscreen driver: $fsdrv - using null driver"
-+  echo 'fsdrv=null_fs.c' >> $TMPF
-+  fsdrv=null_fs.c
-+fi
-+
-+if [ "$fsdrv" = "xvid_fs.c" ]; then
-+  FS_LIBS="-lX11 -lXxf86vm -lXext"
-+  [ "$cpu" = "x86_64" ] && lib=lib64
-+  FS_LIBS="$FS_LIBS -L/usr/X11R6/${lib:-lib}"
-+  echo FS_LIBS=\"$FS_LIBS\" >> $TMPF
-+fi
-+
-+fi # gtk=yes test
-+
- if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
- cat << EOF
-@@ -434,6 +495,8 @@
- if test "$sdl" != "no" ; then
-     echo "SDL static link   $sdl_static"
- fi
-+echo "GTK support       $gtk"
-+echo "GTK FS driver     $fsdrv"
- echo "mingw32 support   $mingw32"
- echo "Adlib support     $adlib"
- echo -n "FMOD support      $fmod"
-@@ -643,6 +706,8 @@
- interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
- echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
-+. $TMPF
-+
- if test "$target_cpu" = "i386" ; then
-   echo "TARGET_ARCH=i386" >> $config_mak
-   echo "#define TARGET_ARCH \"i386\"" >> $config_h
-@@ -720,6 +785,17 @@
-     fi
- fi
-+if test "$gtk" = "yes" ; then
-+    . $TMPF
-+    echo "#define CONFIG_GTK 1" >> $config_h
-+    echo "CONFIG_GTK=yes" >> $config_mak
-+    echo "GTK_LIBS=`pkg-config --libs gtk+-2.0`" >> $config_mak
-+    echo "GTK_CFLAGS=`pkg-config --cflags gtk+-2.0`" >> $config_mak
-+    echo "FSDRV=$fsdrv" >> $config_mak
-+    echo "FS_LIBS=$FS_LIBS" >> $config_mak
-+    echo "" >> $config_mak
-+fi
-+
- if test "$cocoa" = "yes" ; then
-     echo "#define CONFIG_COCOA 1" >> $config_h
-     echo "CONFIG_COCOA=yes" >> $config_mak
-@@ -739,4 +815,4 @@
-     done
- fi
--rm -f $TMPO $TMPC $TMPE $TMPS
-+rm -f $TMPO $TMPC $TMPE $TMPS $TMPF
-diff -u qemu.orig/vl.h qemu/vl.h
---- qemu.orig/vl.h     Mon May 30 19:40:14 2005
-+++ qemu/vl.h  Sat May 28 16:16:18 2005
-@@ -579,6 +579,9 @@
- /* sdl.c */
- void sdl_display_init(DisplayState *ds, int full_screen);
-+/* gtk2.c */
-+void gtk2_display_init(DisplayState *ds, int full_screen);
-+
- /* cocoa.m */
- void cocoa_display_init(DisplayState *ds, int full_screen);
-diff -u qemu.orig/vl.c qemu/vl.c
---- qemu.orig/vl.c     Tue May 31 14:53:22 2005
-+++ qemu/vl.c  Tue May 31 14:52:55 2005
-@@ -147,10 +147,13 @@
- TextConsole *vga_console;
- CharDriverState *serial_hds[MAX_SERIAL_PORTS];
- CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
-+int use_gtk = 0;
- #ifdef TARGET_I386
- int win2k_install_hack = 0;
- #endif
-+void gui_checkargs(int *, char ***);
-+
- /***********************************************************/
- /* x86 ISA bus support */
-@@ -2877,6 +2878,7 @@
-     QEMU_OPTION_cirrusvga,
-     QEMU_OPTION_g,
-     QEMU_OPTION_std_vga,
-+    QEMU_OPTION_use_gtk,
-     QEMU_OPTION_monitor,
-     QEMU_OPTION_serial,
-     QEMU_OPTION_parallel,
-@@ -2947,6 +2949,7 @@
-     { "localtime", 0, QEMU_OPTION_localtime },
-     { "isa", 0, QEMU_OPTION_isa },
-     { "std-vga", 0, QEMU_OPTION_std_vga },
-+    { "use-gtk", 0, QEMU_OPTION_use_gtk },
-     { "monitor", 1, QEMU_OPTION_monitor },
-     { "serial", 1, QEMU_OPTION_serial },
-     { "parallel", 1, QEMU_OPTION_parallel },
-@@ -3345,6 +3348,9 @@
-             case QEMU_OPTION_std_vga:
-                 cirrus_vga_enabled = 0;
-                 break;
-+            case QEMU_OPTION_use_gtk:
-+                use_gtk = 1;
-+                break;
-             case QEMU_OPTION_g:
-                 {
-                     const char *p;
-@@ -3090,6 +3092,7 @@
-     const char *loadvm = NULL;
-     QEMUMachine *machine;
-+    gui_checkargs(&argc, &argv);
- #if !defined(CONFIG_SOFTMMU)
-     /* we never want that malloc() uses mmap() */
-     mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
-@@ -3599,7 +3605,17 @@
-     if (nographic) {
-         dumb_display_init(ds);
-     } else {
-+#if defined(CONFIG_GTK)
- #if defined(CONFIG_SDL)
-+      /* so we can choose */
-+      if (use_gtk)
-+        gtk2_display_init(ds, full_screen);
-+      else
-+        sdl_display_init(ds, full_screen);
-+#else
-+        gtk2_display_init(ds, full_screen);
-+#endif
-+#elif defined(CONFIG_SDL)
-         sdl_display_init(ds, full_screen);
- #elif defined(CONFIG_COCOA)
-         cocoa_display_init(ds, full_screen);
index e95889d..8d9d296 100644 (file)
--- a/qemu.spec
+++ b/qemu.spec
@@ -1,9 +1,9 @@
 %define kmodule_name   kqemu
-%define kqemuver       0.7.1.1
+%define kqemuver       0.7.2
 %define gtkver         20050716
 
 Name: qemu
-Version: 0.7.1
+Version: 0.7.2
 Release: alt1
 
 Summary: QEMU CPU Emulator
@@ -12,21 +12,24 @@ Group: Emulators
 
 URL: http://fabrice.bellard.free.fr/qemu/
 Source: %name-%version.tar.bz2
-Source1: kqemu-%kqemuver.tar.bz2
+Source1: kqemu-%kqemuver.tar.gz
 Source2: kqemu-permission
 Source3: qemu-gtk-%gtkver.tar.bz2
 
 Patch: %name-0.7.1-alt-makefile.patch
 Patch1: %name-0.6.2-alt-hdtrans.patch
 Patch2: %name-0.7.0-alt-kqemu.patch
-Patch3: %name-0.7.1-alt-guiargs.patch
+Patch3: %name-0.7.2-gtk.patch
+Patch4: %name-0.7.1-alt-guiargs.patch
 
 # for %_bindir/qemu*
 %set_verify_elf_method textrel=relaxed
+# for proll.elf
+%add_strip_skiplist *%_datadir/*
 
-BuildRequires: libSDL-devel-static xorg-x11-devel-static
-BuildRequires: glibc-devel-static zlib-devel-static
-BuildRequires: libaudiofile-devel-static esound-devel-static libalsa-devel-static
+BuildRequires: libSDL-devel xorg-x11-devel
+BuildRequires: glibc-devel zlib-devel
+BuildRequires: libaudiofile-devel esound-devel libalsa-devel
 BuildRequires: tetex-core libgtk+2-devel
 
 %description
@@ -59,8 +62,8 @@ Group: Development/Kernel
 %patch -p1
 %patch1 -p1
 %patch2 -p0
-%__patch -p1 < qemu-gtk-patch.diff
 %patch3 -p1
+%patch4 -p1
 
 %__cp -a kqemu kernel-source-%kmodule_name-%kqemuver
 %__cp -a %SOURCE2 kernel-source-%kmodule_name-%kqemuver/PERMISSION
@@ -94,6 +97,10 @@ cd tests
 %_usrsrc/kernel/sources/*
 
 %changelog
+* Tue Sep 20 2005 Kachalov Anton <mouse@altlinux.ru> 0.7.2-alt1
+- 0.7.2
+- Updated Kqemu to 0.7.2
+
 * Thu Aug 04 2005 Kachalov Anton <mouse@altlinux.ru> 0.7.1-alt1
 - 0.7.1
 - Updated:
index dcd252c..3ba685b 100644 (file)
@@ -1,3 +1,10 @@
+version 0.7.2:
+  
+  - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
+  - merge self modifying code handling in dirty ram page mecanism.
+  - MIPS fixes (Ralf Baechle)
+  - better user net performances
+
 version 0.7.1:
 
   - read-only Virtual FAT support (Johannes Schindelin)
@@ -8,6 +15,7 @@ version 0.7.1:
   - initial MIPS support (Jocelyn mayer)
   - MIPS improvements (Ralf Baechle)
   - 64 bit fixes in user networking (initial patch by Gwenole Beauchesne)
+  - IOAPIC support (Filip Navara)
 
 version 0.7.0:
 
index 8736090..3320586 100644 (file)
@@ -84,6 +84,11 @@ test speed test2: all
 TAGS: 
        etags *.[ch] tests/*.[ch]
 
+cscope:
+       rm -f ./cscope.*
+       find . -name "*.[ch]" -print > ./cscope.files
+       cscope -b
+
 # documentation
 %.html: %.texi
        texi2html -monolithic -number $<
index 9a6b4d7..ea0f5c8 100644 (file)
@@ -295,8 +295,8 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8259.o
-#VL_OBJS+= #ide.o pckbd.o i8254.o fdc.o m48t59.o
+VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8254.o i8259.o
+#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
index 7deb86f..d5cc44d 100644 (file)
@@ -1 +1 @@
-0.7.1
\ No newline at end of file
+0.7.2
\ No newline at end of file
index b45408a..19a0ec9 100755 (executable)
@@ -99,7 +99,7 @@ mingw32="yes"
 FreeBSD)
 bsd="yes"
 oss="yes"
-if [ "$cpu" = "i386" ] ; then
+if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     kqemu="yes"
 fi
 ;;
index d50f5a2..4f1f772 100644 (file)
@@ -708,7 +708,6 @@ extern uint8_t *phys_ram_dirty;
 #define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
 #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
 #define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
-#define IO_MEM_CODE        (3 << IO_MEM_SHIFT) /* used internally, never use directly */
 #define IO_MEM_NOTDIRTY    (4 << IO_MEM_SHIFT) /* used internally, never use directly */
 
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
@@ -743,27 +742,29 @@ void stl_phys(target_phys_addr_t addr, uint32_t val);
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
                         uint8_t *buf, int len, int is_write);
 
-#define VGA_DIRTY_FLAG 0x01
+#define VGA_DIRTY_FLAG  0x01
+#define CODE_DIRTY_FLAG 0x02
 
 /* read dirty bit (return 0 or 1) */
-static inline int cpu_physical_memory_is_dirty(target_ulong addr)
+static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
     return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
 }
 
-static inline int cpu_physical_memory_get_dirty(target_ulong addr, 
+static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, 
                                                 int dirty_flags)
 {
     return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
 }
 
-static inline void cpu_physical_memory_set_dirty(target_ulong addr)
+static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
     phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
 }
 
-void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end,
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags);
+void cpu_tlb_update_dirty(CPUState *env);
 
 void dump_exec_info(FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
index 83d1748..912133e 100644 (file)
@@ -66,6 +66,9 @@ typedef uint64_t target_phys_addr_t;
 #error TARGET_PHYS_ADDR_BITS undefined
 #endif
 
+/* address in the RAM (different from a physical address) */
+typedef unsigned long ram_addr_t;
+
 #define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
 
 #define EXCP_INTERRUPT         0x10000 /* async interruption */
index e7f4322..bdfc865 100644 (file)
@@ -307,7 +307,7 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_MIPS)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->CP0_Status & (1 << CP0St_IE)) &&
-                        (env->CP0_Cause & 0x0000FF00) &&
+                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
                         !(env->hflags & MIPS_HFLAG_EXL) &&
                         !(env->hflags & MIPS_HFLAG_ERL) &&
                         !(env->hflags & MIPS_HFLAG_DM)) {
index 5e809b0..5db83d3 100644 (file)
@@ -320,13 +320,16 @@ TranslationBlock *tb_find_pc(unsigned long pc_ptr);
 #define ASM_PREVIOUS_SECTION ".previous\n"
 #endif
 
+#define ASM_OP_LABEL_NAME(n, opname) \
+    ASM_NAME(__op_label) #n "." ASM_NAME(opname)
+
 #if defined(__powerpc__)
 
 /* we patch the jump instruction directly */
 #define GOTO_TB(opname, tbparam, n)\
 do {\
     asm volatile (ASM_DATA_SECTION\
-                 ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
+                 ASM_OP_LABEL_NAME(n, opname) ":\n"\
                  ".long 1f\n"\
                  ASM_PREVIOUS_SECTION \
                   "b " ASM_NAME(__op_jmp) #n "\n"\
@@ -339,7 +342,7 @@ do {\
 #define GOTO_TB(opname, tbparam, n)\
 do {\
     asm volatile (".section .data\n"\
-                 ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
+                 ASM_OP_LABEL_NAME(n, opname) ":\n"\
                  ".long 1f\n"\
                  ASM_PREVIOUS_SECTION \
                   "jmp " ASM_NAME(__op_jmp) #n "\n"\
@@ -353,7 +356,8 @@ do {\
 #define GOTO_TB(opname, tbparam, n)\
 do {\
     static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
-    static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
+    static void __attribute__((unused)) *__op_label ## n \
+        __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
     goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
 label ## n: ;\
 dummy_label ## n: ;\
@@ -572,7 +576,6 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
 /* NOTE: this function can trigger an exception */
 /* NOTE2: the returned address is not exactly the physical address: it
    is the offset relative to phys_ram_base */
-/* XXX: i386 target specific */
 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
 {
     int is_user, index, pd;
@@ -607,6 +610,8 @@ int kqemu_init(CPUState *env);
 int kqemu_cpu_exec(CPUState *env);
 void kqemu_flush_page(CPUState *env, target_ulong addr);
 void kqemu_flush(CPUState *env, int global);
+void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
+void kqemu_cpu_interrupt(CPUState *env);
 
 static inline int kqemu_is_ok(CPUState *env)
 {
@@ -615,8 +620,7 @@ static inline int kqemu_is_ok(CPUState *env)
            (env->eflags & IOPL_MASK) != IOPL_MASK &&
            (env->cr[0] & CR0_PE_MASK) && 
            (env->eflags & IF_MASK) &&
-           !(env->eflags & VM_MASK) &&
-           (env->ldt.limit == 0 || env->ldt.limit == 0x27));
+           !(env->eflags & VM_MASK));
 }
 
 #endif
index 26abb0f..11a3a64 100644 (file)
@@ -262,8 +262,10 @@ static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static void tlb_protect_code(CPUState *env, target_ulong addr);
-static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
+static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, 
+                             target_ulong vaddr);
+static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
+                                    target_ulong vaddr);
 
 static VirtPageDesc *virt_page_find_alloc(target_ulong index, int alloc)
 {
@@ -945,7 +947,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
     TranslationBlock *last_first_tb;
 
     tb->page_addr[n] = page_addr;
-    p = page_find(page_addr >> TARGET_PAGE_BITS);
+    p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
     tb->page_next[n] = p->first_tb;
     last_first_tb = p->first_tb;
     p->first_tb = (TranslationBlock *)((long)tb | n);
@@ -981,7 +983,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
         target_ulong virt_addr;
 
         virt_addr = (tb->pc & TARGET_PAGE_MASK) + (n << TARGET_PAGE_BITS);
-        tlb_protect_code(cpu_single_env, virt_addr);        
+        tlb_protect_code(cpu_single_env, page_addr, virt_addr);
     }
 #endif
 
@@ -1473,50 +1475,44 @@ static inline void tlb_protect_code1(CPUTLBEntry *tlb_entry, target_ulong addr)
 {
     if (addr == (tlb_entry->address & 
                  (TARGET_PAGE_MASK | TLB_INVALID_MASK)) &&
-        (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_CODE &&
-        (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
-        tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_CODE;
+        (tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
     }
 }
 
 /* update the TLBs so that writes to code in the virtual page 'addr'
    can be detected */
-static void tlb_protect_code(CPUState *env, target_ulong addr)
+static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, 
+                             target_ulong vaddr)
 {
     int i;
 
-    addr &= TARGET_PAGE_MASK;
-    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    tlb_protect_code1(&env->tlb_write[0][i], addr);
-    tlb_protect_code1(&env->tlb_write[1][i], addr);
+    vaddr &= TARGET_PAGE_MASK;
+    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    tlb_protect_code1(&env->tlb_write[0][i], vaddr);
+    tlb_protect_code1(&env->tlb_write[1][i], vaddr);
+
+#ifdef USE_KQEMU
+    if (env->kqemu_enabled) {
+        kqemu_set_notdirty(env, ram_addr);
+    }
+#endif
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG;
+    
 #if !defined(CONFIG_SOFTMMU)
     /* NOTE: as we generated the code for this page, it is already at
        least readable */
-    if (addr < MMAP_AREA_END)
-        mprotect((void *)addr, TARGET_PAGE_SIZE, PROT_READ);
+    if (vaddr < MMAP_AREA_END)
+        mprotect((void *)vaddr, TARGET_PAGE_SIZE, PROT_READ);
 #endif
 }
 
-static inline void tlb_unprotect_code2(CPUTLBEntry *tlb_entry, 
-                                       unsigned long phys_addr)
-{
-    if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE &&
-        ((tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend) == phys_addr) {
-        tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
-    }
-}
-
 /* update the TLB so that writes in physical page 'phys_addr' are no longer
-   tested self modifying code */
-static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr)
+   tested for self modifying code */
+static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
+                                    target_ulong vaddr)
 {
-    int i;
-
-    phys_addr &= TARGET_PAGE_MASK;
-    phys_addr += (long)phys_ram_base;
-    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    tlb_unprotect_code2(&env->tlb_write[0][i], phys_addr);
-    tlb_unprotect_code2(&env->tlb_write[1][i], phys_addr);
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
 }
 
 static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, 
@@ -1531,7 +1527,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
     }
 }
 
-void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end,
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags)
 {
     CPUState *env;
@@ -1545,13 +1541,23 @@ void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end,
     length = end - start;
     if (length == 0)
         return;
+    len = length >> TARGET_PAGE_BITS;
+    env = cpu_single_env;
+#ifdef USE_KQEMU
+    if (env->kqemu_enabled) {
+        ram_addr_t addr;
+        addr = start;
+        for(i = 0; i < len; i++) {
+            kqemu_set_notdirty(env, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
+    }
+#endif
     mask = ~dirty_flags;
     p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
-    len = length >> TARGET_PAGE_BITS;
     for(i = 0; i < len; i++)
         p[i] &= mask;
 
-    env = cpu_single_env;
     /* we modify the TLB cache so that the dirty bit will be set again
        when accessing the range */
     start1 = start + (unsigned long)phys_ram_base;
@@ -1589,6 +1595,29 @@ void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end,
 #endif
 }
 
+static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
+{
+    ram_addr_t ram_addr;
+
+    if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        ram_addr = (tlb_entry->address & TARGET_PAGE_MASK) + 
+            tlb_entry->addend - (unsigned long)phys_ram_base;
+        if (!cpu_physical_memory_is_dirty(ram_addr)) {
+            tlb_entry->address |= IO_MEM_NOTDIRTY;
+        }
+    }
+}
+
+/* update the TLB according to the current state of the dirty bits */
+void cpu_tlb_update_dirty(CPUState *env)
+{
+    int i;
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_write[0][i]);
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_write[1][i]);
+}
+
 static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
                                   unsigned long start)
 {
@@ -1608,8 +1637,6 @@ static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
     CPUState *env = cpu_single_env;
     int i;
 
-    phys_ram_dirty[(addr - (unsigned long)phys_ram_base) >> TARGET_PAGE_BITS] = 0xff;
-
     addr &= TARGET_PAGE_MASK;
     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_set_dirty1(&env->tlb_write[0][i], addr);
@@ -1626,28 +1653,20 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
 {
     PhysPageDesc *p;
     unsigned long pd;
-    TranslationBlock *first_tb;
     unsigned int index;
     target_ulong address;
     target_phys_addr_t addend;
     int ret;
 
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
-    first_tb = NULL;
     if (!p) {
         pd = IO_MEM_UNASSIGNED;
     } else {
-        PageDesc *p1;
         pd = p->phys_offset;
-        if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
-            /* NOTE: we also allocate the page at this stage */
-            p1 = page_find_alloc(pd >> TARGET_PAGE_BITS);
-            first_tb = p1->first_tb;
-        }
     }
 #if defined(DEBUG_TLB)
-    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d c=%d smmu=%d pd=0x%08x\n",
-           vaddr, paddr, prot, is_user, (first_tb != NULL), is_softmmu, pd);
+    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
+           vaddr, paddr, prot, is_user, is_softmmu, pd);
 #endif
 
     ret = 0;
@@ -1679,18 +1698,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
                 /* ROM: access is ignored (same as unassigned) */
                 env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
                 env->tlb_write[is_user][index].addend = addend;
-            } else 
-                /* XXX: the PowerPC code seems not ready to handle
-                   self modifying code with DCBI */
-#if defined(TARGET_HAS_SMC) || 1
-            if (first_tb) {
-                /* if code is present, we use a specific memory
-                   handler. It works only for physical memory access */
-                env->tlb_write[is_user][index].address = vaddr | IO_MEM_CODE;
-                env->tlb_write[is_user][index].addend = addend;
-            } else 
-#endif
-            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
+            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
                        !cpu_physical_memory_is_dirty(pd)) {
                 env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
                 env->tlb_write[is_user][index].addend = addend;
@@ -1986,75 +1994,75 @@ static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
     unassigned_mem_writeb,
 };
 
-/* self modifying code support in soft mmu mode : writing to a page
-   containing code comes to these functions */
-
-static void code_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    unsigned long phys_addr;
-
-    phys_addr = addr - (unsigned long)phys_ram_base;
+    unsigned long ram_addr;
+    int dirty_flags;
+    ram_addr = addr - (unsigned long)phys_ram_base;
+    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
+    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
 #if !defined(CONFIG_USER_ONLY)
-    tb_invalidate_phys_page_fast(phys_addr, 1);
+        tb_invalidate_phys_page_fast(ram_addr, 1);
+        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
 #endif
+    }
     stb_p((uint8_t *)(long)addr, val);
-    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 0xff;
+    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
+    /* we remove the notdirty callback only if the code has been
+       flushed */
+    if (dirty_flags == 0xff)
+        tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
-static void code_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    unsigned long phys_addr;
-
-    phys_addr = addr - (unsigned long)phys_ram_base;
+    unsigned long ram_addr;
+    int dirty_flags;
+    ram_addr = addr - (unsigned long)phys_ram_base;
+    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
+    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
 #if !defined(CONFIG_USER_ONLY)
-    tb_invalidate_phys_page_fast(phys_addr, 2);
+        tb_invalidate_phys_page_fast(ram_addr, 2);
+        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
 #endif
+    }
     stw_p((uint8_t *)(long)addr, val);
-    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 0xff;
+    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
+    /* we remove the notdirty callback only if the code has been
+       flushed */
+    if (dirty_flags == 0xff)
+        tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
-static void code_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    unsigned long phys_addr;
-
-    phys_addr = addr - (unsigned long)phys_ram_base;
+    unsigned long ram_addr;
+    int dirty_flags;
+    ram_addr = addr - (unsigned long)phys_ram_base;
+    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
+    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
 #if !defined(CONFIG_USER_ONLY)
-    tb_invalidate_phys_page_fast(phys_addr, 4);
+        tb_invalidate_phys_page_fast(ram_addr, 4);
+        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
 #endif
+    }
     stl_p((uint8_t *)(long)addr, val);
-    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 0xff;
+    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
+    /* we remove the notdirty callback only if the code has been
+       flushed */
+    if (dirty_flags == 0xff)
+        tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
-static CPUReadMemoryFunc *code_mem_read[3] = {
+static CPUReadMemoryFunc *error_mem_read[3] = {
     NULL, /* never used */
     NULL, /* never used */
     NULL, /* never used */
 };
 
-static CPUWriteMemoryFunc *code_mem_write[3] = {
-    code_mem_writeb,
-    code_mem_writew,
-    code_mem_writel,
-};
-
-static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    stb_p((uint8_t *)(long)addr, val);
-    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
-}
-
-static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    stw_p((uint8_t *)(long)addr, val);
-    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
-}
-
-static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    stl_p((uint8_t *)(long)addr, val);
-    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
-}
-
 static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
     notdirty_mem_writeb,
     notdirty_mem_writew,
@@ -2063,14 +2071,14 @@ static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
 
 static void io_mem_init(void)
 {
-    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write, NULL);
+    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
-    cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write, NULL);
-    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, code_mem_read, notdirty_mem_write, NULL);
+    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
     io_mem_nb = 5;
 
     /* alloc dirty bits array */
     phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
+    memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
 }
 
 /* mem_read and mem_write are arrays of functions containing the
@@ -2182,20 +2190,20 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         }
         
         if (is_write) {
-            if ((pd & ~TARGET_PAGE_MASK) != 0) {
+            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (l >= 4 && ((addr & 3) == 0)) {
-                    /* 32 bit read access */
+                    /* 32 bit write access */
                     val = ldl_p(buf);
                     io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
                     l = 4;
                 } else if (l >= 2 && ((addr & 1) == 0)) {
-                    /* 16 bit read access */
+                    /* 16 bit write access */
                     val = lduw_p(buf);
                     io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
                     l = 2;
                 } else {
-                    /* 8 bit access */
+                    /* 8 bit write access */
                     val = ldub_p(buf);
                     io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
                     l = 1;
@@ -2206,14 +2214,16 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 /* RAM case */
                 ptr = phys_ram_base + addr1;
                 memcpy(ptr, buf, l);
-                /* invalidate code */
-                tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
-                /* set dirty bit */
-                phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff;
+                if (!cpu_physical_memory_is_dirty(addr1)) {
+                    /* invalidate code */
+                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
+                    /* set dirty bit */
+                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= 
+                        (0xff & ~CODE_DIRTY_FLAG);
+                }
             }
         } else {
-            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-                (pd & ~TARGET_PAGE_MASK) != IO_MEM_CODE) {
+            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
                 /* I/O case */
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (l >= 4 && ((addr & 3) == 0)) {
@@ -2227,7 +2237,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     stw_p(buf, val);
                     l = 2;
                 } else {
-                    /* 8 bit access */
+                    /* 8 bit read access */
                     val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
                     stb_p(buf, val);
                     l = 1;
@@ -2261,8 +2271,7 @@ uint32_t ldl_phys(target_phys_addr_t addr)
         pd = p->phys_offset;
     }
         
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
-        (pd & ~TARGET_PAGE_MASK) != IO_MEM_CODE) {
+    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
@@ -2292,7 +2301,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
         pd = p->phys_offset;
     }
         
-    if ((pd & ~TARGET_PAGE_MASK) != 0) {
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
@@ -2303,7 +2312,6 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 }
 
 /* warning: addr must be aligned */
-/* XXX: optimize code invalidation test */
 void stl_phys(target_phys_addr_t addr, uint32_t val)
 {
     int io_index;
@@ -2318,7 +2326,7 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
         pd = p->phys_offset;
     }
         
-    if ((pd & ~TARGET_PAGE_MASK) != 0) {
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
@@ -2327,10 +2335,13 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
         /* RAM case */
         ptr = phys_ram_base + addr1;
         stl_p(ptr, val);
-        /* invalidate code */
-        tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
-        /* set dirty bit */
-        phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff;
+        if (!cpu_physical_memory_is_dirty(addr1)) {
+            /* invalidate code */
+            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
+            /* set dirty bit */
+            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
+                (0xff & ~CODE_DIRTY_FLAG);
+        }
     }
 }
 
index f5fd028..28ed5ab 100644 (file)
@@ -2330,6 +2330,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
     pci_conf[0x01] = 0x80;
     pci_conf[0x02] = 0x10;
     pci_conf[0x03] = 0x70;
+    pci_conf[0x09] = 0x80; // legacy ATA mode
     pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
index ca135ac..bf3376d 100644 (file)
@@ -7,6 +7,8 @@
 
 extern FILE *logfile;
 
+static PITState *pit;
+
 static void pic_irq_request(void *opaque, int level)
 {
     if (level) {
@@ -72,7 +74,8 @@ void cpu_mips_store_count (CPUState *env, uint32_t value)
 void cpu_mips_store_compare (CPUState *env, uint32_t value)
 {
     cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    pic_set_irq(5, 0);
+    cpu_single_env->CP0_Cause &= ~0x00008000;
+    cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
 }
 
 static void mips_timer_cb (void *opaque)
@@ -86,7 +89,8 @@ static void mips_timer_cb (void *opaque)
     }
 #endif
     cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
-    pic_set_irq(5, 1);
+    cpu_single_env->CP0_Cause |= 0x00008000;
+    cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
 }
 
 void cpu_mips_clock_init (CPUState *env)
@@ -240,6 +244,7 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
     isa_mem_base = 0x10000000;
 
     isa_pic = pic_init(pic_irq_request, cpu_single_env);
+    pit = pit_init(0x40, 0);
     serial_init(0x3f8, 4, serial_hds[0]);
     vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size, 
                    vga_ram_size, 0, 0);
index 33026fe..bca5795 100644 (file)
@@ -540,7 +540,7 @@ static void command (SB16State *s, uint8_t cmd)
     return;
 
  warn:
-    dolog ("warning: command %#x,%d is not trully understood yet\n",
+    dolog ("warning: command %#x,%d is not truly understood yet\n",
            cmd, s->needed_bytes);
     s->cmd = cmd;
     return;
index 4d15250..70cfe28 100644 (file)
@@ -40,6 +40,7 @@
 #ifdef USE_KQEMU
 
 #define DEBUG
+//#define PROFILE
 
 #include <unistd.h>
 #include <fcntl.h>
 #ifndef KQEMU_RET_SYSCALL
 #define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
 #endif
+#ifndef KQEMU_MAX_RAM_PAGES_TO_UPDATE
+#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
+#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
+#endif
 
 #ifdef _WIN32
 #define KQEMU_DEVICE "\\\\.\\kqemu"
@@ -69,6 +74,8 @@ int kqemu_fd = KQEMU_INVALID_FD;
 int kqemu_allowed = 1;
 unsigned long *pages_to_flush;
 unsigned int nb_pages_to_flush;
+unsigned long *ram_pages_to_update;
+unsigned int nb_ram_pages_to_update;
 extern uint32_t **l1_phys_map;
 
 #define cpuid(index, eax, ebx, ecx, edx) \
@@ -112,13 +119,19 @@ static void kqemu_update_cpuid(CPUState *env)
     critical_features_mask = 
         CPUID_CMOV | CPUID_CX8 | 
         CPUID_FXSR | CPUID_MMX | CPUID_SSE | 
-        CPUID_SSE2;
+        CPUID_SSE2 | CPUID_SEP;
     if (!is_cpuid_supported()) {
         features = 0;
     } else {
         cpuid(1, eax, ebx, ecx, edx);
         features = edx;
     }
+#ifdef __x86_64__
+    /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
+       compatibility mode, so in order to have the best performances
+       it is better not to use it */
+    features &= ~CPUID_SEP;
+#endif
     env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
         (features & critical_features_mask);
     /* XXX: we could update more of the target CPUID state so that the
@@ -167,11 +180,19 @@ int kqemu_init(CPUState *env)
     if (!pages_to_flush)
         goto fail;
 
+    ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE * 
+                                       sizeof(unsigned long));
+    if (!ram_pages_to_update)
+        goto fail;
+
     init.ram_base = phys_ram_base;
     init.ram_size = phys_ram_size;
     init.ram_dirty = phys_ram_dirty;
     init.phys_to_ram_map = l1_phys_map;
     init.pages_to_flush = pages_to_flush;
+#if KQEMU_VERSION >= 0x010200
+    init.ram_pages_to_update = ram_pages_to_update;
+#endif
 #ifdef _WIN32
     ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
                           NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
@@ -188,6 +209,7 @@ int kqemu_init(CPUState *env)
     kqemu_update_cpuid(env);
     env->kqemu_enabled = 1;
     nb_pages_to_flush = 0;
+    nb_ram_pages_to_update = 0;
     return 0;
 }
 
@@ -214,6 +236,22 @@ void kqemu_flush(CPUState *env, int global)
     nb_pages_to_flush = KQEMU_FLUSH_ALL;
 }
 
+void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
+{
+#ifdef DEBUG
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
+    }
+#endif
+    /* we only track transitions to dirty state */
+    if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
+        return;
+    if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
+        nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
+    else
+        ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
+}
+
 struct fpstate {
     uint16_t fpuc;
     uint16_t dummy1;
@@ -404,6 +442,103 @@ static int do_syscall(CPUState *env,
     return 2;
 }
 
+#ifdef PROFILE
+
+#define PC_REC_SIZE 1
+#define PC_REC_HASH_BITS 16
+#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
+
+typedef struct PCRecord {
+    unsigned long pc;
+    int64_t count;
+    struct PCRecord *next;
+} PCRecord;
+
+PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
+int nb_pc_records;
+
+void kqemu_record_pc(unsigned long pc)
+{
+    unsigned long h;
+    PCRecord **pr, *r;
+
+    h = pc / PC_REC_SIZE;
+    h = h ^ (h >> PC_REC_HASH_BITS);
+    h &= (PC_REC_HASH_SIZE - 1);
+    pr = &pc_rec_hash[h];
+    for(;;) {
+        r = *pr;
+        if (r == NULL)
+            break;
+        if (r->pc == pc) {
+            r->count++;
+            return;
+        }
+        pr = &r->next;
+    }
+    r = malloc(sizeof(PCRecord));
+    r->count = 1;
+    r->pc = pc;
+    r->next = NULL;
+    *pr = r;
+    nb_pc_records++;
+}
+
+int pc_rec_cmp(const void *p1, const void *p2)
+{
+    PCRecord *r1 = *(PCRecord **)p1;
+    PCRecord *r2 = *(PCRecord **)p2;
+    if (r1->count < r2->count)
+        return 1;
+    else if (r1->count == r2->count)
+        return 0;
+    else
+        return -1;
+}
+
+void kqemu_record_dump(void)
+{
+    PCRecord **pr, *r;
+    int i, h;
+    FILE *f;
+    int64_t total, sum;
+
+    pr = malloc(sizeof(PCRecord *) * nb_pc_records);
+    i = 0;
+    total = 0;
+    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
+        for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
+            pr[i++] = r;
+            total += r->count;
+        }
+    }
+    qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
+    
+    f = fopen("/tmp/kqemu.stats", "w");
+    if (!f) {
+        perror("/tmp/kqemu.stats");
+        exit(1);
+    }
+    fprintf(f, "total: %lld\n", total);
+    sum = 0;
+    for(i = 0; i < nb_pc_records; i++) {
+        r = pr[i];
+        sum += r->count;
+        fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n", 
+                r->pc, 
+                r->count, 
+                (double)r->count / (double)total * 100.0,
+                (double)sum / (double)total * 100.0);
+    }
+    fclose(f);
+    free(pr);
+}
+#else
+void kqemu_record_dump(void)
+{
+}
+#endif
+
 int kqemu_cpu_exec(CPUState *env)
 {
     struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
@@ -447,6 +582,11 @@ int kqemu_cpu_exec(CPUState *env)
     kenv->cpl = 3;
     kenv->nb_pages_to_flush = nb_pages_to_flush;
     nb_pages_to_flush = 0;
+#if KQEMU_VERSION >= 0x010200
+    kenv->user_only = 1;
+    kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
+#endif
+    nb_ram_pages_to_update = 0;
     
     if (!(kenv->cr0 & CR0_TS_MASK)) {
         if (env->cpuid_features & CPUID_FXSR)
@@ -456,11 +596,14 @@ int kqemu_cpu_exec(CPUState *env)
     }
 
 #ifdef _WIN32
-    DeviceIoControl(kqemu_fd, KQEMU_EXEC,
-                   kenv, sizeof(struct kqemu_cpu_state),
-                   kenv, sizeof(struct kqemu_cpu_state),
-                   &temp, NULL);
-    ret = kenv->retval;
+    if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
+                        kenv, sizeof(struct kqemu_cpu_state),
+                        kenv, sizeof(struct kqemu_cpu_state),
+                        &temp, NULL)) {
+        ret = kenv->retval;
+    } else {
+        ret = -1;
+    }
 #else
 #if KQEMU_VERSION >= 0x010100
     ioctl(kqemu_fd, KQEMU_EXEC, kenv);
@@ -494,6 +637,49 @@ int kqemu_cpu_exec(CPUState *env)
     env->cr[2] = kenv->cr2;
     env->dr[6] = kenv->dr6;
 
+#if KQEMU_VERSION >= 0x010200
+    if (kenv->nb_ram_pages_to_update > 0) {
+        cpu_tlb_update_dirty(env);
+    }
+#endif
+
+    /* restore the hidden flags */
+    {
+        unsigned int new_hflags;
+#ifdef TARGET_X86_64
+        if ((env->hflags & HF_LMA_MASK) && 
+            (env->segs[R_CS].flags & DESC_L_MASK)) {
+            /* long mode */
+            new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
+        } else
+#endif
+        {
+            /* legacy / compatibility case */
+            new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
+                >> (DESC_B_SHIFT - HF_CS32_SHIFT);
+            new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
+                >> (DESC_B_SHIFT - HF_SS32_SHIFT);
+            if (!(env->cr[0] & CR0_PE_MASK) || 
+                   (env->eflags & VM_MASK) ||
+                   !(env->hflags & HF_CS32_MASK)) {
+                /* XXX: try to avoid this test. The problem comes from the
+                   fact that is real mode or vm86 mode we only modify the
+                   'base' and 'selector' fields of the segment cache to go
+                   faster. A solution may be to force addseg to one in
+                   translate-i386.c. */
+                new_hflags |= HF_ADDSEG_MASK;
+            } else {
+                new_hflags |= ((env->segs[R_DS].base | 
+                                env->segs[R_ES].base |
+                                env->segs[R_SS].base) != 0) << 
+                    HF_ADDSEG_SHIFT;
+            }
+        }
+        env->hflags = (env->hflags & 
+           ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
+            new_hflags;
+    }
+
 #ifdef DEBUG
     if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
@@ -537,6 +723,14 @@ int kqemu_cpu_exec(CPUState *env)
 #endif
         return 0;
     } else if (ret == KQEMU_RET_SOFTMMU) { 
+#ifdef PROFILE
+        kqemu_record_pc(env->eip + env->segs[R_CS].base);
+#endif
+#ifdef DEBUG
+        if (loglevel & CPU_LOG_INT) {
+            cpu_dump_state(env, logfile, fprintf, 0);
+        }
+#endif
         return 2;
     } else {
         cpu_dump_state(env, stderr, fprintf, 0);
@@ -546,4 +740,13 @@ int kqemu_cpu_exec(CPUState *env)
     return 0;
 }
 
+void kqemu_cpu_interrupt(CPUState *env)
+{
+#if defined(_WIN32) && KQEMU_VERSION >= 0x010101
+    /* cancelling the I/O request causes KQEMU to finish executing the 
+       current block and successfully returning. */
+    CancelIo(kqemu_fd);
+#endif
+}
+
 #endif
index 6950daa..472361a 100644 (file)
@@ -178,7 +178,7 @@ uint32_t do_arm_semihosting(CPUState *env)
                 ts->heap_limit = limit;
             }
               
-            ptr = (uint32_t *)tswap32(ARG(0));
+            ptr = (uint32_t *)ARG(0);
             ptr[0] = tswap32(ts->heap_base);
             ptr[1] = tswap32(ts->heap_limit);
             ptr[2] = tswap32(ts->stack_base);
index 80b964d..7b102c6 100644 (file)
@@ -186,19 +186,17 @@ do {                                                       \
  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  */
-#define DLINFO_ARCH_ITEMS       3
+#define DLINFO_ARCH_ITEMS       5
 #define ARCH_DLINFO                                                     \
 do {                                                                    \
-       sp -= DLINFO_ARCH_ITEMS * 2;                                    \
-        NEW_AUX_ENT(0, AT_DCACHEBSIZE, 0x20);                           \
-        NEW_AUX_ENT(1, AT_ICACHEBSIZE, 0x20);                           \
-        NEW_AUX_ENT(2, AT_UCACHEBSIZE, 0);                              \
+        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
+        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
+        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
         /*                                                              \
          * Now handle glibc compatibility.                              \
          */                                                             \
-       sp -= 2*2;                                                      \
-       NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC);                     \
-       NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC);                     \
+       NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);                        \
+       NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);                        \
  } while (0)
 
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
@@ -643,24 +641,24 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc,
         if ((unsigned long)csp & 15UL)
             sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
         
-#define NEW_AUX_ENT(nr, id, val) \
-          put_user (id, sp + (nr * 2)); \
-          put_user (val, sp + (nr * 2 + 1))
-        sp -= 2;
-        NEW_AUX_ENT (0, AT_NULL, 0);
-
-       sp -= DLINFO_ITEMS*2;
-        NEW_AUX_ENT( 0, AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
-        NEW_AUX_ENT( 1, AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
-        NEW_AUX_ENT( 2, AT_PHNUM, (target_ulong)(exec->e_phnum));
-        NEW_AUX_ENT( 3, AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
-        NEW_AUX_ENT( 4, AT_BASE, (target_ulong)(interp_load_addr));
-        NEW_AUX_ENT( 5, AT_FLAGS, (target_ulong)0);
-        NEW_AUX_ENT( 6, AT_ENTRY, load_bias + exec->e_entry);
-        NEW_AUX_ENT( 7, AT_UID, (target_ulong) getuid());
-        NEW_AUX_ENT( 8, AT_EUID, (target_ulong) geteuid());
-        NEW_AUX_ENT( 9, AT_GID, (target_ulong) getgid());
-        NEW_AUX_ENT(11, AT_EGID, (target_ulong) getegid());
+#define NEW_AUX_ENT(id, val) \
+          sp -= 2; \
+          put_user (id, sp); \
+          put_user (val, sp + 1)
+        NEW_AUX_ENT (AT_NULL, 0);
+
+        /* There must be exactly DLINFO_ITEMS entries here.  */
+        NEW_AUX_ENT(AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
+        NEW_AUX_ENT(AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
+        NEW_AUX_ENT(AT_PHNUM, (target_ulong)(exec->e_phnum));
+        NEW_AUX_ENT(AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
+        NEW_AUX_ENT(AT_BASE, (target_ulong)(interp_load_addr));
+        NEW_AUX_ENT(AT_FLAGS, (target_ulong)0);
+        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+        NEW_AUX_ENT(AT_UID, (target_ulong) getuid());
+        NEW_AUX_ENT(AT_EUID, (target_ulong) geteuid());
+        NEW_AUX_ENT(AT_GID, (target_ulong) getgid());
+        NEW_AUX_ENT(AT_EGID, (target_ulong) getegid());
 #ifdef ARCH_DLINFO
        /* 
         * ARCH_DLINFO must come last so platform specific code can enforce
index 297c0a4..1ff9bde 100644 (file)
@@ -251,6 +251,9 @@ static void do_info_history (void)
 
 static void do_quit(void)
 {
+#ifdef USE_KQEMU
+    kqemu_record_dump();
+#endif
     exit(0);
 }
 
index c2c8346..7f2ed65 100644 (file)
@@ -1,6 +1,6 @@
 <HTML>
 <HEAD>
-<!-- Created by texi2html 1.56k from qemu-doc.texi on 24 July 2005 -->
+<!-- Created by texi2html 1.56k from qemu-doc.texi on 4 September 2005 -->
 
 <TITLE>QEMU CPU Emulator User Documentation</TITLE>
 </HEAD>
 <LI><A NAME="TOC27" HREF="qemu-doc.html#SEC27">3.10.2.1 SVGA graphic modes support</A>
 <LI><A NAME="TOC28" HREF="qemu-doc.html#SEC28">3.10.2.2 CPU usage reduction</A>
 <LI><A NAME="TOC29" HREF="qemu-doc.html#SEC29">3.10.2.3 Windows 2000 disk full problem</A>
-<LI><A NAME="TOC30" HREF="qemu-doc.html#SEC30">3.10.2.4 Windows XP security problems</A>
+<LI><A NAME="TOC30" HREF="qemu-doc.html#SEC30">3.10.2.4 Windows 2000 shutdown</A>
+<LI><A NAME="TOC31" HREF="qemu-doc.html#SEC31">3.10.2.5 Share a directory between Unix and Windows</A>
+<LI><A NAME="TOC32" HREF="qemu-doc.html#SEC32">3.10.2.6 Windows XP security problems</A>
 </UL>
-<LI><A NAME="TOC31" HREF="qemu-doc.html#SEC31">3.10.3 MS-DOS and FreeDOS</A>
+<LI><A NAME="TOC33" HREF="qemu-doc.html#SEC33">3.10.3 MS-DOS and FreeDOS</A>
 <UL>
-<LI><A NAME="TOC32" HREF="qemu-doc.html#SEC32">3.10.3.1 CPU usage reduction</A>
+<LI><A NAME="TOC34" HREF="qemu-doc.html#SEC34">3.10.3.1 CPU usage reduction</A>
 </UL>
 </UL>
 </UL>
-<LI><A NAME="TOC33" HREF="qemu-doc.html#SEC33">4. QEMU PowerPC System emulator invocation</A>
-<LI><A NAME="TOC34" HREF="qemu-doc.html#SEC34">5. Sparc32 System emulator invocation</A>
-<LI><A NAME="TOC35" HREF="qemu-doc.html#SEC35">6. Sparc64 System emulator invocation</A>
-<LI><A NAME="TOC36" HREF="qemu-doc.html#SEC36">7. MIPS System emulator invocation</A>
-<LI><A NAME="TOC37" HREF="qemu-doc.html#SEC37">8. QEMU User space emulator invocation</A>
+<LI><A NAME="TOC35" HREF="qemu-doc.html#SEC35">4. QEMU PowerPC System emulator invocation</A>
+<LI><A NAME="TOC36" HREF="qemu-doc.html#SEC36">5. Sparc32 System emulator invocation</A>
+<LI><A NAME="TOC37" HREF="qemu-doc.html#SEC37">6. Sparc64 System emulator invocation</A>
+<LI><A NAME="TOC38" HREF="qemu-doc.html#SEC38">7. MIPS System emulator invocation</A>
+<LI><A NAME="TOC39" HREF="qemu-doc.html#SEC39">8. QEMU User space emulator invocation</A>
 <UL>
-<LI><A NAME="TOC38" HREF="qemu-doc.html#SEC38">8.1 Quick Start</A>
-<LI><A NAME="TOC39" HREF="qemu-doc.html#SEC39">8.2 Wine launch</A>
-<LI><A NAME="TOC40" HREF="qemu-doc.html#SEC40">8.3 Command line options</A>
+<LI><A NAME="TOC40" HREF="qemu-doc.html#SEC40">8.1 Quick Start</A>
+<LI><A NAME="TOC41" HREF="qemu-doc.html#SEC41">8.2 Wine launch</A>
+<LI><A NAME="TOC42" HREF="qemu-doc.html#SEC42">8.3 Command line options</A>
 </UL>
-<LI><A NAME="TOC41" HREF="qemu-doc.html#SEC41">9. Compilation from the sources</A>
+<LI><A NAME="TOC43" HREF="qemu-doc.html#SEC43">9. Compilation from the sources</A>
 <UL>
-<LI><A NAME="TOC42" HREF="qemu-doc.html#SEC42">9.1 Linux/Unix</A>
+<LI><A NAME="TOC44" HREF="qemu-doc.html#SEC44">9.1 Linux/Unix</A>
 <UL>
-<LI><A NAME="TOC43" HREF="qemu-doc.html#SEC43">9.1.1 Compilation</A>
-<LI><A NAME="TOC44" HREF="qemu-doc.html#SEC44">9.1.2 Tested tool versions</A>
+<LI><A NAME="TOC45" HREF="qemu-doc.html#SEC45">9.1.1 Compilation</A>
+<LI><A NAME="TOC46" HREF="qemu-doc.html#SEC46">9.1.2 Tested tool versions</A>
 </UL>
-<LI><A NAME="TOC45" HREF="qemu-doc.html#SEC45">9.2 Windows</A>
-<LI><A NAME="TOC46" HREF="qemu-doc.html#SEC46">9.3 Cross compilation for Windows with Linux</A>
-<LI><A NAME="TOC47" HREF="qemu-doc.html#SEC47">9.4 Mac OS X</A>
+<LI><A NAME="TOC47" HREF="qemu-doc.html#SEC47">9.2 Windows</A>
+<LI><A NAME="TOC48" HREF="qemu-doc.html#SEC48">9.3 Cross compilation for Windows with Linux</A>
+<LI><A NAME="TOC49" HREF="qemu-doc.html#SEC49">9.4 Mac OS X</A>
 </UL>
 </UL>
 <P><HR><P>
@@ -158,7 +160,7 @@ For user emulation, x86, PowerPC, ARM, and Sparc32/64 CPUs are supported.
 <H1><A NAME="SEC3" HREF="qemu-doc.html#TOC3">2. Installation</A></H1>
 
 <P>
-If you want to compile QEMU yourself, see section <A HREF="qemu-doc.html#SEC41">9. Compilation from the sources</A>.
+If you want to compile QEMU yourself, see section <A HREF="qemu-doc.html#SEC43">9. Compilation from the sources</A>.
 
 
 
@@ -167,7 +169,7 @@ If you want to compile QEMU yourself, see section <A HREF="qemu-doc.html#SEC41">
 
 <P>
 If a precompiled package is available for your distribution - you just
-have to install it. Otherwise, see section <A HREF="qemu-doc.html#SEC41">9. Compilation from the sources</A>.
+have to install it. Otherwise, see section <A HREF="qemu-doc.html#SEC43">9. Compilation from the sources</A>.
 
 
 
@@ -421,7 +423,7 @@ Then <TT>`dir'</TT> can be accessed in <TT>`\\smbserver\qemu'</TT>.
 
 Note that a SAMBA server must be installed on the host OS in
 <TT>`/usr/sbin/smbd'</TT>. QEMU was tested succesfully with smbd version
-2.2.7a from the Red Hat 9.
+2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
 
 <DT><SAMP>`-redir [tcp|udp]:host-port:[guest-host]:guest-port'</SAMP>
 <DD>
@@ -1383,7 +1385,34 @@ IDE transfers).
 
 
 
-<H4><A NAME="SEC30" HREF="qemu-doc.html#TOC30">3.10.2.4 Windows XP security problems</A></H4>
+<H4><A NAME="SEC30" HREF="qemu-doc.html#TOC30">3.10.2.4 Windows 2000 shutdown</A></H4>
+
+<P>
+Windows 2000 cannot automatically shutdown in QEMU although Windows 98
+can. It comes from the fact that Windows 2000 does not automatically
+use the APM driver provided by the BIOS.
+
+
+<P>
+In order to correct that, do the following (thanks to Struan
+Bartlett): go to the Control Panel =&#62; Add/Remove Hardware &#38; Next =&#62;
+Add/Troubleshoot a device =&#62; Add a new device &#38; Next =&#62; No, select the
+hardware from a list &#38; Next =&#62; NT Apm/Legacy Support &#38; Next =&#62; Next
+(again) a few times. Now the driver is installed and Windows 2000 now
+correctly instructs QEMU to shutdown at the appropriate moment. 
+
+
+
+
+<H4><A NAME="SEC31" HREF="qemu-doc.html#TOC31">3.10.2.5 Share a directory between Unix and Windows</A></H4>
+
+<P>
+See section <A HREF="qemu-doc.html#SEC10">3.3 Invocation</A> about the help of the option <SAMP>`-smb'</SAMP>.
+
+
+
+
+<H4><A NAME="SEC32" HREF="qemu-doc.html#TOC32">3.10.2.6 Windows XP security problems</A></H4>
 
 <P>
 Some releases of Windows XP install correctly but give a security
@@ -1405,11 +1434,11 @@ Future QEMU releases are likely to correct this bug.
 
 
 
-<H3><A NAME="SEC31" HREF="qemu-doc.html#TOC31">3.10.3 MS-DOS and FreeDOS</A></H3>
+<H3><A NAME="SEC33" HREF="qemu-doc.html#TOC33">3.10.3 MS-DOS and FreeDOS</A></H3>
 
 
 
-<H4><A NAME="SEC32" HREF="qemu-doc.html#TOC32">3.10.3.1 CPU usage reduction</A></H4>
+<H4><A NAME="SEC34" HREF="qemu-doc.html#TOC34">3.10.3.1 CPU usage reduction</A></H4>
 
 <P>
 DOS does not correctly use the CPU HLT instruction. The result is that
@@ -1420,7 +1449,7 @@ problem.
 
 
 
-<H1><A NAME="SEC33" HREF="qemu-doc.html#TOC33">4. QEMU PowerPC System emulator invocation</A></H1>
+<H1><A NAME="SEC35" HREF="qemu-doc.html#TOC35">4. QEMU PowerPC System emulator invocation</A></H1>
 
 <P>
 Use the executable <TT>`qemu-system-ppc'</TT> to simulate a complete PREP
@@ -1518,7 +1547,7 @@ More information is available at
 
 
 
-<H1><A NAME="SEC34" HREF="qemu-doc.html#TOC34">5. Sparc32 System emulator invocation</A></H1>
+<H1><A NAME="SEC36" HREF="qemu-doc.html#TOC36">5. Sparc32 System emulator invocation</A></H1>
 
 <P>
 Use the executable <TT>`qemu-system-sparc'</TT> to simulate a JavaStation
@@ -1585,7 +1614,7 @@ Set the initial TCX graphic mode. The default is 1024x768.
 
 
 
-<H1><A NAME="SEC35" HREF="qemu-doc.html#TOC35">6. Sparc64 System emulator invocation</A></H1>
+<H1><A NAME="SEC37" HREF="qemu-doc.html#TOC37">6. Sparc64 System emulator invocation</A></H1>
 
 <P>
 Use the executable <TT>`qemu-system-sparc64'</TT> to simulate a Sun4u machine.
@@ -1614,7 +1643,7 @@ PC-compatible serial ports
 
 
 
-<H1><A NAME="SEC36" HREF="qemu-doc.html#TOC36">7. MIPS System emulator invocation</A></H1>
+<H1><A NAME="SEC38" HREF="qemu-doc.html#TOC38">7. MIPS System emulator invocation</A></H1>
 
 <P>
 Use the executable <TT>`qemu-system-mips'</TT> to simulate a MIPS machine.
@@ -1623,11 +1652,11 @@ The emulator begins to launch a Linux kernel.
 
 
 
-<H1><A NAME="SEC37" HREF="qemu-doc.html#TOC37">8. QEMU User space emulator invocation</A></H1>
+<H1><A NAME="SEC39" HREF="qemu-doc.html#TOC39">8. QEMU User space emulator invocation</A></H1>
 
 
 
-<H2><A NAME="SEC38" HREF="qemu-doc.html#TOC38">8.1 Quick Start</A></H2>
+<H2><A NAME="SEC40" HREF="qemu-doc.html#TOC40">8.1 Quick Start</A></H2>
 
 <P>
 In order to launch a Linux process, QEMU needs the process executable
@@ -1689,7 +1718,7 @@ qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 /usr/local/qemu-i386/bin/ls-i386
 
 
 
-<H2><A NAME="SEC39" HREF="qemu-doc.html#TOC39">8.2 Wine launch</A></H2>
+<H2><A NAME="SEC41" HREF="qemu-doc.html#TOC41">8.2 Wine launch</A></H2>
 
 
 <UL>
@@ -1724,7 +1753,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine /usr/local/qemu-i386/wine/c/Program
 
 
 
-<H2><A NAME="SEC40" HREF="qemu-doc.html#TOC40">8.3 Command line options</A></H2>
+<H2><A NAME="SEC42" HREF="qemu-doc.html#TOC42">8.3 Command line options</A></H2>
 
 
 <PRE>
@@ -1760,15 +1789,15 @@ Act as if the host page size was 'pagesize' bytes
 
 
 
-<H1><A NAME="SEC41" HREF="qemu-doc.html#TOC41">9. Compilation from the sources</A></H1>
+<H1><A NAME="SEC43" HREF="qemu-doc.html#TOC43">9. Compilation from the sources</A></H1>
 
 
 
-<H2><A NAME="SEC42" HREF="qemu-doc.html#TOC42">9.1 Linux/Unix</A></H2>
+<H2><A NAME="SEC44" HREF="qemu-doc.html#TOC44">9.1 Linux/Unix</A></H2>
 
 
 
-<H3><A NAME="SEC43" HREF="qemu-doc.html#TOC43">9.1.1 Compilation</A></H3>
+<H3><A NAME="SEC45" HREF="qemu-doc.html#TOC45">9.1.1 Compilation</A></H3>
 
 <P>
 First you must decompress the sources:
@@ -1800,7 +1829,7 @@ to install QEMU in <TT>`/usr/local'</TT>.
 
 
 
-<H3><A NAME="SEC44" HREF="qemu-doc.html#TOC44">9.1.2 Tested tool versions</A></H3>
+<H3><A NAME="SEC46" HREF="qemu-doc.html#TOC46">9.1.2 Tested tool versions</A></H3>
 
 <P>
 In order to compile QEMU succesfully, it is very important that you
@@ -1839,7 +1868,7 @@ variables. You must use gcc 3.x on PowerPC.
 
 
 
-<H2><A NAME="SEC45" HREF="qemu-doc.html#TOC45">9.2 Windows</A></H2>
+<H2><A NAME="SEC47" HREF="qemu-doc.html#TOC47">9.2 Windows</A></H2>
 
 
 <UL>
@@ -1876,7 +1905,7 @@ correct SDL directory when invoked.
 
 
 
-<H2><A NAME="SEC46" HREF="qemu-doc.html#TOC46">9.3 Cross compilation for Windows with Linux</A></H2>
+<H2><A NAME="SEC48" HREF="qemu-doc.html#TOC48">9.3 Cross compilation for Windows with Linux</A></H2>
 
 
 <UL>
@@ -1918,7 +1947,7 @@ QEMU for Win32.
 
 
 
-<H2><A NAME="SEC47" HREF="qemu-doc.html#TOC47">9.4 Mac OS X</A></H2>
+<H2><A NAME="SEC49" HREF="qemu-doc.html#TOC49">9.4 Mac OS X</A></H2>
 
 <P>
 The Mac OS X patches are not fully merged in QEMU, so you should look
@@ -1927,7 +1956,7 @@ information.
 
 
 <P><HR><P>
-This document was generated on 24 July 2005 using
+This document was generated on 4 September 2005 using
 <A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A>&nbsp;1.56k.
 </BODY>
 </HTML>
index 17072a7..526bd4b 100644 (file)
@@ -113,6 +113,7 @@ qemu linux.img
 
 Linux should boot and give you a prompt.
 
+@node sec_invocation
 @section Invocation
 
 @example
@@ -254,7 +255,7 @@ Then @file{dir} can be accessed in @file{\\smbserver\qemu}.
 
 Note that a SAMBA server must be installed on the host OS in
 @file{/usr/sbin/smbd}. QEMU was tested succesfully with smbd version
-2.2.7a from the Red Hat 9.
+2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
 
 @item -redir [tcp|udp]:host-port:[guest-host]:guest-port
 
@@ -912,6 +913,23 @@ option to enable a specific workaround. After Windows 2000 is
 installed, you no longer need this option (this option slows down the
 IDE transfers).
 
+@subsubsection Windows 2000 shutdown
+
+Windows 2000 cannot automatically shutdown in QEMU although Windows 98
+can. It comes from the fact that Windows 2000 does not automatically
+use the APM driver provided by the BIOS.
+
+In order to correct that, do the following (thanks to Struan
+Bartlett): go to the Control Panel => Add/Remove Hardware & Next =>
+Add/Troubleshoot a device => Add a new device & Next => No, select the
+hardware from a list & Next => NT Apm/Legacy Support & Next => Next
+(again) a few times. Now the driver is installed and Windows 2000 now
+correctly instructs QEMU to shutdown at the appropriate moment. 
+
+@subsubsection Share a directory between Unix and Windows
+
+See @ref{sec_invocation} about the help of the option @option{-smb}.
+
 @subsubsection Windows XP security problems
 
 Some releases of Windows XP install correctly but give a security
index 51abc2c..7181373 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "QEMU-IMG 1"
-.TH QEMU-IMG 1 "2005-07-24" " " " "
+.TH QEMU-IMG 1 "2005-09-04" " " " "
 .SH "NAME"
 qemu\-img \- QEMU disk image utility
 .SH "SYNOPSIS"
index b6c948b..774996e 100644 (file)
@@ -1,6 +1,6 @@
 <HTML>
 <HEAD>
-<!-- Created by texi2html 1.56k from qemu-tech.texi on 24 July 2005 -->
+<!-- Created by texi2html 1.56k from qemu-tech.texi on 4 September 2005 -->
 
 <TITLE>QEMU Internals</TITLE>
 </HEAD>
@@ -773,7 +773,7 @@ and host CPUs.
 <P>
 Example of usage of <CODE>libqemu</CODE> to emulate a user mode i386 CPU.
 <P><HR><P>
-This document was generated on 24 July 2005 using
+This document was generated on 4 September 2005 using
 <A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A>&nbsp;1.56k.
 </BODY>
 </HTML>
index dff6013..9d22629 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "QEMU 1"
-.TH QEMU 1 "2005-07-24" " " " "
+.TH QEMU 1 "2005-09-04" " " " "
 .SH "NAME"
 qemu  \- QEMU System Emulator
 .SH "SYNOPSIS"
@@ -295,7 +295,7 @@ Then \fIdir\fR can be accessed in \fI\e\esmbserver\eqemu\fR.
 .Sp
 Note that a \s-1SAMBA\s0 server must be installed on the host \s-1OS\s0 in
 \&\fI/usr/sbin/smbd\fR. \s-1QEMU\s0 was tested succesfully with smbd version
-2.2.7a from the Red Hat 9.
+2.2.7a from the Red Hat 9 and version 3.0.10\-1.fc3 from Fedora Core 3.
 .IP "\fB\-redir [tcp|udp]:host\-port:[guest\-host]:guest\-port\fR" 4
 .IX Item "-redir [tcp|udp]:host-port:[guest-host]:guest-port"
 When using the user mode network stack, redirect incoming \s-1TCP\s0 or \s-1UDP\s0
index 3b840a8..404cce8 100644 (file)
@@ -350,7 +350,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
         * See if anything has timed out 
         */
        if (link_up) {
-               if (time_fasttimo && ((curtime - time_fasttimo) >= 199)) {
+               if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
                        tcp_fasttimo();
                        time_fasttimo = 0;
                }
index adbd561..c3e8fe8 100644 (file)
@@ -2204,12 +2204,13 @@ void cpu_dump_state(CPUState *env, FILE *f,
         else
             cpu_fprintf(f, " ");
     }
-    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
+    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c\n", 
              env->cpsr, 
             env->cpsr & (1 << 31) ? 'N' : '-',
             env->cpsr & (1 << 30) ? 'Z' : '-',
             env->cpsr & (1 << 29) ? 'C' : '-',
-            env->cpsr & (1 << 28) ? 'V' : '-');
+            env->cpsr & (1 << 28) ? 'V' : '-',
+            env->thumb ? 'T' : 'A');
 
     for (i = 0; i < 16; i++) {
         d.d = env->vfp.regs[i];
index 01b663f..c7fea95 100644 (file)
@@ -622,9 +622,10 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
         if (has_error_code) {
-            int mask;
+            int mask, type;
             /* push the error code */
-            shift = (env->segs[R_CS].flags >> DESC_B_SHIFT) & 1;
+            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
+            shift = type >> 3;
             if (env->segs[R_SS].flags & DESC_B_MASK)
                 mask = 0xffffffff;
             else
@@ -1307,7 +1308,7 @@ void helper_cpuid(void)
         break;
     case 1:
         EAX = env->cpuid_version;
-        EBX = 0;
+        EBX = 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
         ECX = env->cpuid_ext_features;
         EDX = env->cpuid_features;
         break;
@@ -2012,7 +2013,6 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
 #endif
         sp_mask = get_sp_mask(env->segs[R_SS].flags);
     sp = ESP;
-    /* XXX: ssp is zero in 64 bit ? */
     ssp = env->segs[R_SS].base;
     new_eflags = 0; /* avoid warning */
 #ifdef TARGET_X86_64
@@ -2145,7 +2145,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
         cpu_x86_set_cpl(env, rpl);
         sp = new_esp;
 #ifdef TARGET_X86_64
-        if (shift == 2)
+        if (env->hflags & HF_CS64_MASK)
             sp_mask = -1;
         else
 #endif
@@ -2329,7 +2329,10 @@ void helper_invlpg(target_ulong addr)
 void helper_rdtsc(void)
 {
     uint64_t val;
-    
+
+    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
+        raise_exception(EXCP0D_GPF);
+    }
     val = cpu_get_tsc(env);
     EAX = (uint32_t)(val);
     EDX = (uint32_t)(val >> 32);
index 142b662..6370045 100644 (file)
@@ -865,7 +865,7 @@ void OPPROTO op_decq_ECX(void)
 
 void op_addl_A0_SS(void)
 {
-    A0 += (long)env->segs[R_SS].base;
+    A0 = (uint32_t)(A0 + env->segs[R_SS].base);
 }
 
 void op_subl_A0_2(void)
index 619522a..0f6b0eb 100644 (file)
@@ -4909,7 +4909,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_op_movl_T1_imu(offset);
         }
         goto do_lcall;
-    case 0xe9: /* jmp */
+    case 0xe9: /* jmp im */
         if (dflag)
             tval = (int32_t)insn_get(s, OT_LONG);
         else
@@ -5366,6 +5366,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x131: /* rdtsc */
+        gen_jmp_im(pc_start - s->cs_base);
         gen_op_rdtsc();
         break;
     case 0x134: /* sysenter */
index 354968d..e7cd966 100644 (file)
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -875,6 +875,11 @@ static void host_alarm_handler(int host_signum)
                            qemu_get_clock(rt_clock))) {
         /* stop the cpu because a timer occured */
         cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
+#ifdef USE_KQEMU
+        if (global_env->kqemu_enabled) {
+            kqemu_cpu_interrupt(global_env);
+        }
+#endif
     }
 }
 
@@ -1138,7 +1143,11 @@ CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
 
 #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
 
+#define TERM_FIFO_MAX_SIZE 1
+
 static int term_got_escape, client_index;
+static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
+int term_fifo_size;
 
 void term_print_help(void)
 {
@@ -1207,19 +1216,37 @@ static void stdio_received_byte(int ch)
             
             chr = stdio_clients[client_index];
             s = chr->opaque;
-            buf[0] = ch;
-            /* XXX: should queue the char if the device is not
-               ready */
-            if (s->fd_can_read(s->fd_opaque) > 0) 
+            if (s->fd_can_read(s->fd_opaque) > 0) {
+                buf[0] = ch;
                 s->fd_read(s->fd_opaque, buf, 1);
+            } else if (term_fifo_size == 0) {
+                term_fifo[term_fifo_size++] = ch;
+            }
         }
     }
 }
 
 static int stdio_can_read(void *opaque)
 {
-    /* XXX: not strictly correct */
-    return 1;
+    CharDriverState *chr;
+    FDCharDriver *s;
+
+    if (client_index < stdio_nb_clients) {
+        chr = stdio_clients[client_index];
+        s = chr->opaque;
+        /* try to flush the queue if needed */
+        if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) {
+            s->fd_read(s->fd_opaque, term_fifo, 1);
+            term_fifo_size = 0;
+        }
+        /* see if we can absorb more chars */
+        if (term_fifo_size == 0)
+            return 1;
+        else
+            return 0;
+    } else {
+        return 1;
+    }
 }
 
 static void stdio_read(void *opaque, const uint8_t *buf, int size)
index e0bc8b8..31d05b6 100644 (file)
--- a/qemu/vl.h
+++ b/qemu/vl.h
@@ -878,4 +878,6 @@ const char *readline_get_history(unsigned int index);
 void readline_start(const char *prompt, int is_password,
                     ReadLineFunc *readline_func, void *opaque);
 
+void kqemu_record_dump(void);
+
 #endif /* VL_H */