ports/80595: update emulators/qemu to 2005-05-02 snapshot, add kqemu

Juergen Lock nox at jelal.kn-bremen.de
Tue May 3 23:00:27 UTC 2005


>Number:         80595
>Category:       ports
>Synopsis:       update emulators/qemu to 2005-05-02 snapshot, add kqemu
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          maintainer-update
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 03 23:00:18 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Juergen Lock
>Release:        FreeBSD 5.3-RELEASE-p2 i386
>Organization:
me?  organized??
>Environment:
System: FreeBSD saturn 5.3-RELEASE-p2 FreeBSD 5.3-RELEASE-p2 #6: Wed Feb 16 17:56:04 CET 2005     nox at saturn:/ad0/usr/home/nox/src5/usr/src/sys/i386/compile/NEPTUN  i386

>Description:

- i386 kqemu support (tested on 4.10 and 5.3, kudos to Antony T Curtis
for the wrapper!)

Virtual PC read-only disk image support (Alex Beregszaszi), BMDMA
interrupt fix (aka Solaris x86 IDE bug fix), ne2000 reset fix - start/stop
registers read access (aka OS/2 Warp V4 fix) (lukewarm), raw dmg support,
block driver probing fixes, Virtual VFAT support (Johannes Schindelin),
Windows 2000 install disk full hack (original idea from Vladimir N. Oleynik)

>How-To-Repeat:
	n/a
>Fix:

new files: files/kmod_bsd.c, files/kqemu-patch, files/patch-osdep.c

Index: Makefile
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/Makefile,v
retrieving revision 1.24
diff -u -r1.24 Makefile
--- Makefile	3 May 2005 04:02:45 -0000	1.24
+++ Makefile	3 May 2005 20:55:19 -0000
@@ -6,10 +6,17 @@
 #
 
 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}
+.if defined(WITH_KQEMU)
+DISTKQEMU=	kqemu-0.6.2-1.tar.gz
+DISTFILES=	${EXTRACT_ONLY} ${DISTKQEMU}
+.endif
 
 MAINTAINER=	nox at jelal.kn-bremen.de
 COMMENT=	QEMU CPU Emulator
@@ -20,6 +27,7 @@
 .endif
 
 HAS_CONFIGURE=	yes
+USE_BZIP2=	yes
 USE_GMAKE=	yes
 USE_GETOPT_LONG=	yes
 USE_SDL=	sdl
@@ -29,6 +37,14 @@
 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 +63,48 @@
 USE_GCC=	3.4
 .endif
 
+.if defined(WITH_KQEMU) && ${ARCH} != "i386"
+BROKEN=		kqemu only supported on i386
+.endif
+
+.if defined(WITH_KQEMU) && !exists(${SRC_BASE}/sys/Makefile)
+BROKEN=		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>
Index: distinfo
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/distinfo,v
retrieving revision 1.17
diff -u -r1.17 distinfo
--- distinfo	1 May 2005 07:39:10 -0000	1.17
+++ distinfo	3 May 2005 18:11:40 -0000
@@ -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
Index: pkg-plist
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/pkg-plist,v
retrieving revision 1.9
diff -u -r1.9 pkg-plist
--- pkg-plist	27 Feb 2005 15:43:19 -0000	1.9
+++ pkg-plist	3 May 2005 18:38:56 -0000
@@ -49,3 +49,5 @@
 @dirrm share/qemu/keymaps
 @dirrm share/qemu
 %%PORTDOCS%%@dirrm %%DOCSDIR%%
+ at cwd /
+%%WITH_KQEMU%%%%KMODDIR%%/kqemu.ko
Index: files/patch-fbsd
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/files/patch-fbsd,v
retrieving revision 1.1
diff -u -r1.1 patch-fbsd
--- files/patch-fbsd	3 May 2005 04:02:46 -0000	1.1
+++ files/patch-fbsd	3 May 2005 18:48:50 -0000
@@ -8,14 +8,19 @@
  	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 @@
  	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
Index: 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);
+
Index: 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>
Index: 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);
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list