summaryrefslogtreecommitdiff
path: root/emulators
diff options
context:
space:
mode:
authorPav Lucistnik <pav@FreeBSD.org>2005-05-05 12:41:10 +0000
committerPav Lucistnik <pav@FreeBSD.org>2005-05-05 12:41:10 +0000
commit8ca48ff8979e6c7a1377bf6d55a9dc0a230c29c5 (patch)
tree3916ca087ea065ad456125c7b5bc216c73253ce6 /emulators
parent- update to 1.29 (diff)
- Update to 2005-05-02 snapshot
- Add kqemu support PR: ports/80595 Submitted by: Juergen Lock <nox@jelal.kn-bremen.de> (maintainer)
Notes
Notes: svn path=/head/; revision=134652
Diffstat (limited to 'emulators')
-rw-r--r--emulators/qemu-devel/Makefile52
-rw-r--r--emulators/qemu-devel/distinfo6
-rw-r--r--emulators/qemu-devel/files/kmod_bsd.c575
-rw-r--r--emulators/qemu-devel/files/kqemu-patch68
-rw-r--r--emulators/qemu-devel/files/patch-fbsd28
-rw-r--r--emulators/qemu-devel/files/patch-osdep.c40
-rw-r--r--emulators/qemu-devel/pkg-plist2
-rw-r--r--emulators/qemu/Makefile52
-rw-r--r--emulators/qemu/distinfo6
-rw-r--r--emulators/qemu/files/kmod_bsd.c575
-rw-r--r--emulators/qemu/files/kqemu-patch68
-rw-r--r--emulators/qemu/files/patch-fbsd28
-rw-r--r--emulators/qemu/files/patch-osdep.c40
-rw-r--r--emulators/qemu/pkg-plist2
14 files changed, 1528 insertions, 14 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile
index 6d1a7c1a4c54..5bec3cc93a84 100644
--- a/emulators/qemu-devel/Makefile
+++ b/emulators/qemu-devel/Makefile
@@ -6,10 +6,13 @@
#
PORTNAME= qemu
-PORTVERSION= 0.7.0
-POTREVISION= 1
+PORTVERSION= 0.7.0s.20050502
CATEGORIES= emulators
-MASTER_SITES= http://www.qemu.org/
+MASTER_SITES= http://www.qemu.org/ \
+ http://people.fruitsalad.org/nox/qemu/ \
+ http://dad-answers.com/qemu/
+DISTNAME= ${PORTNAME}-snapshot-2005-05-02_23
+EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX}
MAINTAINER= nox@jelal.kn-bremen.de
COMMENT= QEMU CPU Emulator
@@ -19,7 +22,13 @@ BUILD_DEPENDS+= texi2html:${PORTSDIR}/textproc/texi2html
RUN_DEPENDS+= ${LOCALBASE}/sbin/smbd:${PORTSDIR}/net/samba
.endif
+.if defined(WITH_KQEMU)
+DISTKQEMU= kqemu-0.6.2-1.tar.gz
+DISTFILES= ${EXTRACT_ONLY} ${DISTKQEMU}
+.endif
+
HAS_CONFIGURE= yes
+USE_BZIP2= yes
USE_GMAKE= yes
USE_GETOPT_LONG= yes
USE_SDL= sdl
@@ -29,6 +38,14 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC}
MAKE_ENV+= BSD_MAKE=${MAKE}
MAN1= qemu.1 qemu-img.1
ONLY_FOR_ARCHS= amd64 i386
+.if defined(WITH_KQEMU)
+NO_PACKAGE= Depends on kernel, and module not redistributable
+PLIST_SUB= WITH_KQEMU=""
+PLIST_SUB+= KMODDIR=${KMODDIR}
+EXTRA_PATCHES= ${FILESDIR}/kqemu-patch
+.else
+PLIST_SUB= WITH_KQEMU="@comment "
+.endif
# gcc34 (system cc on 5.x now) has problems with qemu on amd64
# (doesnt build target-i386/op.c), try the one in ports which is newer
@@ -47,19 +64,48 @@ USE_GCC= 3.4
USE_GCC= 3.4
.endif
+.if defined(WITH_KQEMU) && ${ARCH} != "i386"
+IGNORE= kqemu only supported on i386
+.endif
+
+.if defined(WITH_KQEMU) && !exists(${SRC_BASE}/sys/Makefile)
+IGNORE= kqemu requires kernel source to be installed
+.endif
+
pre-everything::
+.if !defined(WITH_KQEMU) && ${ARCH} == "i386"
+ @${ECHO_MSG} "Notice: you can build qemu with the (alpha!) kqemu accelerator kernel module"
+ @${ECHO_MSG} "by defining WITH_KQEMU."
+.endif
.if !defined(WITH_SAMBA) && !exists(${LOCALBASE}/sbin/smbd)
@${ECHO_MSG} "Notice: if you need qemu's -smb option (smb-export local dir to guest)"
@${ECHO_MSG} "then you also need samba, you can have this port install it by defining"
@${ECHO_MSG} "WITH_SAMBA."
.endif
+.if defined(WITH_KQEMU)
+post-extract:
+ @cd ${WRKSRC} && ${TAR} xfz ${_DISTDIR}/${DISTKQEMU}
+ @${CP} ${FILESDIR}/kmod_bsd.c ${WRKSRC}/kqemu
+.endif
+
pre-patch:
@for A in ${ONLY_FOR_ARCHS}; do \
${MKDIR} ${WRKSRC}/bsd/$$A; \
done
post-install:
+.if defined(WITH_KQEMU)
+ ${INSTALL_SCRIPT} ${WRKSRC}/kqemu/kqemu.ko ${KMODDIR}
+ if mount |${GREP} ^devfs >/dev/null ; then \
+ : ; \
+ else \
+ if [ ! -e /dev/kqemu ]; then\
+ mknod /dev/kqemu c 250 0 ; \
+ fi ; \
+ ${CHMOD} 666 /dev/kqemu ; \
+ fi
+.endif
@${CAT} ${PKGMESSAGE}
.include <bsd.port.post.mk>
diff --git a/emulators/qemu-devel/distinfo b/emulators/qemu-devel/distinfo
index a02ee0ccb2b1..5d4b1c2ede35 100644
--- a/emulators/qemu-devel/distinfo
+++ b/emulators/qemu-devel/distinfo
@@ -1,2 +1,4 @@
-MD5 (qemu-0.7.0.tar.gz) = 234e9ace03b00259bb57dc5a9c633056
-SIZE (qemu-0.7.0.tar.gz) = 1211802
+MD5 (qemu-snapshot-2005-05-02_23.tar.bz2) = b7d4115a68bf93a9ad2c0c64a0c59137
+SIZE (qemu-snapshot-2005-05-02_23.tar.bz2) = 1020482
+MD5 (kqemu-0.6.2-1.tar.gz) = c6bb3b40fb3d526d731eb0f1f9dee7ee
+SIZE (kqemu-0.6.2-1.tar.gz) = 21002
diff --git a/emulators/qemu-devel/files/kmod_bsd.c b/emulators/qemu-devel/files/kmod_bsd.c
new file mode 100644
index 000000000000..63e1cf5053d8
--- /dev/null
+++ b/emulators/qemu-devel/files/kmod_bsd.c
@@ -0,0 +1,575 @@
+/*
+ * FreeBSD kernel wrapper for KQEMU
+ * Copyright (c) 2005 Antony T Curtis
+ *
+ * Based upon the Linux wrapper by Fabrice Bellard
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#if __FreeBSD_version < 500000
+#include <sys/buf.h>
+#endif
+#include <sys/uio.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#if __FreeBSD_version > 500000
+#include <sys/ktr.h>
+#include <sys/sched.h>
+#endif
+#include <sys/ioccom.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/module.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/stdarg.h>
+
+#define __KERNEL__
+
+#include "kqemu.h"
+
+static unsigned long cache_page(vm_offset_t paddr, caddr_t addr);
+static caddr_t find_page(vm_offset_t paddr, int free);
+
+static MALLOC_DEFINE(M_KQEMU, "KQEMU", "KQEMU Resources");
+
+struct pagecache {
+ caddr_t addr;
+};
+
+static struct pagecache **pagecache;
+#if __FreeBSD_version > 500000
+static struct mtx cache_lock;
+#endif
+
+static unsigned long cache_page(vm_offset_t paddr, caddr_t addr)
+{
+ unsigned long ppn = (unsigned long)(paddr >> PAGE_SHIFT);
+ int pci = (int)(ppn >> 10);
+ struct pagecache *cache;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!(cache = pagecache[pci])) {
+ if (!addr) {
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ cache = pagecache[pci] = (struct pagecache *)
+ kqemu_vmalloc(1024 * sizeof(struct pagecache));
+
+ memset(cache, 0, 1024 * sizeof(struct pagecache));
+ }
+ if (!addr) {
+ int i;
+ cache[ppn & 1023].addr = (caddr_t) 0;
+ for (i = 1023; i >= 0; i--, cache++)
+ if (cache->addr)
+ break;
+ if (i < 0) {
+ kqemu_vfree(pagecache[pci]);
+ pagecache[pci] = 0;
+ }
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ cache[ppn & 1023].addr = (caddr_t) (((unsigned long) addr) & ~PAGE_MASK);
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return ppn;
+}
+
+static caddr_t find_page(vm_offset_t paddr, int free)
+{
+ unsigned long ppn = (unsigned long)(paddr >> PAGE_SHIFT);
+ struct pagecache *cache;
+ caddr_t addr;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!(cache = pagecache[ppn >> 10])) {
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ addr = (caddr_t)(((unsigned long)cache[ppn & 1023].addr)
+ | ((unsigned long)paddr & PAGE_MASK));
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ if (free && addr)
+ cache_page(paddr, 0);
+ return addr;
+}
+
+/* lock the page at virtual address 'user_addr' and return its
+ page index. Return -1 if error */
+unsigned long CDECL kqemu_lock_user_page(unsigned long user_addr)
+{
+ int rc;
+ caddr_t addr = (caddr_t) user_addr;
+ vm_page_t m;
+ vm_offset_t paddr;
+
+ /*kqemu_log("kqemu_lock_user_page(0x%08x)\n", addr);*/
+
+ rc = vm_fault_quick(addr, VM_PROT_READ|VM_PROT_WRITE);
+ if (rc < 0) {
+ /*kqemu_log("vm_fault_quick failed rc=%d\n",rc);*/
+ return -1;
+ }
+ paddr = vtophys(addr);
+ m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_wire(m);
+
+ return cache_page(paddr, addr);
+}
+
+void CDECL kqemu_unlock_user_page(unsigned long page_index)
+{
+ vm_page_t m;
+ vm_offset_t paddr;
+ /*kqemu_log("kqemu_unlock_user_page(0x%08x)\n",page_index);*/
+
+ paddr = (vm_offset_t)(page_index << PAGE_SHIFT);
+ m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_unwire(m, 1);
+ cache_page(paddr, 0);
+}
+
+unsigned long CDECL kqemu_alloc_zeroed_page(void)
+{
+ void *addr;
+ vm_offset_t paddr;
+
+ /*kqemu_log("kqemu_alloc_zeroed_page()\n");*/
+ addr = contigmalloc(PAGE_SIZE, M_KQEMU, M_WAITOK, 0, ~0ul, PAGE_SIZE, 0);
+ if (!addr) {
+ /*kqemu_log("contigmalloc failed\n");*/
+ return -1;
+ }
+ memset(addr, 0, PAGE_SIZE);
+ paddr = vtophys(addr);
+ return cache_page(paddr, addr);
+}
+
+void CDECL kqemu_free_page(unsigned long page_index)
+{
+ vm_offset_t paddr;
+ caddr_t addr;
+ /*kqemu_log("kqemu_free_page(0x%08x)\n", page_index);*/
+ paddr = (vm_offset_t) (page_index << PAGE_SHIFT);
+ if ((addr = find_page(paddr,1))) {
+ contigfree((void *) addr, PAGE_SIZE, M_KQEMU);
+ }
+}
+
+void * CDECL kqemu_page_kaddr(unsigned long page_index)
+{
+ vm_offset_t paddr;
+ /*kqemu_log("kqemu_page_kaddr(0x%08x)\n", page_index);*/
+ paddr = (vm_offset_t) (page_index << PAGE_SHIFT);
+ return (void *) find_page(paddr, 0);
+}
+
+/* contraint: each page of the vmalloced area must be in the first 4
+ GB of physical memory */
+void * CDECL kqemu_vmalloc(unsigned int size)
+{
+ /*kqemu_log("kqemu_vmalloc(0x%08x)\n", size);*/
+ return malloc(size, M_KQEMU, M_WAITOK);
+}
+
+void CDECL kqemu_vfree(void *ptr)
+{
+ /*kqemu_log("kqemu_vfree(0x%08x)\n", ptr);*/
+ return free(ptr, M_KQEMU);
+}
+
+unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr)
+{
+ caddr_t addr = (caddr_t)vaddr;
+ vm_offset_t paddr = vtophys(addr);
+ return cache_page(paddr, addr);
+}
+
+#if __FreeBSD_version < 500000
+static int
+curpriority_cmp(struct proc *p)
+{
+ int c_class, p_class;
+
+ c_class = RTP_PRIO_BASE(curproc->p_rtprio.type);
+ p_class = RTP_PRIO_BASE(p->p_rtprio.type);
+ if (p_class != c_class)
+ return (p_class - c_class);
+ if (p_class == RTP_PRIO_NORMAL)
+ return (((int)p->p_priority - (int)curpriority) / PPQ);
+ return ((int)p->p_rtprio.prio - (int)curproc->p_rtprio.prio);
+}
+
+/* return TRUE if a signal is pending (i.e. the guest must stop
+ execution) */
+int CDECL kqemu_schedule(void)
+{
+ struct proc *p = curproc;
+ if (curpriority_cmp(p) > 0) {
+ int s = splhigh();
+ p->p_priority = MAXPRI;
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nvcsw++;
+ mi_switch();
+ splx(s);
+ }
+ return issignal(curproc) != 0;
+}
+
+#else
+
+/* return TRUE if a signal is pending (i.e. the guest must stop
+ execution) */
+int CDECL kqemu_schedule(void)
+{
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ int rc;
+ mtx_lock_spin(&sched_lock);
+ sched_prio(td, td->td_ksegrp->kg_user_pri);
+ mi_switch(SW_INVOL, NULL);
+ mtx_unlock_spin(&sched_lock);
+
+ PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ rc = cursig(td);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
+ PROC_UNLOCK(p);
+ return rc;
+}
+
+#endif
+
+
+static char log_buf[4096];
+
+void CDECL kqemu_log(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(log_buf, sizeof(log_buf), fmt, ap);
+ printf("kqemu: %s", log_buf);
+ va_end(ap);
+}
+
+/*********************************************************/
+
+
+#define KQEMU_MAX_INSTANCES 4
+
+struct kqemu_instance {
+ struct kqemu_state *state;
+};
+
+static int kqemu_ref_count = 0;
+static int max_locked_pages;
+#if __FreeBSD_version < 500000
+static dev_t kqemu_dev;
+#else
+static struct cdev *kqemu_dev;
+#endif
+
+
+static d_open_t kqemu_open;
+static d_close_t kqemu_close;
+static d_ioctl_t kqemu_ioctl;
+
+static struct cdevsw kqemu_cdevsw = {
+#if __FreeBSD_version < 500000
+ /* open */ kqemu_open,
+ /* close */ kqemu_close,
+ /* read */ noread,
+ /* write */ nowrite,
+ /* ioctl */ kqemu_ioctl,
+ /* poll */ nopoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "kqemu",
+ /* maj */ KQEMU_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* bmaj */ -1
+#else
+ .d_version = D_VERSION,
+ .d_open = kqemu_open,
+ .d_close = kqemu_close,
+ .d_ioctl = kqemu_ioctl,
+ .d_name = "kqemu",
+#endif
+};
+
+int
+#if __FreeBSD_version < 500000
+kqemu_open(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+#else
+kqemu_open(dev, flags, fmt, td)
+ struct cdev *dev;
+ int flags, fmt;
+ struct thread *td;
+{
+ struct proc *p = td->td_proc;
+#endif
+ struct kqemu_instance *ks;
+
+ if (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES)
+ return(EBUSY);
+
+ if ((flags & (FREAD|FWRITE)) == FREAD)
+ return(EPERM);
+
+ ks = (struct kqemu_instance *) malloc(sizeof(*ks), M_KQEMU, M_WAITOK);
+ if (ks == NULL)
+ return(ENOMEM);
+ memset(ks, 0, sizeof *ks);
+
+ dev->si_drv1 = ks;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ kqemu_ref_count++;
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ kqemu_log("opened by pid=%d\n", p->p_pid);
+ return(0);
+}
+
+int
+#if __FreeBSD_version < 500000
+kqemu_close(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+#else
+kqemu_close(dev, flags, fmt, td)
+ struct cdev *dev;
+ int flags, fmt;
+ struct thread *td;
+{
+ struct proc *p = td->td_proc;
+#endif
+ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
+
+ if (ks->state) {
+ kqemu_delete(ks->state);
+ ks->state = NULL;
+ }
+
+ free(ks, M_KQEMU);
+ dev->si_drv1 = NULL;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!--kqemu_ref_count) {
+ int i;
+ for (i = 1023; i >= 0; i--)
+ kqemu_vfree(pagecache[i]);
+ memset(pagecache, 0, 1024 * sizeof(void *));
+ }
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ kqemu_log("closed by pid=%d\n", p->p_pid);
+ return(0);
+}
+
+int
+#if __FreeBSD_version < 500000
+kqemu_ioctl(dev, cmd, cmdarg, flags, p)
+ dev_t dev;
+ unsigned long cmd;
+ caddr_t cmdarg;
+ int flags;
+ struct proc *p;
+{
+#else
+kqemu_ioctl(dev, cmd, cmdarg, flags, td)
+ struct cdev *dev;
+ unsigned long cmd;
+ caddr_t cmdarg;
+ int flags;
+ struct thread *td;
+{
+#endif
+ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
+ struct kqemu_state *s = ks->state;
+ long ret;
+ int error = 0;
+
+ switch (cmd) {
+ case KQEMU_INIT:
+ /*kqemu_log("KQEMU_INIT data=0x%08x\n",cmdarg);*/
+ {
+ if (s) {
+ error = (EIO);
+ break;
+ }
+
+ if (!(s = kqemu_init((struct kqemu_init *)cmdarg, max_locked_pages))) {
+ error = (ENOMEM);
+ break;
+ }
+
+ ks->state = s;
+ break;
+ }
+ case KQEMU_EXEC:
+ /*kqemu_log("KQEMU_EXEC data=0x%08x\n",cmdarg);*/
+ {
+ struct kqemu_cpu_state *ctx;
+
+ if (!s) {
+ error = (EIO);
+ break;
+ }
+
+ ctx = kqemu_get_cpu_state(s);
+ memcpy((void *)ctx, (void *)cmdarg, sizeof(struct kqemu_cpu_state));
+
+ ret = kqemu_exec(s);
+#if __FreeBSD_version > 500000
+ td->td_retval[0] = ret;
+#else
+ p->p_retval[0] = ret;
+#endif
+ memcpy((void *)cmdarg, (void *)ctx, sizeof(struct kqemu_cpu_state));
+
+ break;
+ }
+ case KQEMU_GET_VERSION:
+ /*kqemu_log("KQEMU_GET_VERSION data=0x%08x\n",cmdarg);*/
+ {
+ *(int *)cmdarg = KQEMU_VERSION;
+ break;
+ }
+ default:
+ /*kqemu_log("ioctl unknown 0x%08x\n",cmd);*/
+ error = (ENXIO);
+ }
+ return(error);
+}
+
+static int
+init_module(void)
+{
+#if __FreeBSD_version < 500000
+ int rc;
+#endif
+ printf("QEMU Accelerator Module version %d.%d.%d, Copyright (c) 2005 Fabrice Bellard\n"
+ "FreeBSD wrapper port, Copyright (c) 2005 Antony T Curtis\n"
+ "This is a proprietary product. Read the LICENSE file for more information\n"
+ "Redistribution of this module is prohibited without authorization\n",
+ (KQEMU_VERSION >> 16),
+ (KQEMU_VERSION >> 8) & 0xff,
+ (KQEMU_VERSION) & 0xff);
+
+ if (!(pagecache = (struct pagecache **)
+ kqemu_vmalloc(1024 * sizeof(void *))))
+ return(ENOMEM);
+ memset(pagecache, 0, 1024 * sizeof(void *));
+
+#if __FreeBSD_version > 500000
+ mtx_init(&cache_lock, "pagecache lock", NULL, MTX_SPIN);
+#endif
+
+ max_locked_pages = physmem / (2 * KQEMU_MAX_INSTANCES);
+ if (max_locked_pages > 32768)
+ max_locked_pages = 32768;
+
+#if __FreeBSD_version < 500000
+ if ((rc = cdevsw_add(&kqemu_cdevsw))) {
+ kqemu_log("error registering cdevsw, rc=%d\n", rc);
+ return(ENOENT);
+ }
+#endif
+
+ kqemu_dev = make_dev(&kqemu_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, "kqemu");
+
+ kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
+ KQEMU_MAX_INSTANCES, max_locked_pages * 4);
+
+ kqemu_ref_count = 0;
+ return 0;
+}
+
+static void
+cleanup_module(void)
+{
+#if __FreeBSD_version < 500000
+ int rc;
+#endif
+
+ destroy_dev(kqemu_dev);
+#if __FreeBSD_version < 500000
+ if ((rc = cdevsw_remove(&kqemu_cdevsw)))
+ kqemu_log("error unregistering, rc=%d\n", rc);
+#endif
+
+ kqemu_vfree(pagecache);
+ pagecache = 0;
+}
+
+static int
+kqemu_modevent(module_t mod, int type, void *data)
+{
+ int err = 0;
+ switch (type) {
+ case MOD_LOAD:
+ err = init_module();
+ break;
+ case MOD_UNLOAD:
+ if (kqemu_ref_count > 0) {
+ err = EBUSY;
+ break;
+ }
+ /* fall through */
+ case MOD_SHUTDOWN:
+ cleanup_module();
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+static moduledata_t kqemu_mod = {
+ "kqemu_driver",
+ kqemu_modevent,
+ NULL
+};
+
+DECLARE_MODULE(kqemu, kqemu_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+
diff --git a/emulators/qemu-devel/files/kqemu-patch b/emulators/qemu-devel/files/kqemu-patch
new file mode 100644
index 000000000000..ba82ba368808
--- /dev/null
+++ b/emulators/qemu-devel/files/kqemu-patch
@@ -0,0 +1,68 @@
+Index: qemu/kqemu/Makefile
+@@ -1,62 +1,5 @@
+-ifeq ($(PATCHLEVEL),)
+-# compile in kqemu directory
++KMOD= kqemu
++SRCS= kmod_bsd.c
++OBJS= kqemu-mod-i386.o
+
+--include ../config-host.mak
+-
+-ifdef CONFIG_KBUILD26
+-# 2.6 build
+-
+-all: kqemu.ko
+-
+-kqemu.ko:
+- make -C $(KERNEL_PATH) M=`pwd` modules
+-
+-else
+-# 2.4 build
+-
+-all: kqemu.o
+-
+-kqemu.o:
+- make -C $(KERNEL_PATH) SUBDIRS=`pwd` modules
+-
+-endif # !CONFIG_KBUILD26
+-
+-clean:
+- rm -f kqemu.o kqemu.ko kmod.o kqemu-mod.o kqemu.mod.c *~
+-
+-FILES=Makefile README LICENSE install.sh kmod.c kqemu.h kqemu-mod-i386.o \
+- kqemu-doc.texi kqemu-doc.html
+-VERSION=0.6.2
+-
+-tar:
+- cd .. ; tar zcvf /tmp/kqemu-$(VERSION).tar.gz $(addprefix kqemu/, $(FILES))
+-
+-# documentation
+-doc: kqemu-doc.html
+-
+-%.html: %.texi
+- texi2html -monolithic -number $<
+-
+-else
+-
+-ifeq ($(PATCHLEVEL),4)
+-# called from 2.4 kernel kbuild
+-
+-obj-m:= kqemu.o
+-kqemu-objs:= kmod.o kqemu-mod-i386.o
+-
+-include $(TOPDIR)/Rules.make
+-
+-kqemu.o: $(kqemu-objs)
+- $(LD) -r -o $@ $(kqemu-objs)
+-
+-else
+-# called from 2.6 kernel kbuild
+-
+-obj-m:= kqemu.o
+-kqemu-objs:= kmod.o kqemu-mod.o
+-
+-$(obj)/kqemu-mod.o: $(src)/kqemu-mod-i386.o
+- cp $< $@
+-endif
+-endif # PATCHLEVEL
++.include <bsd.kmod.mk>
diff --git a/emulators/qemu-devel/files/patch-fbsd b/emulators/qemu-devel/files/patch-fbsd
index dab1f93fc8a0..76e950045de7 100644
--- a/emulators/qemu-devel/files/patch-fbsd
+++ b/emulators/qemu-devel/files/patch-fbsd
@@ -8,14 +8,19 @@ Index: qemu/Makefile
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
-@@ -25,6 +25,9 @@
+@@ -21,10 +21,13 @@
+ ifdef CONFIG_WIN32
+ $(MAKE) -C kqemu -f Makefile.winnt
+ else
+- $(MAKE) -C kqemu
++ cd kqemu && $(BSD_MAKE)
endif
endif
+bsd/libmath.a:
+ ( cd bsd ; $(BSD_MAKE) CC=$(CC) )
+
- qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c
+ qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
@@ -33,6 +36,7 @@
@@ -26,6 +31,25 @@ Index: qemu/Makefile
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
$(MAKE) -C tests clean
+@@ -40,7 +44,7 @@
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+ ifdef CONFIG_KQEMU
+- $(MAKE) -C kqemu clean
++ cd kqemu && $(BSD_MAKE) clean
+ endif
+
+ distclean: clean
+@@ -73,9 +77,6 @@
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+-ifdef CONFIG_KQEMU
+- cd kqemu ; ./install.sh
+-endif
+
+ # various test targets
+ test speed test2: all
Index: qemu/Makefile.target
@@ -391,8 +391,8 @@
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
diff --git a/emulators/qemu-devel/files/patch-osdep.c b/emulators/qemu-devel/files/patch-osdep.c
new file mode 100644
index 000000000000..3d5382b50c51
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-osdep.c
@@ -0,0 +1,40 @@
+Index: qemu/osdep.c
+@@ -323,7 +323,9 @@
+
+ #elif defined(USE_KQEMU)
+
++#ifndef __FreeBSD__
+ #include <sys/vfs.h>
++#endif
+ #include <sys/mman.h>
+ #include <fcntl.h>
+
+@@ -334,6 +336,7 @@
+ const char *tmpdir;
+ char phys_ram_file[1024];
+ void *ptr;
++#ifndef __FreeBSD__
+ struct statfs stfs;
+
+ if (phys_ram_fd < 0) {
+@@ -389,12 +392,20 @@
+ }
+ unlink(phys_ram_file);
+ }
++#endif
+ size = (size + 4095) & ~4095;
++#ifndef __FreeBSD__
+ ftruncate(phys_ram_fd, phys_ram_size + size);
+ ptr = mmap(NULL,
+ size,
+ PROT_WRITE | PROT_READ, MAP_SHARED,
+ phys_ram_fd, phys_ram_size);
++#else
++ ptr = mmap(NULL,
++ size,
++ PROT_WRITE | PROT_READ, MAP_PRIVATE|MAP_ANON,
++ -1, 0);
++#endif
+ if (ptr == MAP_FAILED) {
+ fprintf(stderr, "Could not map physical memory\n");
+ exit(1);
diff --git a/emulators/qemu-devel/pkg-plist b/emulators/qemu-devel/pkg-plist
index 3ff1d2332248..129ae46415a7 100644
--- a/emulators/qemu-devel/pkg-plist
+++ b/emulators/qemu-devel/pkg-plist
@@ -49,3 +49,5 @@ share/qemu/keymaps/tr
@dirrm share/qemu/keymaps
@dirrm share/qemu
%%PORTDOCS%%@dirrm %%DOCSDIR%%
+@cwd /
+%%WITH_KQEMU%%%%KMODDIR%%/kqemu.ko
diff --git a/emulators/qemu/Makefile b/emulators/qemu/Makefile
index 6d1a7c1a4c54..5bec3cc93a84 100644
--- a/emulators/qemu/Makefile
+++ b/emulators/qemu/Makefile
@@ -6,10 +6,13 @@
#
PORTNAME= qemu
-PORTVERSION= 0.7.0
-POTREVISION= 1
+PORTVERSION= 0.7.0s.20050502
CATEGORIES= emulators
-MASTER_SITES= http://www.qemu.org/
+MASTER_SITES= http://www.qemu.org/ \
+ http://people.fruitsalad.org/nox/qemu/ \
+ http://dad-answers.com/qemu/
+DISTNAME= ${PORTNAME}-snapshot-2005-05-02_23
+EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX}
MAINTAINER= nox@jelal.kn-bremen.de
COMMENT= QEMU CPU Emulator
@@ -19,7 +22,13 @@ BUILD_DEPENDS+= texi2html:${PORTSDIR}/textproc/texi2html
RUN_DEPENDS+= ${LOCALBASE}/sbin/smbd:${PORTSDIR}/net/samba
.endif
+.if defined(WITH_KQEMU)
+DISTKQEMU= kqemu-0.6.2-1.tar.gz
+DISTFILES= ${EXTRACT_ONLY} ${DISTKQEMU}
+.endif
+
HAS_CONFIGURE= yes
+USE_BZIP2= yes
USE_GMAKE= yes
USE_GETOPT_LONG= yes
USE_SDL= sdl
@@ -29,6 +38,14 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC}
MAKE_ENV+= BSD_MAKE=${MAKE}
MAN1= qemu.1 qemu-img.1
ONLY_FOR_ARCHS= amd64 i386
+.if defined(WITH_KQEMU)
+NO_PACKAGE= Depends on kernel, and module not redistributable
+PLIST_SUB= WITH_KQEMU=""
+PLIST_SUB+= KMODDIR=${KMODDIR}
+EXTRA_PATCHES= ${FILESDIR}/kqemu-patch
+.else
+PLIST_SUB= WITH_KQEMU="@comment "
+.endif
# gcc34 (system cc on 5.x now) has problems with qemu on amd64
# (doesnt build target-i386/op.c), try the one in ports which is newer
@@ -47,19 +64,48 @@ USE_GCC= 3.4
USE_GCC= 3.4
.endif
+.if defined(WITH_KQEMU) && ${ARCH} != "i386"
+IGNORE= kqemu only supported on i386
+.endif
+
+.if defined(WITH_KQEMU) && !exists(${SRC_BASE}/sys/Makefile)
+IGNORE= kqemu requires kernel source to be installed
+.endif
+
pre-everything::
+.if !defined(WITH_KQEMU) && ${ARCH} == "i386"
+ @${ECHO_MSG} "Notice: you can build qemu with the (alpha!) kqemu accelerator kernel module"
+ @${ECHO_MSG} "by defining WITH_KQEMU."
+.endif
.if !defined(WITH_SAMBA) && !exists(${LOCALBASE}/sbin/smbd)
@${ECHO_MSG} "Notice: if you need qemu's -smb option (smb-export local dir to guest)"
@${ECHO_MSG} "then you also need samba, you can have this port install it by defining"
@${ECHO_MSG} "WITH_SAMBA."
.endif
+.if defined(WITH_KQEMU)
+post-extract:
+ @cd ${WRKSRC} && ${TAR} xfz ${_DISTDIR}/${DISTKQEMU}
+ @${CP} ${FILESDIR}/kmod_bsd.c ${WRKSRC}/kqemu
+.endif
+
pre-patch:
@for A in ${ONLY_FOR_ARCHS}; do \
${MKDIR} ${WRKSRC}/bsd/$$A; \
done
post-install:
+.if defined(WITH_KQEMU)
+ ${INSTALL_SCRIPT} ${WRKSRC}/kqemu/kqemu.ko ${KMODDIR}
+ if mount |${GREP} ^devfs >/dev/null ; then \
+ : ; \
+ else \
+ if [ ! -e /dev/kqemu ]; then\
+ mknod /dev/kqemu c 250 0 ; \
+ fi ; \
+ ${CHMOD} 666 /dev/kqemu ; \
+ fi
+.endif
@${CAT} ${PKGMESSAGE}
.include <bsd.port.post.mk>
diff --git a/emulators/qemu/distinfo b/emulators/qemu/distinfo
index a02ee0ccb2b1..5d4b1c2ede35 100644
--- a/emulators/qemu/distinfo
+++ b/emulators/qemu/distinfo
@@ -1,2 +1,4 @@
-MD5 (qemu-0.7.0.tar.gz) = 234e9ace03b00259bb57dc5a9c633056
-SIZE (qemu-0.7.0.tar.gz) = 1211802
+MD5 (qemu-snapshot-2005-05-02_23.tar.bz2) = b7d4115a68bf93a9ad2c0c64a0c59137
+SIZE (qemu-snapshot-2005-05-02_23.tar.bz2) = 1020482
+MD5 (kqemu-0.6.2-1.tar.gz) = c6bb3b40fb3d526d731eb0f1f9dee7ee
+SIZE (kqemu-0.6.2-1.tar.gz) = 21002
diff --git a/emulators/qemu/files/kmod_bsd.c b/emulators/qemu/files/kmod_bsd.c
new file mode 100644
index 000000000000..63e1cf5053d8
--- /dev/null
+++ b/emulators/qemu/files/kmod_bsd.c
@@ -0,0 +1,575 @@
+/*
+ * FreeBSD kernel wrapper for KQEMU
+ * Copyright (c) 2005 Antony T Curtis
+ *
+ * Based upon the Linux wrapper by Fabrice Bellard
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#if __FreeBSD_version < 500000
+#include <sys/buf.h>
+#endif
+#include <sys/uio.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#if __FreeBSD_version > 500000
+#include <sys/ktr.h>
+#include <sys/sched.h>
+#endif
+#include <sys/ioccom.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/module.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/stdarg.h>
+
+#define __KERNEL__
+
+#include "kqemu.h"
+
+static unsigned long cache_page(vm_offset_t paddr, caddr_t addr);
+static caddr_t find_page(vm_offset_t paddr, int free);
+
+static MALLOC_DEFINE(M_KQEMU, "KQEMU", "KQEMU Resources");
+
+struct pagecache {
+ caddr_t addr;
+};
+
+static struct pagecache **pagecache;
+#if __FreeBSD_version > 500000
+static struct mtx cache_lock;
+#endif
+
+static unsigned long cache_page(vm_offset_t paddr, caddr_t addr)
+{
+ unsigned long ppn = (unsigned long)(paddr >> PAGE_SHIFT);
+ int pci = (int)(ppn >> 10);
+ struct pagecache *cache;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!(cache = pagecache[pci])) {
+ if (!addr) {
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ cache = pagecache[pci] = (struct pagecache *)
+ kqemu_vmalloc(1024 * sizeof(struct pagecache));
+
+ memset(cache, 0, 1024 * sizeof(struct pagecache));
+ }
+ if (!addr) {
+ int i;
+ cache[ppn & 1023].addr = (caddr_t) 0;
+ for (i = 1023; i >= 0; i--, cache++)
+ if (cache->addr)
+ break;
+ if (i < 0) {
+ kqemu_vfree(pagecache[pci]);
+ pagecache[pci] = 0;
+ }
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ cache[ppn & 1023].addr = (caddr_t) (((unsigned long) addr) & ~PAGE_MASK);
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return ppn;
+}
+
+static caddr_t find_page(vm_offset_t paddr, int free)
+{
+ unsigned long ppn = (unsigned long)(paddr >> PAGE_SHIFT);
+ struct pagecache *cache;
+ caddr_t addr;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!(cache = pagecache[ppn >> 10])) {
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ return 0;
+ }
+ addr = (caddr_t)(((unsigned long)cache[ppn & 1023].addr)
+ | ((unsigned long)paddr & PAGE_MASK));
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ if (free && addr)
+ cache_page(paddr, 0);
+ return addr;
+}
+
+/* lock the page at virtual address 'user_addr' and return its
+ page index. Return -1 if error */
+unsigned long CDECL kqemu_lock_user_page(unsigned long user_addr)
+{
+ int rc;
+ caddr_t addr = (caddr_t) user_addr;
+ vm_page_t m;
+ vm_offset_t paddr;
+
+ /*kqemu_log("kqemu_lock_user_page(0x%08x)\n", addr);*/
+
+ rc = vm_fault_quick(addr, VM_PROT_READ|VM_PROT_WRITE);
+ if (rc < 0) {
+ /*kqemu_log("vm_fault_quick failed rc=%d\n",rc);*/
+ return -1;
+ }
+ paddr = vtophys(addr);
+ m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_wire(m);
+
+ return cache_page(paddr, addr);
+}
+
+void CDECL kqemu_unlock_user_page(unsigned long page_index)
+{
+ vm_page_t m;
+ vm_offset_t paddr;
+ /*kqemu_log("kqemu_unlock_user_page(0x%08x)\n",page_index);*/
+
+ paddr = (vm_offset_t)(page_index << PAGE_SHIFT);
+ m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_unwire(m, 1);
+ cache_page(paddr, 0);
+}
+
+unsigned long CDECL kqemu_alloc_zeroed_page(void)
+{
+ void *addr;
+ vm_offset_t paddr;
+
+ /*kqemu_log("kqemu_alloc_zeroed_page()\n");*/
+ addr = contigmalloc(PAGE_SIZE, M_KQEMU, M_WAITOK, 0, ~0ul, PAGE_SIZE, 0);
+ if (!addr) {
+ /*kqemu_log("contigmalloc failed\n");*/
+ return -1;
+ }
+ memset(addr, 0, PAGE_SIZE);
+ paddr = vtophys(addr);
+ return cache_page(paddr, addr);
+}
+
+void CDECL kqemu_free_page(unsigned long page_index)
+{
+ vm_offset_t paddr;
+ caddr_t addr;
+ /*kqemu_log("kqemu_free_page(0x%08x)\n", page_index);*/
+ paddr = (vm_offset_t) (page_index << PAGE_SHIFT);
+ if ((addr = find_page(paddr,1))) {
+ contigfree((void *) addr, PAGE_SIZE, M_KQEMU);
+ }
+}
+
+void * CDECL kqemu_page_kaddr(unsigned long page_index)
+{
+ vm_offset_t paddr;
+ /*kqemu_log("kqemu_page_kaddr(0x%08x)\n", page_index);*/
+ paddr = (vm_offset_t) (page_index << PAGE_SHIFT);
+ return (void *) find_page(paddr, 0);
+}
+
+/* contraint: each page of the vmalloced area must be in the first 4
+ GB of physical memory */
+void * CDECL kqemu_vmalloc(unsigned int size)
+{
+ /*kqemu_log("kqemu_vmalloc(0x%08x)\n", size);*/
+ return malloc(size, M_KQEMU, M_WAITOK);
+}
+
+void CDECL kqemu_vfree(void *ptr)
+{
+ /*kqemu_log("kqemu_vfree(0x%08x)\n", ptr);*/
+ return free(ptr, M_KQEMU);
+}
+
+unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr)
+{
+ caddr_t addr = (caddr_t)vaddr;
+ vm_offset_t paddr = vtophys(addr);
+ return cache_page(paddr, addr);
+}
+
+#if __FreeBSD_version < 500000
+static int
+curpriority_cmp(struct proc *p)
+{
+ int c_class, p_class;
+
+ c_class = RTP_PRIO_BASE(curproc->p_rtprio.type);
+ p_class = RTP_PRIO_BASE(p->p_rtprio.type);
+ if (p_class != c_class)
+ return (p_class - c_class);
+ if (p_class == RTP_PRIO_NORMAL)
+ return (((int)p->p_priority - (int)curpriority) / PPQ);
+ return ((int)p->p_rtprio.prio - (int)curproc->p_rtprio.prio);
+}
+
+/* return TRUE if a signal is pending (i.e. the guest must stop
+ execution) */
+int CDECL kqemu_schedule(void)
+{
+ struct proc *p = curproc;
+ if (curpriority_cmp(p) > 0) {
+ int s = splhigh();
+ p->p_priority = MAXPRI;
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nvcsw++;
+ mi_switch();
+ splx(s);
+ }
+ return issignal(curproc) != 0;
+}
+
+#else
+
+/* return TRUE if a signal is pending (i.e. the guest must stop
+ execution) */
+int CDECL kqemu_schedule(void)
+{
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ int rc;
+ mtx_lock_spin(&sched_lock);
+ sched_prio(td, td->td_ksegrp->kg_user_pri);
+ mi_switch(SW_INVOL, NULL);
+ mtx_unlock_spin(&sched_lock);
+
+ PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ rc = cursig(td);
+ mtx_unlock(&p->p_sigacts->ps_mtx);
+ PROC_UNLOCK(p);
+ return rc;
+}
+
+#endif
+
+
+static char log_buf[4096];
+
+void CDECL kqemu_log(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(log_buf, sizeof(log_buf), fmt, ap);
+ printf("kqemu: %s", log_buf);
+ va_end(ap);
+}
+
+/*********************************************************/
+
+
+#define KQEMU_MAX_INSTANCES 4
+
+struct kqemu_instance {
+ struct kqemu_state *state;
+};
+
+static int kqemu_ref_count = 0;
+static int max_locked_pages;
+#if __FreeBSD_version < 500000
+static dev_t kqemu_dev;
+#else
+static struct cdev *kqemu_dev;
+#endif
+
+
+static d_open_t kqemu_open;
+static d_close_t kqemu_close;
+static d_ioctl_t kqemu_ioctl;
+
+static struct cdevsw kqemu_cdevsw = {
+#if __FreeBSD_version < 500000
+ /* open */ kqemu_open,
+ /* close */ kqemu_close,
+ /* read */ noread,
+ /* write */ nowrite,
+ /* ioctl */ kqemu_ioctl,
+ /* poll */ nopoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "kqemu",
+ /* maj */ KQEMU_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* bmaj */ -1
+#else
+ .d_version = D_VERSION,
+ .d_open = kqemu_open,
+ .d_close = kqemu_close,
+ .d_ioctl = kqemu_ioctl,
+ .d_name = "kqemu",
+#endif
+};
+
+int
+#if __FreeBSD_version < 500000
+kqemu_open(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+#else
+kqemu_open(dev, flags, fmt, td)
+ struct cdev *dev;
+ int flags, fmt;
+ struct thread *td;
+{
+ struct proc *p = td->td_proc;
+#endif
+ struct kqemu_instance *ks;
+
+ if (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES)
+ return(EBUSY);
+
+ if ((flags & (FREAD|FWRITE)) == FREAD)
+ return(EPERM);
+
+ ks = (struct kqemu_instance *) malloc(sizeof(*ks), M_KQEMU, M_WAITOK);
+ if (ks == NULL)
+ return(ENOMEM);
+ memset(ks, 0, sizeof *ks);
+
+ dev->si_drv1 = ks;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ kqemu_ref_count++;
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ kqemu_log("opened by pid=%d\n", p->p_pid);
+ return(0);
+}
+
+int
+#if __FreeBSD_version < 500000
+kqemu_close(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+#else
+kqemu_close(dev, flags, fmt, td)
+ struct cdev *dev;
+ int flags, fmt;
+ struct thread *td;
+{
+ struct proc *p = td->td_proc;
+#endif
+ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
+
+ if (ks->state) {
+ kqemu_delete(ks->state);
+ ks->state = NULL;
+ }
+
+ free(ks, M_KQEMU);
+ dev->si_drv1 = NULL;
+#if __FreeBSD_version > 500000
+ mtx_lock_spin(&cache_lock);
+#endif
+ if (!--kqemu_ref_count) {
+ int i;
+ for (i = 1023; i >= 0; i--)
+ kqemu_vfree(pagecache[i]);
+ memset(pagecache, 0, 1024 * sizeof(void *));
+ }
+#if __FreeBSD_version > 500000
+ mtx_unlock_spin(&cache_lock);
+#endif
+ kqemu_log("closed by pid=%d\n", p->p_pid);
+ return(0);
+}
+
+int
+#if __FreeBSD_version < 500000
+kqemu_ioctl(dev, cmd, cmdarg, flags, p)
+ dev_t dev;
+ unsigned long cmd;
+ caddr_t cmdarg;
+ int flags;
+ struct proc *p;
+{
+#else
+kqemu_ioctl(dev, cmd, cmdarg, flags, td)
+ struct cdev *dev;
+ unsigned long cmd;
+ caddr_t cmdarg;
+ int flags;
+ struct thread *td;
+{
+#endif
+ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
+ struct kqemu_state *s = ks->state;
+ long ret;
+ int error = 0;
+
+ switch (cmd) {
+ case KQEMU_INIT:
+ /*kqemu_log("KQEMU_INIT data=0x%08x\n",cmdarg);*/
+ {
+ if (s) {
+ error = (EIO);
+ break;
+ }
+
+ if (!(s = kqemu_init((struct kqemu_init *)cmdarg, max_locked_pages))) {
+ error = (ENOMEM);
+ break;
+ }
+
+ ks->state = s;
+ break;
+ }
+ case KQEMU_EXEC:
+ /*kqemu_log("KQEMU_EXEC data=0x%08x\n",cmdarg);*/
+ {
+ struct kqemu_cpu_state *ctx;
+
+ if (!s) {
+ error = (EIO);
+ break;
+ }
+
+ ctx = kqemu_get_cpu_state(s);
+ memcpy((void *)ctx, (void *)cmdarg, sizeof(struct kqemu_cpu_state));
+
+ ret = kqemu_exec(s);
+#if __FreeBSD_version > 500000
+ td->td_retval[0] = ret;
+#else
+ p->p_retval[0] = ret;
+#endif
+ memcpy((void *)cmdarg, (void *)ctx, sizeof(struct kqemu_cpu_state));
+
+ break;
+ }
+ case KQEMU_GET_VERSION:
+ /*kqemu_log("KQEMU_GET_VERSION data=0x%08x\n",cmdarg);*/
+ {
+ *(int *)cmdarg = KQEMU_VERSION;
+ break;
+ }
+ default:
+ /*kqemu_log("ioctl unknown 0x%08x\n",cmd);*/
+ error = (ENXIO);
+ }
+ return(error);
+}
+
+static int
+init_module(void)
+{
+#if __FreeBSD_version < 500000
+ int rc;
+#endif
+ printf("QEMU Accelerator Module version %d.%d.%d, Copyright (c) 2005 Fabrice Bellard\n"
+ "FreeBSD wrapper port, Copyright (c) 2005 Antony T Curtis\n"
+ "This is a proprietary product. Read the LICENSE file for more information\n"
+ "Redistribution of this module is prohibited without authorization\n",
+ (KQEMU_VERSION >> 16),
+ (KQEMU_VERSION >> 8) & 0xff,
+ (KQEMU_VERSION) & 0xff);
+
+ if (!(pagecache = (struct pagecache **)
+ kqemu_vmalloc(1024 * sizeof(void *))))
+ return(ENOMEM);
+ memset(pagecache, 0, 1024 * sizeof(void *));
+
+#if __FreeBSD_version > 500000
+ mtx_init(&cache_lock, "pagecache lock", NULL, MTX_SPIN);
+#endif
+
+ max_locked_pages = physmem / (2 * KQEMU_MAX_INSTANCES);
+ if (max_locked_pages > 32768)
+ max_locked_pages = 32768;
+
+#if __FreeBSD_version < 500000
+ if ((rc = cdevsw_add(&kqemu_cdevsw))) {
+ kqemu_log("error registering cdevsw, rc=%d\n", rc);
+ return(ENOENT);
+ }
+#endif
+
+ kqemu_dev = make_dev(&kqemu_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, "kqemu");
+
+ kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
+ KQEMU_MAX_INSTANCES, max_locked_pages * 4);
+
+ kqemu_ref_count = 0;
+ return 0;
+}
+
+static void
+cleanup_module(void)
+{
+#if __FreeBSD_version < 500000
+ int rc;
+#endif
+
+ destroy_dev(kqemu_dev);
+#if __FreeBSD_version < 500000
+ if ((rc = cdevsw_remove(&kqemu_cdevsw)))
+ kqemu_log("error unregistering, rc=%d\n", rc);
+#endif
+
+ kqemu_vfree(pagecache);
+ pagecache = 0;
+}
+
+static int
+kqemu_modevent(module_t mod, int type, void *data)
+{
+ int err = 0;
+ switch (type) {
+ case MOD_LOAD:
+ err = init_module();
+ break;
+ case MOD_UNLOAD:
+ if (kqemu_ref_count > 0) {
+ err = EBUSY;
+ break;
+ }
+ /* fall through */
+ case MOD_SHUTDOWN:
+ cleanup_module();
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+static moduledata_t kqemu_mod = {
+ "kqemu_driver",
+ kqemu_modevent,
+ NULL
+};
+
+DECLARE_MODULE(kqemu, kqemu_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+
diff --git a/emulators/qemu/files/kqemu-patch b/emulators/qemu/files/kqemu-patch
new file mode 100644
index 000000000000..ba82ba368808
--- /dev/null
+++ b/emulators/qemu/files/kqemu-patch
@@ -0,0 +1,68 @@
+Index: qemu/kqemu/Makefile
+@@ -1,62 +1,5 @@
+-ifeq ($(PATCHLEVEL),)
+-# compile in kqemu directory
++KMOD= kqemu
++SRCS= kmod_bsd.c
++OBJS= kqemu-mod-i386.o
+
+--include ../config-host.mak
+-
+-ifdef CONFIG_KBUILD26
+-# 2.6 build
+-
+-all: kqemu.ko
+-
+-kqemu.ko:
+- make -C $(KERNEL_PATH) M=`pwd` modules
+-
+-else
+-# 2.4 build
+-
+-all: kqemu.o
+-
+-kqemu.o:
+- make -C $(KERNEL_PATH) SUBDIRS=`pwd` modules
+-
+-endif # !CONFIG_KBUILD26
+-
+-clean:
+- rm -f kqemu.o kqemu.ko kmod.o kqemu-mod.o kqemu.mod.c *~
+-
+-FILES=Makefile README LICENSE install.sh kmod.c kqemu.h kqemu-mod-i386.o \
+- kqemu-doc.texi kqemu-doc.html
+-VERSION=0.6.2
+-
+-tar:
+- cd .. ; tar zcvf /tmp/kqemu-$(VERSION).tar.gz $(addprefix kqemu/, $(FILES))
+-
+-# documentation
+-doc: kqemu-doc.html
+-
+-%.html: %.texi
+- texi2html -monolithic -number $<
+-
+-else
+-
+-ifeq ($(PATCHLEVEL),4)
+-# called from 2.4 kernel kbuild
+-
+-obj-m:= kqemu.o
+-kqemu-objs:= kmod.o kqemu-mod-i386.o
+-
+-include $(TOPDIR)/Rules.make
+-
+-kqemu.o: $(kqemu-objs)
+- $(LD) -r -o $@ $(kqemu-objs)
+-
+-else
+-# called from 2.6 kernel kbuild
+-
+-obj-m:= kqemu.o
+-kqemu-objs:= kmod.o kqemu-mod.o
+-
+-$(obj)/kqemu-mod.o: $(src)/kqemu-mod-i386.o
+- cp $< $@
+-endif
+-endif # PATCHLEVEL
++.include <bsd.kmod.mk>
diff --git a/emulators/qemu/files/patch-fbsd b/emulators/qemu/files/patch-fbsd
index dab1f93fc8a0..76e950045de7 100644
--- a/emulators/qemu/files/patch-fbsd
+++ b/emulators/qemu/files/patch-fbsd
@@ -8,14 +8,19 @@ Index: qemu/Makefile
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
-@@ -25,6 +25,9 @@
+@@ -21,10 +21,13 @@
+ ifdef CONFIG_WIN32
+ $(MAKE) -C kqemu -f Makefile.winnt
+ else
+- $(MAKE) -C kqemu
++ cd kqemu && $(BSD_MAKE)
endif
endif
+bsd/libmath.a:
+ ( cd bsd ; $(BSD_MAKE) CC=$(CC) )
+
- qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c
+ qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
@@ -33,6 +36,7 @@
@@ -26,6 +31,25 @@ Index: qemu/Makefile
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
$(MAKE) -C tests clean
+@@ -40,7 +44,7 @@
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+ ifdef CONFIG_KQEMU
+- $(MAKE) -C kqemu clean
++ cd kqemu && $(BSD_MAKE) clean
+ endif
+
+ distclean: clean
+@@ -73,9 +77,6 @@
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+-ifdef CONFIG_KQEMU
+- cd kqemu ; ./install.sh
+-endif
+
+ # various test targets
+ test speed test2: all
Index: qemu/Makefile.target
@@ -391,8 +391,8 @@
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
diff --git a/emulators/qemu/files/patch-osdep.c b/emulators/qemu/files/patch-osdep.c
new file mode 100644
index 000000000000..3d5382b50c51
--- /dev/null
+++ b/emulators/qemu/files/patch-osdep.c
@@ -0,0 +1,40 @@
+Index: qemu/osdep.c
+@@ -323,7 +323,9 @@
+
+ #elif defined(USE_KQEMU)
+
++#ifndef __FreeBSD__
+ #include <sys/vfs.h>
++#endif
+ #include <sys/mman.h>
+ #include <fcntl.h>
+
+@@ -334,6 +336,7 @@
+ const char *tmpdir;
+ char phys_ram_file[1024];
+ void *ptr;
++#ifndef __FreeBSD__
+ struct statfs stfs;
+
+ if (phys_ram_fd < 0) {
+@@ -389,12 +392,20 @@
+ }
+ unlink(phys_ram_file);
+ }
++#endif
+ size = (size + 4095) & ~4095;
++#ifndef __FreeBSD__
+ ftruncate(phys_ram_fd, phys_ram_size + size);
+ ptr = mmap(NULL,
+ size,
+ PROT_WRITE | PROT_READ, MAP_SHARED,
+ phys_ram_fd, phys_ram_size);
++#else
++ ptr = mmap(NULL,
++ size,
++ PROT_WRITE | PROT_READ, MAP_PRIVATE|MAP_ANON,
++ -1, 0);
++#endif
+ if (ptr == MAP_FAILED) {
+ fprintf(stderr, "Could not map physical memory\n");
+ exit(1);
diff --git a/emulators/qemu/pkg-plist b/emulators/qemu/pkg-plist
index 3ff1d2332248..129ae46415a7 100644
--- a/emulators/qemu/pkg-plist
+++ b/emulators/qemu/pkg-plist
@@ -49,3 +49,5 @@ share/qemu/keymaps/tr
@dirrm share/qemu/keymaps
@dirrm share/qemu
%%PORTDOCS%%@dirrm %%DOCSDIR%%
+@cwd /
+%%WITH_KQEMU%%%%KMODDIR%%/kqemu.ko