diff options
author | pav <pav@FreeBSD.org> | 2005-05-05 20:41:10 +0800 |
---|---|---|
committer | pav <pav@FreeBSD.org> | 2005-05-05 20:41:10 +0800 |
commit | 6225c1dae8f9878dd0d4ba3e40f9dd98a3d6024e (patch) | |
tree | 17250384ed709d8f65ab0e105bdbd5f8b3133e70 /emulators | |
parent | b734cffc664a6ab075381fd0aa21595ef03ac538 (diff) | |
download | freebsd-ports-gnome-6225c1dae8f9878dd0d4ba3e40f9dd98a3d6024e.tar.gz freebsd-ports-gnome-6225c1dae8f9878dd0d4ba3e40f9dd98a3d6024e.tar.zst freebsd-ports-gnome-6225c1dae8f9878dd0d4ba3e40f9dd98a3d6024e.zip |
- Update to 2005-05-02 snapshot
- Add kqemu support
PR: ports/80595
Submitted by: Juergen Lock <nox@jelal.kn-bremen.de> (maintainer)
Diffstat (limited to 'emulators')
-rw-r--r-- | emulators/qemu-devel/Makefile | 52 | ||||
-rw-r--r-- | emulators/qemu-devel/distinfo | 6 | ||||
-rw-r--r-- | emulators/qemu-devel/files/kmod_bsd.c | 575 | ||||
-rw-r--r-- | emulators/qemu-devel/files/kqemu-patch | 68 | ||||
-rw-r--r-- | emulators/qemu-devel/files/patch-fbsd | 28 | ||||
-rw-r--r-- | emulators/qemu-devel/files/patch-osdep.c | 40 | ||||
-rw-r--r-- | emulators/qemu-devel/pkg-plist | 2 | ||||
-rw-r--r-- | emulators/qemu/Makefile | 52 | ||||
-rw-r--r-- | emulators/qemu/distinfo | 6 | ||||
-rw-r--r-- | emulators/qemu/files/kmod_bsd.c | 575 | ||||
-rw-r--r-- | emulators/qemu/files/kqemu-patch | 68 | ||||
-rw-r--r-- | emulators/qemu/files/patch-fbsd | 28 | ||||
-rw-r--r-- | emulators/qemu/files/patch-osdep.c | 40 | ||||
-rw-r--r-- | emulators/qemu/pkg-plist | 2 |
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 |