From owner-freebsd-emulation@FreeBSD.ORG Tue Oct 25 12:58:03 2005 Return-Path: X-Original-To: freebsd-emulation@FreeBSD.org Delivered-To: freebsd-emulation@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 221B516A41F; Tue, 25 Oct 2005 12:58:03 +0000 (GMT) (envelope-from nork@FreeBSD.org) Received: from sakura.ninth-nine.com (sakura.ninth-nine.com [219.127.74.120]) by mx1.FreeBSD.org (Postfix) with ESMTP id F394443D60; Tue, 25 Oct 2005 12:58:01 +0000 (GMT) (envelope-from nork@FreeBSD.org) Received: from nadesico.ninth-nine.com (nadesico.ninth-nine.com [219.127.74.122]) by sakura.ninth-nine.com (8.13.3/8.13.3/NinthNine) with ESMTP id j9PCvxaw096894; Tue, 25 Oct 2005 21:58:00 +0900 (JST) (envelope-from nork@FreeBSD.org) Date: Tue, 25 Oct 2005 21:57:59 +0900 From: Norikatsu Shigemura To: Juergen Lock Message-Id: <20051025215759.25681b85.nork@FreeBSD.org> X-Mailer: Sylpheed version 2.1.4 (GTK+ 2.6.10; i386-portbld-freebsd7.0) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0 (sakura.ninth-nine.com [219.127.74.121]); Tue, 25 Oct 2005 21:58:00 +0900 (JST) Cc: freebsd-emulation@FreeBSD.org, Norikatsu Shigemura , Jung-uk Kim Subject: kqemu-kmod port X-BeenThere: freebsd-emulation@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Development of Emulators of other operating systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Oct 2005 12:58:03 -0000 Hi qemu maintainer and users! I want kqemu only port to make buildkernel with PORTS_MODULES. I tested that make buildworld PORTS_MODULES=emulators/qemu, but no good. So I decided to make kqemu-kmod port. If I commit following port, I'll remove kqemu related code from emulators/qemu/Makefile and add dependency on kqemu-kmod. http://people.freebsd.org/~nork/kqemu-kmod.shar or # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # kqemu-kmod/Makefile # kqemu-kmod/distinfo # kqemu-kmod/files # kqemu-kmod/files/patch-Makefile.freebsd # kqemu-kmod/files/patch-kqemu-freebsd.c # kqemu-kmod/pkg-descr # echo x - kqemu-kmod/Makefile sed 's/^X//' >kqemu-kmod/Makefile << 'END-of-kqemu-kmod/Makefile' X# New ports collection makefile for: kqemu-kmod X# Date created: 2005/10/25 X# Whom: nork@FreeBSD.org X# X# $FreeBSD$ X# X XPORTNAME= kqemu XPORTVERSION= 0.7.2 XCATEGORIES= emulators XMASTER_SITES= http://fabrice.bellard.free.fr/qemu/ XPKGNAMESUFFIX= -kmod XDIST_SUBDIR= kqemu X XMAINTAINER= nork@FreeBSD.org XCOMMENT= Kernel Acceralator for QEMU CPU Emulator X XONLY_FOR_ARCHS= i386 amd64 XNO_PACKAGE= "Depends on kernel, and module not redistributable" X XPLIST_FILES= "@cwd /" XPLIST_FILES+= ${KMODDIR:C,^/,,}/kqemu.ko X XWRKSRC= ${WRKDIR}/${PORTNAME} XMAKEFILE= BSDmakefile X X.include X X.if !exists(${SRC_BASE}/sys/Makefile) XIGNORE= kqemu requires kernel source to be installed X.endif X Xpost-extract: X @${LN} -s Makefile.freebsd ${WRKSRC}/BSDmakefile X Xpost-install: X if mount |${GREP} ^devfs >/dev/null ; then \ X : ; \ X else \ X if [ ! -e /dev/kqemu ]; then\ X mknod /dev/kqemu c 250 0 ; \ X fi ; \ X ${CHMOD} 666 /dev/kqemu ; \ X fi X X.include END-of-kqemu-kmod/Makefile echo x - kqemu-kmod/distinfo sed 's/^X//' >kqemu-kmod/distinfo << 'END-of-kqemu-kmod/distinfo' XMD5 (kqemu/kqemu-0.7.2.tar.gz) = 02cfdecda90458d6393781496ec6b48b XSIZE (kqemu/kqemu-0.7.2.tar.gz) = 79314 END-of-kqemu-kmod/distinfo echo c - kqemu-kmod/files mkdir -p kqemu-kmod/files > /dev/null 2>&1 echo x - kqemu-kmod/files/patch-Makefile.freebsd sed 's/^X//' >kqemu-kmod/files/patch-Makefile.freebsd << 'END-of-kqemu-kmod/files/patch-Makefile.freebsd' X--- Makefile.freebsd.orig Fri Jul 29 06:37:06 2005 X+++ Makefile.freebsd Tue Oct 25 21:08:43 2005 X@@ -5,6 +5,7 @@ X .elif ${MACHINE_ARCH} == "amd64" X OBJS= kqemu-mod-x86_64.o X .endif X+CC= cc X WERROR= X X .include END-of-kqemu-kmod/files/patch-Makefile.freebsd echo x - kqemu-kmod/files/patch-kqemu-freebsd.c sed 's/^X//' >kqemu-kmod/files/patch-kqemu-freebsd.c << 'END-of-kqemu-kmod/files/patch-kqemu-freebsd.c' X--- kqemu-freebsd.c.orig Mon Aug 15 01:34:06 2005 X+++ kqemu-freebsd.c Tue Oct 25 21:08:43 2005 X@@ -3,32 +3,55 @@ X #include X #include X #include X+#include X+#include X #include X #include X #include X+#if __FreeBSD_version >= 500000 X #include X+#endif X #include X+#include X+#if __FreeBSD_version >= 500000 X #include X+#endif X #include X #include X+#include X+#include X+#if __FreeBSD_version < 500000 X+#include X+#endif X+ X #include X #include X #include X #include X #include X #include X+#include X+ X #include X #include X X #include "kqemu-kernel.h" X X+#ifndef KQEMU_MAJOR X+#define KQEMU_MAJOR 250 X+#endif X+ X MALLOC_DECLARE(M_KQEMU); X MALLOC_DEFINE(M_KQEMU, "kqemu", "kqemu buffers"); X X+int kqemu_debug; X+SYSCTL_INT(_debug, OID_AUTO, kqemu_debug, CTLFLAG_RW, &kqemu_debug, 0, X+ "kqemu debug flag"); X+ X #define USER_BASE 0x1000 X X /* lock the page at virtual address 'user_addr' and return its X- physical page index. Return -1 if error */ X+ physical page index. Return NULL if error */ X struct kqemu_user_page *CDECL kqemu_lock_user_page(unsigned long *ppage_index, X unsigned long user_addr) X { X@@ -37,14 +60,18 @@ X vm_paddr_t pa = 0; X int ret; X pmap_t pmap; X+#if __FreeBSD_version >= 500000 X ret = vm_map_wire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER); X+#else X+ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, FALSE); X+#endif X if (ret != KERN_SUCCESS) { X- printf("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret); X+ kqemu_log("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret); X return NULL; X } X pmap = vm_map_pmap(&vm->vm_map); X pa = pmap_extract(pmap, va); X- // printf("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa); X+ /* kqemu_log("kqemu_lock_user_page(%08lx) va=%08x pa=%08x\n", user_addr, va, pa); */ X *ppage_index = pa >> PAGE_SHIFT; X return (struct kqemu_user_page *)va; X } X@@ -54,12 +81,16 @@ X struct vmspace *vm = curproc->p_vmspace; X vm_offset_t va; X int ret; X- // printf("kqemu_unlock_user_page(%08lx)\n", page_index); X+ /* kqemu_log("kqemu_unlock_user_page(%08lx)\n", page_index); */ X va = (vm_offset_t)page; X+#if __FreeBSD_version >= 500000 X ret = vm_map_unwire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER); X+#else X+ ret = vm_map_user_pageable(&vm->vm_map, va, va+PAGE_SIZE, TRUE); X+#endif X #if 0 X if (ret != KERN_SUCCESS) { X- printf("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret); X+ kqemu_log("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret); X } X #endif X } X@@ -76,20 +107,21 @@ X X va = kmem_alloc(kernel_map, PAGE_SIZE); X if (va == 0) { X- printf("kqemu_alloc_zeroed_page: NULL\n"); X- return -1; X+ kqemu_log("kqemu_alloc_zeroed_page: NULL\n"); X+ return NULL; X } X pmap = vm_map_pmap(kernel_map); X pa = pmap_extract(pmap, va); X- // printf("kqemu_alloc_zeroed_page: %08x\n", pa); X+ /* kqemu_log("kqemu_alloc_zeroed_page: %08x\n", pa); */ X *ppage_index = pa >> PAGE_SHIFT; X return (struct kqemu_page *)va; X } X X void CDECL kqemu_free_page(struct kqemu_page *page) X { X- // printf("kqemu_free_page(%08lx)\n", page_index); X- /* XXX: do it */ X+ if (kqemu_debug > 0) X+ kqemu_log("kqemu_free_page(%p)\n", page); X+ kmem_free(kernel_map, (vm_offset_t) page, PAGE_SIZE); X } X X /* return kernel address of the physical page page_index */ X@@ -103,42 +135,29 @@ X GB of physical memory */ X void * CDECL kqemu_vmalloc(unsigned int size) X { X- struct vmspace *vm = curproc->p_vmspace; X- vm_offset_t va = USER_BASE; X- int rv; X- if (size % PAGE_SIZE != 0) { X- printf("kqemu_vmalloc(%d) not a multiple of page size\n", size); X- return NULL; X- } X- rv = vm_map_find(&vm->vm_map, NULL, 0, &va, size, 1, X- VM_PROT_ALL, VM_PROT_ALL, 0); X- if (rv != KERN_SUCCESS) { X- printf("kqemu_vmalloc(%d) failed rv=%d\n", size, rv); X- return NULL; X- } X- printf("kqemu_vmalloc(%d): %08x\n", size, va); X- return (void *)va; X+ void *ptr = malloc(size, M_KQEMU, M_WAITOK); X+ if (kqemu_debug > 0) X+ kqemu_log("kqemu_vmalloc(%d): %p\n", size, ptr); X+ return ptr; X } X X void CDECL kqemu_vfree(void *ptr) X { X- printf("kqemu_vfree(%p)\n", ptr); X+ if (kqemu_debug > 0) X+ kqemu_log("kqemu_vfree(%p)\n", ptr); X+ free(ptr, M_KQEMU); X } X X /* return the physical page index for a given virtual page */ X unsigned long CDECL kqemu_vmalloc_to_phys(const void *vaddr) X { X- struct vmspace *vm = curproc->p_vmspace; X- vm_paddr_t pa; X- pmap_t pmap; X- X- pmap = vm_map_pmap(&vm->vm_map); X- pa = pmap_extract(pmap, (vm_offset_t)vaddr); X+ vm_paddr_t pa = vtophys(vaddr); X if (pa == 0) { X- printf("kqemu_vmalloc_to_phys(%p)->error\n", vaddr); X+ kqemu_log("kqemu_vmalloc_to_phys(%p)->error\n", vaddr); X return -1; X } X- printf("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa); X+ if (kqemu_debug > 0) X+ kqemu_log("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa); X return pa >> PAGE_SHIFT; X } X X@@ -154,16 +173,48 @@ X { X } X X+#if __FreeBSD_version < 500000 X+static int X+curpriority_cmp(struct proc *p) X+{ X+ int c_class, p_class; X+ X+ c_class = RTP_PRIO_BASE(curproc->p_rtprio.type); X+ p_class = RTP_PRIO_BASE(p->p_rtprio.type); X+ if (p_class != c_class) X+ return (p_class - c_class); X+ if (p_class == RTP_PRIO_NORMAL) X+ return (((int)p->p_priority - (int)curpriority) / PPQ); X+ return ((int)p->p_rtprio.prio - (int)curproc->p_rtprio.prio); X+} X+ X+/* return TRUE if a signal is pending (i.e. the guest must stop X+ execution) */ X+int CDECL kqemu_schedule(void) X+{ X+ struct proc *p = curproc; X+ if (curpriority_cmp(p) > 0) { X+ int s = splhigh(); X+ p->p_priority = MAXPRI; X+ setrunqueue(p); X+ p->p_stats->p_ru.ru_nvcsw++; X+ mi_switch(); X+ splx(s); X+ } X+ return issignal(curproc) != 0; X+} X+#else X /* return TRUE if a signal is pending (i.e. the guest must stop X execution) */ X int CDECL kqemu_schedule(void) X { X- // printf("kqemu_schedule\n"); X+ /* kqemu_log("kqemu_schedule\n"); */ X mtx_lock_spin(&sched_lock); X mi_switch(SW_VOL, NULL); X mtx_unlock_spin(&sched_lock); X return SIGPENDING(curthread); X } X+#endif X X static char log_buf[4096]; X X@@ -176,47 +227,159 @@ X va_end(ap); X } X X+#define KQEMU_MAX_INSTANCES 4 X+ X struct kqemu_instance { X- // struct semaphore sem; X+#if __FreeBSD_version >= 500000 X+ TAILQ_ENTRY(kqemu_instance) kqemu_ent; X+ struct cdev *kqemu_dev; X+#endif X+ /* struct semaphore sem; */ X struct kqemu_state *state; X }; X X+static int kqemu_ref_count = 0; X+static int max_locked_pages; X+ X+#if __FreeBSD_version < 500000 X+static dev_t kqemu_dev; X+#else X+static struct clonedevs *kqemuclones; X+static TAILQ_HEAD(,kqemu_instance) kqemuhead = TAILQ_HEAD_INITIALIZER(kqemuhead); X+static eventhandler_tag clonetag; X+#endif X+ X static d_close_t kqemu_close; X static d_open_t kqemu_open; X static d_ioctl_t kqemu_ioctl; X X static struct cdevsw kqemu_cdevsw = { X+#if __FreeBSD_version < 500000 X+ /* open */ kqemu_open, X+ /* close */ kqemu_close, X+ /* read */ noread, X+ /* write */ nowrite, X+ /* ioctl */ kqemu_ioctl, X+ /* poll */ nopoll, X+ /* mmap */ nommap, X+ /* strategy */ nostrategy, X+ /* name */ "kqemu", X+ /* maj */ KQEMU_MAJOR, X+ /* dump */ nodump, X+ /* psize */ nopsize, X+ /* flags */ 0, X+ /* bmaj */ -1 X+#else X .d_version = D_VERSION, X .d_flags = D_NEEDGIANT, X .d_open = kqemu_open, X .d_ioctl = kqemu_ioctl, X .d_close = kqemu_close, X .d_name = "kqemu" X+#endif X }; X X-/* For use with make_dev(9)/destroy_dev(9). */ X-static struct cdev *kqemu_dev; X+#if __FreeBSD_version >= 500000 X+static void X+#if __FreeBSD_version >= 600034 X+kqemu_clone(void *arg, struct ucred *cred, char *name, int namelen, X+struct cdev **dev) X+#else X+kqemu_clone(void *arg, char *name, int namelen, struct cdev **dev) X+#endif X+{ X+ int unit, r; X+ if (*dev != NULL) X+ return; X+ X+ if (strcmp(name, "kqemu") == 0) X+ unit = -1; X+ else if (dev_stdclone(name, NULL, "kqemu", &unit) != 1) X+ return; /* Bad name */ X+ if (unit != -1 && unit > KQEMU_MAX_INSTANCES) X+ return; X+ X+ r = clone_create(&kqemuclones, &kqemu_cdevsw, &unit, dev, 0); X+ if (r) { X+ *dev = make_dev(&kqemu_cdevsw, unit2minor(unit), X+ UID_ROOT, GID_WHEEL, 0660, "kqemu%d", unit); X+ if (*dev != NULL) { X+ (*dev)->si_flags |= SI_CHEAPCLONE; X+ } X+ } X+} X+#endif X+ X+static void kqemu_destroy(struct kqemu_instance *ks) X+{ X+#if __FreeBSD_version >= 500000 X+ struct cdev *dev = ks->kqemu_dev; X+#endif X+ X+ if (ks->state) { X+ kqemu_delete(ks->state); X+ ks->state = NULL; X+ } X+ X+#if __FreeBSD_version >= 500000 X+ dev->si_drv1 = NULL; X+ TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent); X+ destroy_dev(dev); X+#endif X+ free(ks, M_KQEMU); X+ --kqemu_ref_count; X+} X X /* ARGSUSED */ X static int X+#if __FreeBSD_version < 500000 X+kqemu_open(dev_t dev, int flags, int fmt __unused, struct proc *p) X+{ X+#else X kqemu_open(struct cdev *dev, int flags, int fmt __unused, X struct thread *td) X { X+ struct proc *p = td->td_proc; X+#endif X struct kqemu_instance *ks; X+ X+#if __FreeBSD_version >= 500000 X+ if (kqemu_ref_count >= KQEMU_MAX_INSTANCES) X+#else X+ if (dev->si_drv1 || kqemu_ref_count >= KQEMU_MAX_INSTANCES) X+#endif X+ return(EBUSY); X+ X+ if ((flags & (FREAD|FWRITE)) == FREAD) X+ return(EPERM); X+ X ks = malloc(sizeof(struct kqemu_instance), M_KQEMU, M_WAITOK); X if (ks == NULL) { X- printf("malloc failed\n"); X+ kqemu_log("malloc failed\n"); X return ENOMEM; X } X- ks->state = NULL; X+ memset(ks, 0, sizeof *ks); X+#if __FreeBSD_version >= 500000 X+ ks->kqemu_dev = dev; X+ TAILQ_INSERT_TAIL(&kqemuhead, ks, kqemu_ent); X+#endif X+ kqemu_ref_count++; X+ X dev->si_drv1 = ks; X+ if (kqemu_debug > 0) X+ kqemu_log("opened by pid=%d\n", p->p_pid); X return 0; X } X X /* ARGSUSED */ X static int X+#if __FreeBSD_version < 500000 X+kqemu_ioctl(dev_t dev, u_long cmd, caddr_t addr, X+ int flags __unused, struct proc *p) X+#else X kqemu_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, X int flags __unused, struct thread *td) X+#endif X { X int error = 0; X int ret; X@@ -231,8 +394,9 @@ X break; X } X d1 = *(struct kqemu_init *)addr; X- printf("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size); X- s = kqemu_init(d, 16000); X+ if (kqemu_debug > 0) X+ kqemu_log("ram_base=%p ram_size=%ld\n", d1.ram_base, d1.ram_size); X+ s = kqemu_init(d, max_locked_pages); X if (s == NULL) { X error = ENOMEM; X break; X@@ -248,9 +412,16 @@ X } X ctx = kqemu_get_cpu_state(s); X *ctx = *(struct kqemu_cpu_state *)addr; X+#if __FreeBSD_version >= 500000 X DROP_GIANT(); X+#endif X ret = kqemu_exec(s); X+#if __FreeBSD_version >= 500000 X PICKUP_GIANT(); X+ td->td_retval[0] = ret; X+#else X+ p->p_retval[0] = ret; X+#endif X *(struct kqemu_cpu_state *)addr = *ctx; X break; X } X@@ -265,10 +436,22 @@ X X /* ARGSUSED */ X static int X+#if __FreeBSD_version < 500000 X+kqemu_close(dev_t dev, int flags, int fmt __unused, struct proc *p) X+{ X+#else X kqemu_close(struct cdev *dev __unused, int flags, int fmt __unused, X struct thread *td) X { X- return 0; X+ struct proc *p = td->td_proc; X+#endif X+ struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1; X+ X+ kqemu_destroy(ks); X+ X+ if (kqemu_debug > 0) X+ kqemu_log("closed by pid=%d\n", p->p_pid); X+ return 0; X } X X /* ARGSUSED */ X@@ -276,15 +459,55 @@ X kqemu_modevent(module_t mod __unused, int type, void *data __unused) X { X int error = 0; X+#if __FreeBSD_version < 500000 X+ int rc; X+#else X+ struct kqemu_instance *ks; X+#endif X X switch (type) { X case MOD_LOAD: X printf("kqemu version 0x%08x\n", KQEMU_VERSION); X+ max_locked_pages = physmem / (2 * KQEMU_MAX_INSTANCES); X+ if (max_locked_pages > 32768) X+ max_locked_pages = 32768; X+#if __FreeBSD_version < 500000 X+ if ((rc = cdevsw_add(&kqemu_cdevsw))) { X+ kqemu_log("error registering cdevsw, rc=%d\n", rc); X+ error = ENOENT; X+ break; X+ } X kqemu_dev = make_dev(&kqemu_cdevsw, 0, X- UID_ROOT, GID_WHEEL, 0666, "kqemu"); X+ UID_ROOT, GID_WHEEL, 0660, "kqemu"); X+#else X+ clone_setup(&kqemuclones); X+ clonetag = EVENTHANDLER_REGISTER(dev_clone, kqemu_clone, 0, 1000); X+ if (!clonetag) { X+ error = ENOMEM; X+ break; X+ } X+#endif X+ kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n", X+ KQEMU_MAX_INSTANCES, max_locked_pages * 4); X+ X+ kqemu_ref_count = 0; X break; X case MOD_UNLOAD: X+ if (kqemu_ref_count > 0) { X+ error = EBUSY; X+ break; X+ } X+#if __FreeBSD_version < 500000 X destroy_dev(kqemu_dev); X+ if ((rc = cdevsw_remove(&kqemu_cdevsw))) X+ kqemu_log("error unregistering, rc=%d\n", rc); X+#else X+ EVENTHANDLER_DEREGISTER(dev_clone, clonetag); X+ while ((ks = TAILQ_FIRST(&kqemuhead)) != NULL) { X+ kqemu_destroy(ks); X+ } X+ clone_cleanup(&kqemuclones); X+#endif X break; X case MOD_SHUTDOWN: X break; END-of-kqemu-kmod/files/patch-kqemu-freebsd.c echo x - kqemu-kmod/pkg-descr sed 's/^X//' >kqemu-kmod/pkg-descr << 'END-of-kqemu-kmod/pkg-descr' XKQEMU is a qemu accelerator kernel module on x86/amd64. X XWWW: http://fabrice.bellard.free.fr/qemu/qemu-accel.html END-of-kqemu-kmod/pkg-descr exit