summaryrefslogtreecommitdiff
path: root/emulators
diff options
context:
space:
mode:
authorNorikatsu Shigemura <nork@FreeBSD.org>2005-10-31 13:42:20 +0000
committerNorikatsu Shigemura <nork@FreeBSD.org>2005-10-31 13:42:20 +0000
commit7fcc885a6cad104b17a7b7e1fcf826edaa580e7c (patch)
tree5b892aa3e037e758890aaf9c55850f453391e1b4 /emulators
parents/one/you/ to make it sound better. (diff)
Add kqemu 0.7.2, is a kernel module to accelerate
QEMU CPU Emulator. WWW: http://fabrice.bellard.free.fr/qemu/qemu-accel.html Discussed with: Juergen Lock <nox@jelal.kn-bremen.de> Reviewed by: Juergen Lock <nox@jelal.kn-bremen.de>
Notes
Notes: svn path=/head/; revision=146829
Diffstat (limited to 'emulators')
-rw-r--r--emulators/Makefile1
-rw-r--r--emulators/kqemu-kmod-devel/Makefile47
-rw-r--r--emulators/kqemu-kmod-devel/distinfo2
-rw-r--r--emulators/kqemu-kmod-devel/files/patch-Makefile.freebsd10
-rw-r--r--emulators/kqemu-kmod-devel/files/patch-kqemu-freebsd.c505
-rw-r--r--emulators/kqemu-kmod-devel/pkg-descr3
-rw-r--r--emulators/kqemu-kmod/Makefile47
-rw-r--r--emulators/kqemu-kmod/distinfo2
-rw-r--r--emulators/kqemu-kmod/files/patch-Makefile.freebsd10
-rw-r--r--emulators/kqemu-kmod/files/patch-kqemu-freebsd.c505
-rw-r--r--emulators/kqemu-kmod/pkg-descr3
11 files changed, 1135 insertions, 0 deletions
diff --git a/emulators/Makefile b/emulators/Makefile
index 598961bdbdbf..331ec7d1602f 100644
--- a/emulators/Makefile
+++ b/emulators/Makefile
@@ -45,6 +45,7 @@
SUBDIR += its
SUBDIR += klh10
SUBDIR += kmamerun
+ SUBDIR += kqemu-kmod
SUBDIR += lib765
SUBDIR += libspectrum
SUBDIR += libvm68k
diff --git a/emulators/kqemu-kmod-devel/Makefile b/emulators/kqemu-kmod-devel/Makefile
new file mode 100644
index 000000000000..8c98a97ac26b
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/Makefile
@@ -0,0 +1,47 @@
+# New ports collection makefile for: kqemu-kmod
+# Date created: 2005/10/25
+# Whom: nork@FreeBSD.org
+#
+# $FreeBSD$
+#
+
+PORTNAME= kqemu
+PORTVERSION= 0.7.2
+CATEGORIES= emulators
+MASTER_SITES= http://fabrice.bellard.free.fr/qemu/
+PKGNAMESUFFIX= -kmod
+DIST_SUBDIR= kqemu
+
+MAINTAINER= nork@FreeBSD.org
+COMMENT= Kernel Acceralator for QEMU CPU Emulator
+
+ONLY_FOR_ARCHS= i386 amd64
+NO_PACKAGE= "Depends on kernel, and module not redistributable"
+
+PLIST_FILES= "include/kqemu/kqemu.h"
+PLIST_FILES+= "@dirrm include/kqemu"
+PLIST_FILES+= "@cwd /"
+PLIST_FILES+= ${KMODDIR:C,^/,,}/kqemu.ko
+
+WRKSRC= ${WRKDIR}/${PORTNAME}
+MAKEFILE= Makefile.freebsd
+
+.include <bsd.port.pre.mk>
+
+.if !exists(${SRC_BASE}/sys/Makefile)
+IGNORE= kqemu requires kernel source to be installed
+.endif
+
+post-install:
+ @${MKDIR} ${PREFIX}/include/kqemu
+ @${INSTALL_DATA} ${WRKSRC}/kqemu.h ${PREFIX}/include/kqemu
+ 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
+
+.include <bsd.port.post.mk>
diff --git a/emulators/kqemu-kmod-devel/distinfo b/emulators/kqemu-kmod-devel/distinfo
new file mode 100644
index 000000000000..9d0296fa02c6
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/distinfo
@@ -0,0 +1,2 @@
+MD5 (kqemu/kqemu-0.7.2.tar.gz) = 02cfdecda90458d6393781496ec6b48b
+SIZE (kqemu/kqemu-0.7.2.tar.gz) = 79314
diff --git a/emulators/kqemu-kmod-devel/files/patch-Makefile.freebsd b/emulators/kqemu-kmod-devel/files/patch-Makefile.freebsd
new file mode 100644
index 000000000000..b75420fa0cc7
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/patch-Makefile.freebsd
@@ -0,0 +1,10 @@
+--- Makefile.freebsd.orig Fri Jul 29 06:37:06 2005
++++ Makefile.freebsd Tue Oct 25 21:08:43 2005
+@@ -5,6 +5,7 @@
+ .elif ${MACHINE_ARCH} == "amd64"
+ OBJS= kqemu-mod-x86_64.o
+ .endif
++CC= cc
+ WERROR=
+
+ .include <bsd.kmod.mk>
diff --git a/emulators/kqemu-kmod-devel/files/patch-kqemu-freebsd.c b/emulators/kqemu-kmod-devel/files/patch-kqemu-freebsd.c
new file mode 100644
index 000000000000..27eb0420a4ff
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/patch-kqemu-freebsd.c
@@ -0,0 +1,505 @@
+--- kqemu-freebsd.c.orig Mon Aug 15 01:34:06 2005
++++ kqemu-freebsd.c Tue Oct 25 21:08:43 2005
+@@ -3,32 +3,55 @@
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/conf.h>
++#include <sys/ctype.h>
++#include <sys/fcntl.h>
+ #include <sys/ioccom.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
++#if __FreeBSD_version >= 500000
+ #include <sys/mutex.h>
++#endif
+ #include <sys/proc.h>
++#include <sys/resourcevar.h>
++#if __FreeBSD_version >= 500000
+ #include <sys/sched.h>
++#endif
+ #include <sys/signalvar.h>
+ #include <sys/kernel.h>
++#include <sys/sysctl.h>
++#include <sys/uio.h>
++#if __FreeBSD_version < 500000
++#include <sys/buf.h>
++#endif
++
+ #include <vm/vm.h>
+ #include <vm/vm_param.h>
+ #include <vm/vm_extern.h>
+ #include <vm/pmap.h>
+ #include <vm/vm_map.h>
+ #include <vm/vm_kern.h>
++#include <vm/vm_page.h>
++
+ #include <machine/vmparam.h>
+ #include <machine/stdarg.h>
+
+ #include "kqemu-kernel.h"
+
++#ifndef KQEMU_MAJOR
++#define KQEMU_MAJOR 250
++#endif
++
+ MALLOC_DECLARE(M_KQEMU);
+ MALLOC_DEFINE(M_KQEMU, "kqemu", "kqemu buffers");
+
++int kqemu_debug;
++SYSCTL_INT(_debug, OID_AUTO, kqemu_debug, CTLFLAG_RW, &kqemu_debug, 0,
++ "kqemu debug flag");
++
+ #define USER_BASE 0x1000
+
+ /* lock the page at virtual address 'user_addr' and return its
+- physical page index. Return -1 if error */
++ physical page index. Return NULL if error */
+ struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
+ unsigned long user_addr)
+ {
+@@ -37,14 +60,18 @@
+ vm_paddr_t pa = 0;
+ int ret;
+ pmap_t pmap;
++#if __FreeBSD_version >= 500000
+ ret = vm_map_wire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
++#else
++ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, FALSE);
++#endif
+ if (ret != KERN_SUCCESS) {
+- printf("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret);
++ kqemu_log("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret);
+ return NULL;
+ }
+ pmap = vm_map_pmap(&vm->vm_map);
+ pa = pmap_extract(pmap, va);
+- // printf("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa);
++ /* kqemu_log("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa); */
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_user_page *)va;
+ }
+@@ -54,12 +81,16 @@
+ struct vmspace *vm = curproc->p_vmspace;
+ vm_offset_t va;
+ int ret;
+- // printf("kqemu_unlock_user_page(%08lx)\n", page_index);
++ /* kqemu_log("kqemu_unlock_user_page(%08lx)\n", page_index); */
+ va = (vm_offset_t)page;
++#if __FreeBSD_version >= 500000
+ ret = vm_map_unwire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
++#else
++ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, TRUE);
++#endif
+ #if 0
+ if (ret != KERN_SUCCESS) {
+- printf("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret);
++ kqemu_log("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret);
+ }
+ #endif
+ }
+@@ -76,20 +107,21 @@
+
+ va = kmem_alloc(kernel_map, PAGE_SIZE);
+ if (va == 0) {
+- printf("kqemu_alloc_zeroed_page: NULL\n");
+- return -1;
++ kqemu_log("kqemu_alloc_zeroed_page: NULL\n");
++ return NULL;
+ }
+ pmap = vm_map_pmap(kernel_map);
+ pa = pmap_extract(pmap, va);
+- // printf("kqemu_alloc_zeroed_page: %08x\n", pa);
++ /* kqemu_log("kqemu_alloc_zeroed_page: %08x\n", pa); */
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_page *)va;
+ }
+
+ void CDECL kqemu_free_page(struct kqemu_page *page)
+ {
+- // printf("kqemu_free_page(%08lx)\n", page_index);
+- /* XXX: do it */
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_free_page(%p)\n", page);
++ kmem_free(kernel_map, (vm_offset_t) page, PAGE_SIZE);
+ }
+
+ /* return kernel address of the physical page page_index */
+@@ -103,42 +135,29 @@
+ GB of physical memory */
+ void * CDECL kqemu_vmalloc(unsigned int size)
+ {
+- struct vmspace *vm = curproc->p_vmspace;
+- vm_offset_t va = USER_BASE;
+- int rv;
+- if (size % PAGE_SIZE != 0) {
+- printf("kqemu_vmalloc(%d) not a multiple of page size\n", size);
+- return NULL;
+- }
+- rv = vm_map_find(&vm->vm_map, NULL, 0, &va, size, 1,
+- VM_PROT_ALL, VM_PROT_ALL, 0);
+- if (rv != KERN_SUCCESS) {
+- printf("kqemu_vmalloc(%d) failed rv=%d\n", size, rv);
+- return NULL;
+- }
+- printf("kqemu_vmalloc(%d): %08x\n", size, va);
+- return (void *)va;
++ void *ptr = malloc(size, M_KQEMU, M_WAITOK);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vmalloc(%d): %p\n", size, ptr);
++ return ptr;
+ }
+
+ void CDECL kqemu_vfree(void *ptr)
+ {
+- printf("kqemu_vfree(%p)\n", ptr);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vfree(%p)\n", ptr);
++ free(ptr, M_KQEMU);
+ }
+
+ /* return the physical page index for a given virtual page */
+ unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr)
+ {
+- struct vmspace *vm = curproc->p_vmspace;
+- vm_paddr_t pa;
+- pmap_t pmap;
+-
+- pmap = vm_map_pmap(&vm->vm_map);
+- pa = pmap_extract(pmap, (vm_offset_t)vaddr);
++ vm_paddr_t pa = vtophys(vaddr);
+ if (pa == 0) {
+- printf("kqemu_vmalloc_to_phys(%p)->error\n", vaddr);
++ kqemu_log("kqemu_vmalloc_to_phys(%p)->error\n", vaddr);
+ return -1;
+ }
+- printf("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa);
+ return pa >> PAGE_SHIFT;
+ }
+
+@@ -154,16 +173,48 @@
+ {
+ }
+
++#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)
+ {
+- // printf("kqemu_schedule\n");
++ /* kqemu_log("kqemu_schedule\n"); */
+ mtx_lock_spin(&sched_lock);
+ mi_switch(SW_VOL, NULL);
+ mtx_unlock_spin(&sched_lock);
+ return SIGPENDING(curthread);
+ }
++#endif
+
+ static char log_buf[4096];
+
+@@ -176,47 +227,159 @@
+ va_end(ap);
+ }
+
++#define KQEMU_MAX_INSTANCES 4
++
+ struct kqemu_instance {
+- // struct semaphore sem;
++#if __FreeBSD_version >= 500000
++ TAILQ_ENTRY(kqemu_instance) kqemu_ent;
++ struct cdev *kqemu_dev;
++#endif
++ /* struct semaphore sem; */
+ 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 clonedevs *kqemuclones;
++static TAILQ_HEAD(,kqemu_instance) kqemuhead = TAILQ_HEAD_INITIALIZER(kqemuhead);
++static eventhandler_tag clonetag;
++#endif
++
+ static d_close_t kqemu_close;
+ static d_open_t kqemu_open;
+ 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_flags = D_NEEDGIANT,
+ .d_open = kqemu_open,
+ .d_ioctl = kqemu_ioctl,
+ .d_close = kqemu_close,
+ .d_name = "kqemu"
++#endif
+ };
+
+-/* For use with make_dev(9)/destroy_dev(9). */
+-static struct cdev *kqemu_dev;
++#if __FreeBSD_version >= 500000
++static void
++#if __FreeBSD_version >= 600034
++kqemu_clone(void *arg, struct ucred *cred, char *name, int namelen,
++struct cdev **dev)
++#else
++kqemu_clone(void *arg, char *name, int namelen, struct cdev **dev)
++#endif
++{
++ int unit, r;
++ if (*dev != NULL)
++ return;
++
++ if (strcmp(name, "kqemu") == 0)
++ unit = -1;
++ else if (dev_stdclone(name, NULL, "kqemu", &unit) != 1)
++ return; /* Bad name */
++ if (unit != -1 && unit > KQEMU_MAX_INSTANCES)
++ return;
++
++ r = clone_create(&kqemuclones, &kqemu_cdevsw, &unit, dev, 0);
++ if (r) {
++ *dev = make_dev(&kqemu_cdevsw, unit2minor(unit),
++ UID_ROOT, GID_WHEEL, 0660, "kqemu%d", unit);
++ if (*dev != NULL) {
++ (*dev)->si_flags |= SI_CHEAPCLONE;
++ }
++ }
++}
++#endif
++
++static void kqemu_destroy(struct kqemu_instance *ks)
++{
++#if __FreeBSD_version >= 500000
++ struct cdev *dev = ks->kqemu_dev;
++#endif
++
++ if (ks->state) {
++ kqemu_delete(ks->state);
++ ks->state = NULL;
++ }
++
++#if __FreeBSD_version >= 500000
++ dev->si_drv1 = NULL;
++ TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent);
++ destroy_dev(dev);
++#endif
++ free(ks, M_KQEMU);
++ --kqemu_ref_count;
++}
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_open(dev_t dev, int flags, int fmt __unused, struct proc *p)
++{
++#else
+ kqemu_open(struct cdev *dev, int flags, int fmt __unused,
+ struct thread *td)
+ {
++ struct proc *p = td->td_proc;
++#endif
+ struct kqemu_instance *ks;
++
++#if __FreeBSD_version >= 500000
++ if (kqemu_ref_count >= KQEMU_MAX_INSTANCES)
++#else
++ if (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES)
++#endif
++ return(EBUSY);
++
++ if ((flags & (FREAD|FWRITE)) == FREAD)
++ return(EPERM);
++
+ ks = malloc(sizeof(struct kqemu_instance), M_KQEMU, M_WAITOK);
+ if (ks == NULL) {
+- printf("malloc failed\n");
++ kqemu_log("malloc failed\n");
+ return ENOMEM;
+ }
+- ks->state = NULL;
++ memset(ks, 0, sizeof *ks);
++#if __FreeBSD_version >= 500000
++ ks->kqemu_dev = dev;
++ TAILQ_INSERT_TAIL(&kqemuhead, ks, kqemu_ent);
++#endif
++ kqemu_ref_count++;
++
+ dev->si_drv1 = ks;
++ if (kqemu_debug > 0)
++ kqemu_log("opened by pid=%d\n", p->p_pid);
+ return 0;
+ }
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_ioctl(dev_t dev, u_long cmd, caddr_t addr,
++ int flags __unused, struct proc *p)
++#else
+ kqemu_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
+ int flags __unused, struct thread *td)
++#endif
+ {
+ int error = 0;
+ int ret;
+@@ -231,8 +394,9 @@
+ break;
+ }
+ d1 = *(struct kqemu_init *)addr;
+- printf("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size);
+- s = kqemu_init(d, 16000);
++ if (kqemu_debug > 0)
++ kqemu_log("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size);
++ s = kqemu_init(d, max_locked_pages);
+ if (s == NULL) {
+ error = ENOMEM;
+ break;
+@@ -248,9 +412,16 @@
+ }
+ ctx = kqemu_get_cpu_state(s);
+ *ctx = *(struct kqemu_cpu_state *)addr;
++#if __FreeBSD_version >= 500000
+ DROP_GIANT();
++#endif
+ ret = kqemu_exec(s);
++#if __FreeBSD_version >= 500000
+ PICKUP_GIANT();
++ td->td_retval[0] = ret;
++#else
++ p->p_retval[0] = ret;
++#endif
+ *(struct kqemu_cpu_state *)addr = *ctx;
+ break;
+ }
+@@ -265,10 +436,22 @@
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_close(dev_t dev, int flags, int fmt __unused, struct proc *p)
++{
++#else
+ kqemu_close(struct cdev *dev __unused, int flags, int fmt __unused,
+ struct thread *td)
+ {
+- return 0;
++ struct proc *p = td->td_proc;
++#endif
++ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
++
++ kqemu_destroy(ks);
++
++ if (kqemu_debug > 0)
++ kqemu_log("closed by pid=%d\n", p->p_pid);
++ return 0;
+ }
+
+ /* ARGSUSED */
+@@ -276,15 +459,55 @@
+ kqemu_modevent(module_t mod __unused, int type, void *data __unused)
+ {
+ int error = 0;
++#if __FreeBSD_version < 500000
++ int rc;
++#else
++ struct kqemu_instance *ks;
++#endif
+
+ switch (type) {
+ case MOD_LOAD:
+ printf("kqemu version 0x%08x\n", KQEMU_VERSION);
++ 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);
++ error = ENOENT;
++ break;
++ }
+ kqemu_dev = make_dev(&kqemu_cdevsw, 0,
+- UID_ROOT, GID_WHEEL, 0666, "kqemu");
++ UID_ROOT, GID_WHEEL, 0660, "kqemu");
++#else
++ clone_setup(&kqemuclones);
++ clonetag = EVENTHANDLER_REGISTER(dev_clone, kqemu_clone, 0, 1000);
++ if (!clonetag) {
++ error = ENOMEM;
++ break;
++ }
++#endif
++ kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
++ KQEMU_MAX_INSTANCES, max_locked_pages * 4);
++
++ kqemu_ref_count = 0;
+ break;
+ case MOD_UNLOAD:
++ if (kqemu_ref_count > 0) {
++ error = EBUSY;
++ break;
++ }
++#if __FreeBSD_version < 500000
+ destroy_dev(kqemu_dev);
++ if ((rc = cdevsw_remove(&kqemu_cdevsw)))
++ kqemu_log("error unregistering, rc=%d\n", rc);
++#else
++ EVENTHANDLER_DEREGISTER(dev_clone, clonetag);
++ while ((ks = TAILQ_FIRST(&kqemuhead)) != NULL) {
++ kqemu_destroy(ks);
++ }
++ clone_cleanup(&kqemuclones);
++#endif
+ break;
+ case MOD_SHUTDOWN:
+ break;
diff --git a/emulators/kqemu-kmod-devel/pkg-descr b/emulators/kqemu-kmod-devel/pkg-descr
new file mode 100644
index 000000000000..d340d3bb1f4b
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/pkg-descr
@@ -0,0 +1,3 @@
+KQEMU is a qemu accelerator kernel module on x86/amd64.
+
+WWW: http://fabrice.bellard.free.fr/qemu/qemu-accel.html
diff --git a/emulators/kqemu-kmod/Makefile b/emulators/kqemu-kmod/Makefile
new file mode 100644
index 000000000000..8c98a97ac26b
--- /dev/null
+++ b/emulators/kqemu-kmod/Makefile
@@ -0,0 +1,47 @@
+# New ports collection makefile for: kqemu-kmod
+# Date created: 2005/10/25
+# Whom: nork@FreeBSD.org
+#
+# $FreeBSD$
+#
+
+PORTNAME= kqemu
+PORTVERSION= 0.7.2
+CATEGORIES= emulators
+MASTER_SITES= http://fabrice.bellard.free.fr/qemu/
+PKGNAMESUFFIX= -kmod
+DIST_SUBDIR= kqemu
+
+MAINTAINER= nork@FreeBSD.org
+COMMENT= Kernel Acceralator for QEMU CPU Emulator
+
+ONLY_FOR_ARCHS= i386 amd64
+NO_PACKAGE= "Depends on kernel, and module not redistributable"
+
+PLIST_FILES= "include/kqemu/kqemu.h"
+PLIST_FILES+= "@dirrm include/kqemu"
+PLIST_FILES+= "@cwd /"
+PLIST_FILES+= ${KMODDIR:C,^/,,}/kqemu.ko
+
+WRKSRC= ${WRKDIR}/${PORTNAME}
+MAKEFILE= Makefile.freebsd
+
+.include <bsd.port.pre.mk>
+
+.if !exists(${SRC_BASE}/sys/Makefile)
+IGNORE= kqemu requires kernel source to be installed
+.endif
+
+post-install:
+ @${MKDIR} ${PREFIX}/include/kqemu
+ @${INSTALL_DATA} ${WRKSRC}/kqemu.h ${PREFIX}/include/kqemu
+ 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
+
+.include <bsd.port.post.mk>
diff --git a/emulators/kqemu-kmod/distinfo b/emulators/kqemu-kmod/distinfo
new file mode 100644
index 000000000000..9d0296fa02c6
--- /dev/null
+++ b/emulators/kqemu-kmod/distinfo
@@ -0,0 +1,2 @@
+MD5 (kqemu/kqemu-0.7.2.tar.gz) = 02cfdecda90458d6393781496ec6b48b
+SIZE (kqemu/kqemu-0.7.2.tar.gz) = 79314
diff --git a/emulators/kqemu-kmod/files/patch-Makefile.freebsd b/emulators/kqemu-kmod/files/patch-Makefile.freebsd
new file mode 100644
index 000000000000..b75420fa0cc7
--- /dev/null
+++ b/emulators/kqemu-kmod/files/patch-Makefile.freebsd
@@ -0,0 +1,10 @@
+--- Makefile.freebsd.orig Fri Jul 29 06:37:06 2005
++++ Makefile.freebsd Tue Oct 25 21:08:43 2005
+@@ -5,6 +5,7 @@
+ .elif ${MACHINE_ARCH} == "amd64"
+ OBJS= kqemu-mod-x86_64.o
+ .endif
++CC= cc
+ WERROR=
+
+ .include <bsd.kmod.mk>
diff --git a/emulators/kqemu-kmod/files/patch-kqemu-freebsd.c b/emulators/kqemu-kmod/files/patch-kqemu-freebsd.c
new file mode 100644
index 000000000000..27eb0420a4ff
--- /dev/null
+++ b/emulators/kqemu-kmod/files/patch-kqemu-freebsd.c
@@ -0,0 +1,505 @@
+--- kqemu-freebsd.c.orig Mon Aug 15 01:34:06 2005
++++ kqemu-freebsd.c Tue Oct 25 21:08:43 2005
+@@ -3,32 +3,55 @@
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/conf.h>
++#include <sys/ctype.h>
++#include <sys/fcntl.h>
+ #include <sys/ioccom.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
++#if __FreeBSD_version >= 500000
+ #include <sys/mutex.h>
++#endif
+ #include <sys/proc.h>
++#include <sys/resourcevar.h>
++#if __FreeBSD_version >= 500000
+ #include <sys/sched.h>
++#endif
+ #include <sys/signalvar.h>
+ #include <sys/kernel.h>
++#include <sys/sysctl.h>
++#include <sys/uio.h>
++#if __FreeBSD_version < 500000
++#include <sys/buf.h>
++#endif
++
+ #include <vm/vm.h>
+ #include <vm/vm_param.h>
+ #include <vm/vm_extern.h>
+ #include <vm/pmap.h>
+ #include <vm/vm_map.h>
+ #include <vm/vm_kern.h>
++#include <vm/vm_page.h>
++
+ #include <machine/vmparam.h>
+ #include <machine/stdarg.h>
+
+ #include "kqemu-kernel.h"
+
++#ifndef KQEMU_MAJOR
++#define KQEMU_MAJOR 250
++#endif
++
+ MALLOC_DECLARE(M_KQEMU);
+ MALLOC_DEFINE(M_KQEMU, "kqemu", "kqemu buffers");
+
++int kqemu_debug;
++SYSCTL_INT(_debug, OID_AUTO, kqemu_debug, CTLFLAG_RW, &kqemu_debug, 0,
++ "kqemu debug flag");
++
+ #define USER_BASE 0x1000
+
+ /* lock the page at virtual address 'user_addr' and return its
+- physical page index. Return -1 if error */
++ physical page index. Return NULL if error */
+ struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index,
+ unsigned long user_addr)
+ {
+@@ -37,14 +60,18 @@
+ vm_paddr_t pa = 0;
+ int ret;
+ pmap_t pmap;
++#if __FreeBSD_version >= 500000
+ ret = vm_map_wire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
++#else
++ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, FALSE);
++#endif
+ if (ret != KERN_SUCCESS) {
+- printf("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret);
++ kqemu_log("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret);
+ return NULL;
+ }
+ pmap = vm_map_pmap(&vm->vm_map);
+ pa = pmap_extract(pmap, va);
+- // printf("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa);
++ /* kqemu_log("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa); */
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_user_page *)va;
+ }
+@@ -54,12 +81,16 @@
+ struct vmspace *vm = curproc->p_vmspace;
+ vm_offset_t va;
+ int ret;
+- // printf("kqemu_unlock_user_page(%08lx)\n", page_index);
++ /* kqemu_log("kqemu_unlock_user_page(%08lx)\n", page_index); */
+ va = (vm_offset_t)page;
++#if __FreeBSD_version >= 500000
+ ret = vm_map_unwire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
++#else
++ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, TRUE);
++#endif
+ #if 0
+ if (ret != KERN_SUCCESS) {
+- printf("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret);
++ kqemu_log("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret);
+ }
+ #endif
+ }
+@@ -76,20 +107,21 @@
+
+ va = kmem_alloc(kernel_map, PAGE_SIZE);
+ if (va == 0) {
+- printf("kqemu_alloc_zeroed_page: NULL\n");
+- return -1;
++ kqemu_log("kqemu_alloc_zeroed_page: NULL\n");
++ return NULL;
+ }
+ pmap = vm_map_pmap(kernel_map);
+ pa = pmap_extract(pmap, va);
+- // printf("kqemu_alloc_zeroed_page: %08x\n", pa);
++ /* kqemu_log("kqemu_alloc_zeroed_page: %08x\n", pa); */
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_page *)va;
+ }
+
+ void CDECL kqemu_free_page(struct kqemu_page *page)
+ {
+- // printf("kqemu_free_page(%08lx)\n", page_index);
+- /* XXX: do it */
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_free_page(%p)\n", page);
++ kmem_free(kernel_map, (vm_offset_t) page, PAGE_SIZE);
+ }
+
+ /* return kernel address of the physical page page_index */
+@@ -103,42 +135,29 @@
+ GB of physical memory */
+ void * CDECL kqemu_vmalloc(unsigned int size)
+ {
+- struct vmspace *vm = curproc->p_vmspace;
+- vm_offset_t va = USER_BASE;
+- int rv;
+- if (size % PAGE_SIZE != 0) {
+- printf("kqemu_vmalloc(%d) not a multiple of page size\n", size);
+- return NULL;
+- }
+- rv = vm_map_find(&vm->vm_map, NULL, 0, &va, size, 1,
+- VM_PROT_ALL, VM_PROT_ALL, 0);
+- if (rv != KERN_SUCCESS) {
+- printf("kqemu_vmalloc(%d) failed rv=%d\n", size, rv);
+- return NULL;
+- }
+- printf("kqemu_vmalloc(%d): %08x\n", size, va);
+- return (void *)va;
++ void *ptr = malloc(size, M_KQEMU, M_WAITOK);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vmalloc(%d): %p\n", size, ptr);
++ return ptr;
+ }
+
+ void CDECL kqemu_vfree(void *ptr)
+ {
+- printf("kqemu_vfree(%p)\n", ptr);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vfree(%p)\n", ptr);
++ free(ptr, M_KQEMU);
+ }
+
+ /* return the physical page index for a given virtual page */
+ unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr)
+ {
+- struct vmspace *vm = curproc->p_vmspace;
+- vm_paddr_t pa;
+- pmap_t pmap;
+-
+- pmap = vm_map_pmap(&vm->vm_map);
+- pa = pmap_extract(pmap, (vm_offset_t)vaddr);
++ vm_paddr_t pa = vtophys(vaddr);
+ if (pa == 0) {
+- printf("kqemu_vmalloc_to_phys(%p)->error\n", vaddr);
++ kqemu_log("kqemu_vmalloc_to_phys(%p)->error\n", vaddr);
+ return -1;
+ }
+- printf("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa);
++ if (kqemu_debug > 0)
++ kqemu_log("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa);
+ return pa >> PAGE_SHIFT;
+ }
+
+@@ -154,16 +173,48 @@
+ {
+ }
+
++#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)
+ {
+- // printf("kqemu_schedule\n");
++ /* kqemu_log("kqemu_schedule\n"); */
+ mtx_lock_spin(&sched_lock);
+ mi_switch(SW_VOL, NULL);
+ mtx_unlock_spin(&sched_lock);
+ return SIGPENDING(curthread);
+ }
++#endif
+
+ static char log_buf[4096];
+
+@@ -176,47 +227,159 @@
+ va_end(ap);
+ }
+
++#define KQEMU_MAX_INSTANCES 4
++
+ struct kqemu_instance {
+- // struct semaphore sem;
++#if __FreeBSD_version >= 500000
++ TAILQ_ENTRY(kqemu_instance) kqemu_ent;
++ struct cdev *kqemu_dev;
++#endif
++ /* struct semaphore sem; */
+ 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 clonedevs *kqemuclones;
++static TAILQ_HEAD(,kqemu_instance) kqemuhead = TAILQ_HEAD_INITIALIZER(kqemuhead);
++static eventhandler_tag clonetag;
++#endif
++
+ static d_close_t kqemu_close;
+ static d_open_t kqemu_open;
+ 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_flags = D_NEEDGIANT,
+ .d_open = kqemu_open,
+ .d_ioctl = kqemu_ioctl,
+ .d_close = kqemu_close,
+ .d_name = "kqemu"
++#endif
+ };
+
+-/* For use with make_dev(9)/destroy_dev(9). */
+-static struct cdev *kqemu_dev;
++#if __FreeBSD_version >= 500000
++static void
++#if __FreeBSD_version >= 600034
++kqemu_clone(void *arg, struct ucred *cred, char *name, int namelen,
++struct cdev **dev)
++#else
++kqemu_clone(void *arg, char *name, int namelen, struct cdev **dev)
++#endif
++{
++ int unit, r;
++ if (*dev != NULL)
++ return;
++
++ if (strcmp(name, "kqemu") == 0)
++ unit = -1;
++ else if (dev_stdclone(name, NULL, "kqemu", &unit) != 1)
++ return; /* Bad name */
++ if (unit != -1 && unit > KQEMU_MAX_INSTANCES)
++ return;
++
++ r = clone_create(&kqemuclones, &kqemu_cdevsw, &unit, dev, 0);
++ if (r) {
++ *dev = make_dev(&kqemu_cdevsw, unit2minor(unit),
++ UID_ROOT, GID_WHEEL, 0660, "kqemu%d", unit);
++ if (*dev != NULL) {
++ (*dev)->si_flags |= SI_CHEAPCLONE;
++ }
++ }
++}
++#endif
++
++static void kqemu_destroy(struct kqemu_instance *ks)
++{
++#if __FreeBSD_version >= 500000
++ struct cdev *dev = ks->kqemu_dev;
++#endif
++
++ if (ks->state) {
++ kqemu_delete(ks->state);
++ ks->state = NULL;
++ }
++
++#if __FreeBSD_version >= 500000
++ dev->si_drv1 = NULL;
++ TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent);
++ destroy_dev(dev);
++#endif
++ free(ks, M_KQEMU);
++ --kqemu_ref_count;
++}
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_open(dev_t dev, int flags, int fmt __unused, struct proc *p)
++{
++#else
+ kqemu_open(struct cdev *dev, int flags, int fmt __unused,
+ struct thread *td)
+ {
++ struct proc *p = td->td_proc;
++#endif
+ struct kqemu_instance *ks;
++
++#if __FreeBSD_version >= 500000
++ if (kqemu_ref_count >= KQEMU_MAX_INSTANCES)
++#else
++ if (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES)
++#endif
++ return(EBUSY);
++
++ if ((flags & (FREAD|FWRITE)) == FREAD)
++ return(EPERM);
++
+ ks = malloc(sizeof(struct kqemu_instance), M_KQEMU, M_WAITOK);
+ if (ks == NULL) {
+- printf("malloc failed\n");
++ kqemu_log("malloc failed\n");
+ return ENOMEM;
+ }
+- ks->state = NULL;
++ memset(ks, 0, sizeof *ks);
++#if __FreeBSD_version >= 500000
++ ks->kqemu_dev = dev;
++ TAILQ_INSERT_TAIL(&kqemuhead, ks, kqemu_ent);
++#endif
++ kqemu_ref_count++;
++
+ dev->si_drv1 = ks;
++ if (kqemu_debug > 0)
++ kqemu_log("opened by pid=%d\n", p->p_pid);
+ return 0;
+ }
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_ioctl(dev_t dev, u_long cmd, caddr_t addr,
++ int flags __unused, struct proc *p)
++#else
+ kqemu_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
+ int flags __unused, struct thread *td)
++#endif
+ {
+ int error = 0;
+ int ret;
+@@ -231,8 +394,9 @@
+ break;
+ }
+ d1 = *(struct kqemu_init *)addr;
+- printf("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size);
+- s = kqemu_init(d, 16000);
++ if (kqemu_debug > 0)
++ kqemu_log("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size);
++ s = kqemu_init(d, max_locked_pages);
+ if (s == NULL) {
+ error = ENOMEM;
+ break;
+@@ -248,9 +412,16 @@
+ }
+ ctx = kqemu_get_cpu_state(s);
+ *ctx = *(struct kqemu_cpu_state *)addr;
++#if __FreeBSD_version >= 500000
+ DROP_GIANT();
++#endif
+ ret = kqemu_exec(s);
++#if __FreeBSD_version >= 500000
+ PICKUP_GIANT();
++ td->td_retval[0] = ret;
++#else
++ p->p_retval[0] = ret;
++#endif
+ *(struct kqemu_cpu_state *)addr = *ctx;
+ break;
+ }
+@@ -265,10 +436,22 @@
+
+ /* ARGSUSED */
+ static int
++#if __FreeBSD_version < 500000
++kqemu_close(dev_t dev, int flags, int fmt __unused, struct proc *p)
++{
++#else
+ kqemu_close(struct cdev *dev __unused, int flags, int fmt __unused,
+ struct thread *td)
+ {
+- return 0;
++ struct proc *p = td->td_proc;
++#endif
++ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
++
++ kqemu_destroy(ks);
++
++ if (kqemu_debug > 0)
++ kqemu_log("closed by pid=%d\n", p->p_pid);
++ return 0;
+ }
+
+ /* ARGSUSED */
+@@ -276,15 +459,55 @@
+ kqemu_modevent(module_t mod __unused, int type, void *data __unused)
+ {
+ int error = 0;
++#if __FreeBSD_version < 500000
++ int rc;
++#else
++ struct kqemu_instance *ks;
++#endif
+
+ switch (type) {
+ case MOD_LOAD:
+ printf("kqemu version 0x%08x\n", KQEMU_VERSION);
++ 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);
++ error = ENOENT;
++ break;
++ }
+ kqemu_dev = make_dev(&kqemu_cdevsw, 0,
+- UID_ROOT, GID_WHEEL, 0666, "kqemu");
++ UID_ROOT, GID_WHEEL, 0660, "kqemu");
++#else
++ clone_setup(&kqemuclones);
++ clonetag = EVENTHANDLER_REGISTER(dev_clone, kqemu_clone, 0, 1000);
++ if (!clonetag) {
++ error = ENOMEM;
++ break;
++ }
++#endif
++ kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
++ KQEMU_MAX_INSTANCES, max_locked_pages * 4);
++
++ kqemu_ref_count = 0;
+ break;
+ case MOD_UNLOAD:
++ if (kqemu_ref_count > 0) {
++ error = EBUSY;
++ break;
++ }
++#if __FreeBSD_version < 500000
+ destroy_dev(kqemu_dev);
++ if ((rc = cdevsw_remove(&kqemu_cdevsw)))
++ kqemu_log("error unregistering, rc=%d\n", rc);
++#else
++ EVENTHANDLER_DEREGISTER(dev_clone, clonetag);
++ while ((ks = TAILQ_FIRST(&kqemuhead)) != NULL) {
++ kqemu_destroy(ks);
++ }
++ clone_cleanup(&kqemuclones);
++#endif
+ break;
+ case MOD_SHUTDOWN:
+ break;
diff --git a/emulators/kqemu-kmod/pkg-descr b/emulators/kqemu-kmod/pkg-descr
new file mode 100644
index 000000000000..d340d3bb1f4b
--- /dev/null
+++ b/emulators/kqemu-kmod/pkg-descr
@@ -0,0 +1,3 @@
+KQEMU is a qemu accelerator kernel module on x86/amd64.
+
+WWW: http://fabrice.bellard.free.fr/qemu/qemu-accel.html