diff options
author | nork <nork@FreeBSD.org> | 2005-09-10 17:04:42 +0000 |
---|---|---|
committer | nork <nork@FreeBSD.org> | 2005-09-10 17:04:42 +0000 |
commit | d4de451e3a306cc937e42f94243e219075f207a4 (patch) | |
tree | ac10032d28518e50fd98d5c9596fc8b501e52c81 /emulators/qemu-devel | |
parent | 2fc6079ad884de6f5272fc24f7c954af70ee8044 (diff) | |
download | FreeBSD-ports-d4de451e3a306cc937e42f94243e219075f207a4.zip FreeBSD-ports-d4de451e3a306cc937e42f94243e219075f207a4.tar.gz |
Update to 0.7.2s.20050909.
PR: ports/85947
Submitted by: Juergen Lock <nox@jelal.kn-bremen.de> (maintainer)
Diffstat (limited to 'emulators/qemu-devel')
-rw-r--r-- | emulators/qemu-devel/Makefile | 19 | ||||
-rw-r--r-- | emulators/qemu-devel/distinfo | 8 | ||||
-rw-r--r-- | emulators/qemu-devel/files/BSDmakefile | 9 | ||||
-rw-r--r-- | emulators/qemu-devel/files/kmod_bsd.c | 642 | ||||
-rw-r--r-- | emulators/qemu-devel/files/kqemu-freebsd-patch | 506 | ||||
-rw-r--r-- | emulators/qemu-devel/files/patch-fbsd | 2 | ||||
-rw-r--r-- | emulators/qemu-devel/files/patch-libmath2 | 67 | ||||
-rw-r--r-- | emulators/qemu-devel/files/patch-vl.c | 21 | ||||
-rw-r--r-- | emulators/qemu-devel/pkg-message | 8 |
9 files changed, 616 insertions, 666 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile index 318df65..895cd75 100644 --- a/emulators/qemu-devel/Makefile +++ b/emulators/qemu-devel/Makefile @@ -6,12 +6,12 @@ # PORTNAME= qemu -PORTVERSION= 0.7.0s.20050717 +PORTVERSION= 0.7.2s.20050909 CATEGORIES= emulators MASTER_SITES= http://www.qemu.org/ \ http://people.fruitsalad.org/nox/qemu/ \ http://dad-answers.com/qemu/ -DISTNAME= ${PORTNAME}-snapshot-2005-07-17_23 +DISTNAME= ${PORTNAME}-snapshot-2005-09-09_23 EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} MAINTAINER= nox@jelal.kn-bremen.de @@ -23,8 +23,9 @@ RUN_DEPENDS+= ${LOCALBASE}/sbin/smbd:${PORTSDIR}/net/samba .endif .if defined(WITH_KQEMU) -DISTKQEMU= kqemu-0.6.2-1.tar.gz +DISTKQEMU= kqemu-0.7.2.tar.gz DISTFILES= ${EXTRACT_ONLY} ${DISTKQEMU} +EXTRA_PATCHES= ${FILESDIR}/kqemu-freebsd-patch .endif HAS_CONFIGURE= yes @@ -40,9 +41,11 @@ MAN1= qemu.1 qemu-img.1 ONLY_FOR_ARCHS= amd64 i386 .if defined(WITH_KQEMU) NO_PACKAGE= Depends on kernel, and module not redistributable +CONFIGURE_ARGS+= --enable-kqemu PLIST_SUB= WITH_KQEMU="" PLIST_SUB+= KMODDIR=${KMODDIR} .else +CONFIGURE_ARGS+= --disable-kqemu PLIST_SUB= WITH_KQEMU="@comment " .endif @@ -52,7 +55,7 @@ PLIST_SUB= WITH_KQEMU="@comment " .if ${ARCH} == "amd64" ARCH= x86_64 -.if ${OSVERSION} >= 502126 +.if ${OSVERSION} >= 502126 && ${OSVERSION} <= 600029 BUILD_DEPENDS+= gcc34:${PORTSDIR}/lang/gcc34 GCCVERSION= 030402 CC= gcc34 @@ -63,16 +66,12 @@ 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" +.if !defined(WITH_KQEMU) @${ECHO_MSG} "Notice: you can build qemu with the (alpha!) kqemu accelerator kernel module" @${ECHO_MSG} "by defining WITH_KQEMU." .endif @@ -85,7 +84,7 @@ pre-everything:: .if defined(WITH_KQEMU) post-extract: @cd ${WRKSRC} && ${TAR} xfz ${_DISTDIR}/${DISTKQEMU} - @${CP} ${FILESDIR}/BSDmakefile ${FILESDIR}/kmod_bsd.c ${WRKSRC}/kqemu + @${LN} -s Makefile.freebsd ${WRKSRC}/kqemu/BSDmakefile .endif pre-patch: diff --git a/emulators/qemu-devel/distinfo b/emulators/qemu-devel/distinfo index b687e57..a1230e1 100644 --- a/emulators/qemu-devel/distinfo +++ b/emulators/qemu-devel/distinfo @@ -1,4 +1,4 @@ -MD5 (qemu-snapshot-2005-07-17_23.tar.bz2) = 5d21295c1f328ea00de19a54715ee7c3 -SIZE (qemu-snapshot-2005-07-17_23.tar.bz2) = 1114748 -MD5 (kqemu-0.6.2-1.tar.gz) = c6bb3b40fb3d526d731eb0f1f9dee7ee -SIZE (kqemu-0.6.2-1.tar.gz) = 21002 +MD5 (qemu-snapshot-2005-09-09_23.tar.bz2) = db4ffeb081666c7352f5c0231e3f09c7 +SIZE (qemu-snapshot-2005-09-09_23.tar.bz2) = 1122120 +MD5 (kqemu-0.7.2.tar.gz) = 02cfdecda90458d6393781496ec6b48b +SIZE (kqemu-0.7.2.tar.gz) = 79314 diff --git a/emulators/qemu-devel/files/BSDmakefile b/emulators/qemu-devel/files/BSDmakefile deleted file mode 100644 index 41be885..0000000 --- a/emulators/qemu-devel/files/BSDmakefile +++ /dev/null @@ -1,9 +0,0 @@ -KMOD= kqemu -SRCS= kmod_bsd.c -OBJS= kqemu-mod-i386.o -.if ${OSVERSION} >= 500000 -CC= cc -.endif -WERROR= - -.include <bsd.kmod.mk> diff --git a/emulators/qemu-devel/files/kmod_bsd.c b/emulators/qemu-devel/files/kmod_bsd.c deleted file mode 100644 index 9e51b7c..0000000 --- a/emulators/qemu-devel/files/kmod_bsd.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * 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 { -#if __FreeBSD_version > 500000 - TAILQ_ENTRY(kqemu_instance) kqemu_ent; - struct cdev *kqemu_dev; -#endif - 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_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", -#ifdef D_NEEDGIANT - .d_flags = D_NEEDGIANT, -#endif -#endif -}; - -#if __FreeBSD_version > 500000 -static void -kqemu_clone(void *arg, char *name, int namelen, struct cdev **dev) -{ - 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_ref(*dev); - (*dev)->si_flags |= SI_CHEAPCLONE; - } - } -} -#endif - -static void kqemu_destroy(struct kqemu_instance *ks) -{ - struct cdev *dev = ks->kqemu_dev; - - 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); - TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent); -#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); - - destroy_dev(dev); -#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 - ks->kqemu_dev = dev; - mtx_lock_spin(&cache_lock); - TAILQ_INSERT_TAIL(&kqemuhead, ks, kqemu_ent); -#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; - - kqemu_destroy(ks); - - 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); - } - - kqemu_dev = make_dev(&kqemu_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, "kqemu"); -#else - clone_setup(&kqemuclones); - clonetag = EVENTHANDLER_REGISTER(dev_clone, kqemu_clone, 0, 1000); - if (!clonetag) - return ENOMEM; -#endif - - 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; -#else - struct kqemu_instance *ks; -#endif - -#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); - mtx_lock_spin(&cache_lock); - while ((ks = TAILQ_FIRST(&kqemuhead)) != NULL) { - mtx_unlock_spin(&cache_lock); - kqemu_destroy(ks); - mtx_lock_spin(&cache_lock); - } - mtx_unlock_spin(&cache_lock); - mtx_destroy(&cache_lock); - clone_cleanup(&kqemuclones); -#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-freebsd-patch b/emulators/qemu-devel/files/kqemu-freebsd-patch new file mode 100644 index 0000000..75ff3cf --- /dev/null +++ b/emulators/qemu-devel/files/kqemu-freebsd-patch @@ -0,0 +1,506 @@ +Index: qemu/kqemu/Makefile.freebsd +@@ -1,9 +1,13 @@ ++# $Id: Makefile.freebsd,v 1.1 2005/04/17 17:21:31 bellard Exp $ + KMOD= kqemu + SRCS= kqemu-freebsd.c + .if ${MACHINE_ARCH} == "i386" + OBJS= kqemu-mod-i386.o + .elif ${MACHINE_ARCH} == "amd64" + OBJS= kqemu-mod-x86_64.o ++.endif ++.if ${OSVERSION} >= 500000 ++CC= cc + .endif + WERROR= + +Index: qemu/kqemu/kqemu-freebsd.c +@@ -3,20 +3,33 @@ + #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> + #include <sys/mutex.h> + #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> + +@@ -25,10 +38,14 @@ + 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 +54,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 +75,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 +101,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 +129,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 +167,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) + { +- // printf("kqemu_schedule\n"); ++ 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) ++{ ++ // 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 +221,154 @@ + va_end(ap); + } + ++#define KQEMU_MAX_INSTANCES 4 ++ + struct kqemu_instance { ++#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_ref(*dev); ++ (*dev)->si_flags |= SI_CHEAPCLONE; ++ } ++ } ++} ++#endif ++ ++static void kqemu_destroy(struct kqemu_instance *ks) ++{ ++ struct cdev *dev = ks->kqemu_dev; ++ ++ if (ks->state) { ++ kqemu_delete(ks->state); ++ ks->state = NULL; ++ } ++ ++ free(ks, M_KQEMU); ++ dev->si_drv1 = NULL; ++#if __FreeBSD_version >= 500000 ++ TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent); ++ destroy_dev(dev); ++#endif ++ --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 (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES) ++ 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 +383,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 +401,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 +425,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 +448,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/qemu-devel/files/patch-fbsd b/emulators/qemu-devel/files/patch-fbsd index 76e9500..a668fde 100644 --- a/emulators/qemu-devel/files/patch-fbsd +++ b/emulators/qemu-devel/files/patch-fbsd @@ -13,7 +13,7 @@ Index: qemu/Makefile $(MAKE) -C kqemu -f Makefile.winnt else - $(MAKE) -C kqemu -+ cd kqemu && $(BSD_MAKE) ++ ( cd kqemu && $(BSD_MAKE) ) endif endif diff --git a/emulators/qemu-devel/files/patch-libmath2 b/emulators/qemu-devel/files/patch-libmath2 new file mode 100644 index 0000000..a6f6475 --- /dev/null +++ b/emulators/qemu-devel/files/patch-libmath2 @@ -0,0 +1,67 @@ +Index: qemu/bsd/Makefile +@@ -16,7 +16,8 @@ + ${MACHINE_ARCH}/s_rintl.c \ + ${MACHINE_ARCH}/s_round.c \ + ${MACHINE_ARCH}/s_sinl.S \ +- ${MACHINE_ARCH}/s_tanl.S ++ ${MACHINE_ARCH}/s_tanl.S \ ++ ${MACHINE_ARCH}/s_ldexpl.c + + OBJS= ${SRCS:R:S/$/.o/} + +Index: qemu/bsd/i386/s_ldexpl.c +@@ -0,0 +1,21 @@ ++#include <math.h> ++#include <errno.h> ++#include <sysdep.h> ++ ++long double __ldexpl(long double x, int expn) ++{ ++ long double res; ++ if (!isfinite (x) || x == 0.0L) ++ return x; ++ ++ __asm__ ("fscale" ++ : "=t" (res) ++ : "0" (x), "u" ((long double) expn)); ++ ++ if (!isfinite (res) || res == 0.0L) ++ errno = ERANGE; ++ ++ return res; ++} ++ ++weak_alias(__ldexpl,ldexpl) +Index: qemu/bsd/amd64/s_ldexpl.c +@@ -0,0 +1,21 @@ ++#include <math.h> ++#include <errno.h> ++#include <sysdep.h> ++ ++long double __ldexpl(long double x, int expn) ++{ ++ long double res; ++ if (!isfinite (x) || x == 0.0L) ++ return x; ++ ++ __asm__ ("fscale" ++ : "=t" (res) ++ : "0" (x), "u" ((long double) expn)); ++ ++ if (!isfinite (res) || res == 0.0L) ++ errno = ERANGE; ++ ++ return res; ++} ++ ++weak_alias(__ldexpl,ldexpl) +Index: qemu/target-i386/helper.c +@@ -2886,6 +2886,8 @@ + ST0 = floatx_round_to_int(ST0, &env->fp_status); + } + ++long double ldexpl(long double, int); ++ + void helper_fscale(void) + { + ST0 = ldexp (ST0, (int)(ST1)); diff --git a/emulators/qemu-devel/files/patch-vl.c b/emulators/qemu-devel/files/patch-vl.c new file mode 100644 index 0000000..85a521b --- /dev/null +++ b/emulators/qemu-devel/files/patch-vl.c @@ -0,0 +1,21 @@ +Index: qemu/vl.c +@@ -40,6 +40,10 @@ + #include <sys/socket.h> + #include <netinet/in.h> + #include <dirent.h> ++#ifdef __FreeBSD__ ++#include <sys/types.h> ++#include <libutil.h> ++#endif + #ifdef _BSD + #include <sys/stat.h> + #ifndef __APPLE__ +@@ -1280,7 +1284,7 @@ + return chr; + } + +-#if defined(__linux__) ++#if defined(__linux__) || defined(__FreeBSD__) + CharDriverState *qemu_chr_open_pty(void) + { + char slave_name[1024]; diff --git a/emulators/qemu-devel/pkg-message b/emulators/qemu-devel/pkg-message index ad921ec..31e02bd 100644 --- a/emulators/qemu-devel/pkg-message +++ b/emulators/qemu-devel/pkg-message @@ -1,6 +1,9 @@ ==== FreeBSD host notes: - needs to run as root in order to use /dev/tap* networking (why?) +(actually RELENG_6 and above now has a sysctl net.link.tap.user_open +to allow users to use it too. don't forget to adjust device node +permissions in /etc/devfs.rules.) - slirp (usermode networking) is fixed now in cvs, on FreeSBIE 1.0 guests you still have to manually do: echo nameserver 10.0.2.3 >/etc/resolv.conf @@ -18,4 +21,9 @@ its kernel is built with HZ=5000, and FreeBSD's default is 100... ioctl.) - the -smb option (smb-export local dir to guest) needs the net/samba port/package installed in addition to qemu. +- RELENG_6 and up guests often crash while accessing the emulated cdrom +(see kern/84102, http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/84102), +using a kernel without PREEMPTION has been reported to fix this problem. +(or do an ftp install instead of installing from the emulated cdrom, and +then make a new kernel.) ==== |