qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
@ 2005-03-23 19:29 Pierre Beyssac
  2005-03-24  1:35 ` Antony T Curtis
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Beyssac @ 2005-03-23 19:29 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 872 bytes --]

Hello,

I have written a kqemu wrapper for FreeBSD 5.x (attached). It seems
to work (I've had no crash at all) but it's alpha quality and it
currently lacks working kqemu_free_page() and kqemu_vfree() hooks
(which were never called by kqemu-mid-i386.o in my tests).

I would be interested in any comments. It's substantially different
from the code posted here by Antony T Curtis.

I have also attached a patch to qemu/osdep.c to replace the mmaped
"swap" file with a MAP_ANON area; using a file is unnecessary under
FreeBSD; perhaps it's been done this way due to Linux peculiarities,
but I don't see why. The patch doesn't help performance noticeably
but it saves some precious disk or ramdisk space.
-- 
A: Yes.					  Pierre Beyssac pb@freebsd.org
>Q: Are you sure?
>>A: Because it reverses the logical flow of conversation.
>>>Q: Why is top posting annoying in email?

[-- Attachment #2: kmod-freebsd.c --]
[-- Type: text/plain, Size: 7367 bytes --]

/* $Id: kmod-freebsd.c,v 1.3 2005/03/23 17:53:24 pb Exp $ */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/ioccom.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#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 <machine/vmparam.h>
#include <machine/stdarg.h>

#define __KERNEL__

#include "kqemu.h"

MALLOC_DECLARE(M_KQEMU);
MALLOC_DEFINE(M_KQEMU, "kqemu", "kqemu buffers");

#define	USER_BASE	0x1000

/* quick and dirty convert a physical address to a virtual address */
static vm_offset_t pa_to_va(vm_paddr_t pa, vm_offset_t beg, vm_offset_t end)
{
    struct vmspace *vm = curproc->p_vmspace;
    vm_offset_t va;
    pmap_t pmap;
    pmap = vm_map_pmap(&vm->vm_map);
    for (va = beg; va != end; va += PAGE_SIZE)
	if (pa == pmap_extract(pmap, va))
	    return va;
    printf("pa_to_va failed: pa=%08x\n", pa);
    return -1;
}

/* lock the page at virtual address 'user_addr' and return its
   physical page index. Return -1 if error */
unsigned long CDECL kqemu_lock_user_page(unsigned long user_addr)
{
    struct vmspace *vm = curproc->p_vmspace;
    vm_offset_t va = user_addr;
    vm_paddr_t pa = 0;
    int ret;
    pmap_t pmap;
    ret = vm_map_wire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
    if (ret != KERN_SUCCESS) {
	printf("kqemu_lock_user_page(%08lx) failed, ret=%d\n", user_addr, ret);
	return -1;
    }
    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);
    return pa >> PAGE_SHIFT;
}

void CDECL kqemu_unlock_user_page(unsigned long page_index)
{
    struct vmspace *vm = curproc->p_vmspace;
    vm_offset_t va;
    int ret;
    // printf("kqemu_unlock_user_page(%08lx)\n", page_index);
    va = pa_to_va(page_index << PAGE_SHIFT, USER_BASE, KERNBASE);
    ret = vm_map_unwire(&vm->vm_map, va, va+PAGE_SIZE, VM_MAP_WIRE_USER);
    if (ret != KERN_SUCCESS) {
	printf("kqemu_unlock_user_page(%08lx) failed, ret=%d\n", page_index, ret);
    }
}

/*
 * Allocate a new page. The page must be mapped in the kernel space.
 * Return the page_index or -1 if error.
 */
unsigned long CDECL kqemu_alloc_zeroed_page(void)
{
    pmap_t pmap;
    vm_offset_t va;
    vm_paddr_t pa;

    va = kmem_alloc(kernel_map, PAGE_SIZE);
    if (va == 0) {
	printf("kqemu_alloc_zeroed_page: NULL\n");
	return -1;
    }
    pmap = vm_map_pmap(kernel_map);
    pa = pmap_extract(pmap, va);
    // printf("kqemu_alloc_zeroed_page: %08x\n", pa);
    return pa >> PAGE_SHIFT;
}

void CDECL kqemu_free_page(unsigned long page_index)
{
    printf("kqemu_free_page(%08lx)\n", page_index);
}

/* return kernel address of the physical page page_index */
void *CDECL kqemu_page_kaddr(unsigned long page_index)
{
    vm_offset_t va;
    va = pa_to_va(page_index << PAGE_SHIFT, KERNBASE, 0);
    if (va != -1) {
	printf("kqemu_page_kaddr(%08lx)=%08x\n", page_index, va);
	return (void *)va;
    }
    printf("kqemu_page_kaddr(%08lx)=NOT FOUND\n", page_index);
    return NULL;
}

/* contraint: each page of the vmalloced area must be in the first 4
   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 CDECL kqemu_vfree(void *ptr)
{
    printf("kqemu_vfree(%p)\n", ptr);
}

/* 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);
    if (pa == 0) {
	printf("kqemu_vmalloc_to_phys(%p)->error\n", vaddr);
	return -1;
    }
    printf("kqemu_vmalloc_to_phys(%p)->%08x\n", vaddr, pa);
    return pa >> PAGE_SHIFT;
}

/* return TRUE if a signal is pending (i.e. the guest must stop
   execution) */
int CDECL kqemu_schedule(void)
{
    // printf("kqemu_schedule\n");
    mtx_lock_spin(&sched_lock);
    mi_switch(SW_VOL, NULL);
    mtx_unlock_spin(&sched_lock);
    return SIGPENDING(curthread);
}

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);
}

struct kqemu_instance { 
    //    struct semaphore sem;  
    struct kqemu_state *state;
};

static d_close_t kqemu_close;
static d_open_t kqemu_open;
static d_ioctl_t kqemu_ioctl;

static struct cdevsw kqemu_cdevsw = {
	.d_version =	D_VERSION,
	.d_flags =	D_NEEDGIANT,
	.d_open =	kqemu_open,
	.d_ioctl =	kqemu_ioctl,
	.d_close =	kqemu_close,
	.d_name =	"kqemu"
};

/* For use with make_dev(9)/destroy_dev(9). */
static struct cdev *kqemu_dev;

/* ARGSUSED */
static int
kqemu_open(struct cdev *dev, int flags, int fmt __unused,
    struct thread *td)
{
    struct kqemu_instance *ks;
    ks = malloc(sizeof(struct kqemu_instance), M_KQEMU, M_WAITOK);
    if (ks == NULL) {
	printf("malloc failed\n");
	return ENOMEM;
    }
    ks->state = NULL;
    dev->si_drv1 = ks;
    return 0;
}

/* ARGSUSED */
static int
kqemu_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, 
    int flags __unused, struct thread *td)
{
    int error = 0;
    int ret;
    struct kqemu_instance *ks = dev->si_drv1;
    struct kqemu_state *s = ks->state;

    switch(cmd) {
    case KQEMU_INIT: {
	struct kqemu_init d1, *d = &d1;
	if (s != NULL) {
	    error = EIO;
	    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 (s == NULL) {
	    error = ENOMEM;
	    break;
	}
	ks->state = s;
	break;
    }
    case KQEMU_EXEC: {
	struct kqemu_cpu_state *ctx;
	if (s == NULL) {
	    error = EIO;
	    break;
	}
	ctx = kqemu_get_cpu_state(s);
	*ctx = *(struct kqemu_cpu_state *)addr;
	DROP_GIANT();
	ret = kqemu_exec(s);
	PICKUP_GIANT();
	td->td_retval[0] = ret;
	*(struct kqemu_cpu_state *)addr = *ctx;
	break;
    }
    case KQEMU_GET_VERSION:
	*(int *)addr = KQEMU_VERSION;
	break;
    default:
	error = EINVAL;
    }
    return error;
}

/* ARGSUSED */
static int
kqemu_close(struct cdev *dev __unused, int flags, int fmt __unused,
    struct thread *td)
{
	return 0;
}

/* ARGSUSED */
static int
kqemu_modevent(module_t mod __unused, int type, void *data __unused)
{
    int error = 0;

    switch (type) {
    case MOD_LOAD:
	printf("kqemu version 0x%08x\n", KQEMU_VERSION);
	kqemu_dev = make_dev(&kqemu_cdevsw, 0,
			     UID_ROOT, GID_WHEEL, 0666, "kqemu");
	break;
    case MOD_UNLOAD:
	destroy_dev(kqemu_dev);
	break;
    case MOD_SHUTDOWN:
	break;
    default:
	error = EOPNOTSUPP;
	break;
    }
    return (error);
}

DEV_MODULE(kqemu, kqemu_modevent, NULL);
MODULE_VERSION(kqemu, 1);

[-- Attachment #3: Makefile --]
[-- Type: text/plain, Size: 135 bytes --]

# $Id: Makefile,v 1.1.1.1 2005/03/23 12:29:35 pb Exp $
KMOD=	kqemu
SRCS=	kmod-freebsd.c
OBJS=	kqemu-mod-i386.o

.include <bsd.kmod.mk>

[-- Attachment #4: patch-osdep.c --]
[-- Type: text/plain, Size: 820 bytes --]

--- osdep.c.orig	Mon Feb 21 21:10:36 2005
+++ osdep.c	Wed Mar 23 18:10:33 2005
@@ -321,6 +321,7 @@
     char phys_ram_file[1024];
     void *ptr;
 
+#if 0
     if (phys_ram_fd < 0) {
         tmpdir = getenv("QEMU_TMPDIR");
         if (!tmpdir)
@@ -349,12 +350,20 @@
         }
         unlink(phys_ram_file);
     }
+#endif
     size = (size + 4095) & ~4095;
+#if 0
     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);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
  2005-03-23 19:29 [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch Pierre Beyssac
@ 2005-03-24  1:35 ` Antony T Curtis
  2005-03-24  1:51   ` Antony T Curtis
  0 siblings, 1 reply; 7+ messages in thread
From: Antony T Curtis @ 2005-03-24  1:35 UTC (permalink / raw)
  To: qemu-devel

On Wed, 2005-03-23 at 20:29 +0100, Pierre Beyssac wrote:
> Hello,
> 
> I have written a kqemu wrapper for FreeBSD 5.x (attached). It seems
> to work (I've had no crash at all) but it's alpha quality and it
> currently lacks working kqemu_free_page() and kqemu_vfree() hooks
> (which were never called by kqemu-mid-i386.o in my tests).

<snip>

This is the great thing about opensource - theres often more than one
way to do things.

The latest iteration of my code is attached and it does work on both
FreeBSD 4.9 and FreeBSD 5.3 - except that OS/2 Warp 4 doesn't seem to
like running with kqemu.

This version seems a lot more stable, I guess someone is going to have
to decide which is the better wrapper.

-- 
Antony T Curtis, BSc.                   UNIX, Linux, *BSD, Networking
antony.t.curtis@ntlworld.com            C++, J2EE, Perl, MySQL, Apache
                                        IT Consultancy.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
  2005-03-24  1:35 ` Antony T Curtis
@ 2005-03-24  1:51   ` Antony T Curtis
  0 siblings, 0 replies; 7+ messages in thread
From: Antony T Curtis @ 2005-03-24  1:51 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

On Thu, 2005-03-24 at 01:35 +0000, Antony T Curtis wrote:
> On Wed, 2005-03-23 at 20:29 +0100, Pierre Beyssac wrote:
> > Hello,
> > 
> > I have written a kqemu wrapper for FreeBSD 5.x (attached). It seems
> > to work (I've had no crash at all) but it's alpha quality and it
> > currently lacks working kqemu_free_page() and kqemu_vfree() hooks
> > (which were never called by kqemu-mid-i386.o in my tests).
> 
> <snip>
> 
> This is the great thing about opensource - theres often more than one
> way to do things.
> 
> The latest iteration of my code is attached and it does work on both
> FreeBSD 4.9 and FreeBSD 5.3 - except that OS/2 Warp 4 doesn't seem to
> like running with kqemu.
> 
> This version seems a lot more stable, I guess someone is going to have
> to decide which is the better wrapper.

Heh,,, I guess it would actually help if I attached the file.

-- 
Antony T Curtis, BSc.                   UNIX, Linux, *BSD, Networking
antony.t.curtis@ntlworld.com            C++, J2EE, Perl, MySQL, Apache
                                        IT Consultancy.

[-- Attachment #2: kmod_bsd.c --]
[-- Type: text/x-csrc, Size: 13055 bytes --]

/*
 * 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);


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
@ 2005-03-25  9:15 ecs user
  2005-03-25  9:49 ` Antony T Curtis
  0 siblings, 1 reply; 7+ messages in thread
From: ecs user @ 2005-03-25  9:15 UTC (permalink / raw)
  To: qemu-devel


> From: Antony T Curtis <antony.t.curtis@ntlworld.com>
> The latest iteration of my code is attached and it
> does > work on both FreeBSD 4.9 and FreeBSD 5.3 -
> except that OS/2 Warp 4 doesn't seem to like
> running with kqemu.

Antony do you know how to fix the OS/2 Warp4 problems?

I have a several IBM OS2 Warp 4 MCP2 base images that
I can not get to run. 

One is a test image of only 10MB put it still has OS/2
full WorkPlace Shell desktop. I could send you, or
anyone else that is interested, the image if you know
how to debug the QEMU issues.


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
  2005-03-25  9:15 ecs user
@ 2005-03-25  9:49 ` Antony T Curtis
  2005-03-25 11:48   ` Hetz Ben Hamo
  0 siblings, 1 reply; 7+ messages in thread
From: Antony T Curtis @ 2005-03-25  9:49 UTC (permalink / raw)
  To: qemu-devel

On Fri, 2005-03-25 at 01:15 -0800, ecs user wrote:
> > From: Antony T Curtis <antony.t.curtis@ntlworld.com>
> > The latest iteration of my code is attached and it
> > does > work on both FreeBSD 4.9 and FreeBSD 5.3 -
> > except that OS/2 Warp 4 doesn't seem to like
> > running with kqemu.
> 
> Antony do you know how to fix the OS/2 Warp4 problems?
> 
> I have a several IBM OS2 Warp 4 MCP2 base images that
> I can not get to run. 

I have Warp 4 with full WPS running fine on current CVS of QEMU - but
only in VGA mode - I cannot get the Cirrus Logic video drivers to
recognise the emulated card - I'll try with SciTech's driver someday
soon.

Since OS/2 works without KQEMU, I figure that theres something in KQEMU
which is causing the fault.

> One is a test image of only 10MB put it still has OS/2
> full WorkPlace Shell desktop. I could send you, or
> anyone else that is interested, the image if you know
> how to debug the QEMU issues.
> 
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam protection around 
> http://mail.yahoo.com 
> 
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
-- 
Antony T Curtis, BSc.                   UNIX, Linux, *BSD, Networking
antony.t.curtis@ntlworld.com            C++, J2EE, Perl, MySQL, Apache
                                        IT Consultancy.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
  2005-03-25  9:49 ` Antony T Curtis
@ 2005-03-25 11:48   ` Hetz Ben Hamo
  0 siblings, 0 replies; 7+ messages in thread
From: Hetz Ben Hamo @ 2005-03-25 11:48 UTC (permalink / raw)
  To: qemu-devel

I think that in this issue, it's KQEMU's fault, not your wrapper
stuff, since it does have the same problems with windows 9x/ME.

Thanks,
Hetz

On Fri, 25 Mar 2005 09:49:04 +0000, Antony T Curtis
<antony.t.curtis@ntlworld.com> wrote:
> On Fri, 2005-03-25 at 01:15 -0800, ecs user wrote:
> > > From: Antony T Curtis <antony.t.curtis@ntlworld.com>
> > > The latest iteration of my code is attached and it
> > > does > work on both FreeBSD 4.9 and FreeBSD 5.3 -
> > > except that OS/2 Warp 4 doesn't seem to like
> > > running with kqemu.
> >
> > Antony do you know how to fix the OS/2 Warp4 problems?
> >
> > I have a several IBM OS2 Warp 4 MCP2 base images that
> > I can not get to run.
> 
> I have Warp 4 with full WPS running fine on current CVS of QEMU - but
> only in VGA mode - I cannot get the Cirrus Logic video drivers to
> recognise the emulated card - I'll try with SciTech's driver someday
> soon.
> 
> Since OS/2 works without KQEMU, I figure that theres something in KQEMU
> which is causing the fault.
> 
> > One is a test image of only 10MB put it still has OS/2
> > full WorkPlace Shell desktop. I could send you, or
> > anyone else that is interested, the image if you know
> > how to debug the QEMU issues.
> >
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Tired of spam?  Yahoo! Mail has the best spam protection around
> > http://mail.yahoo.com
> >
> >
> > _______________________________________________
> > Qemu-devel mailing list
> > Qemu-devel@nongnu.org
> > http://lists.nongnu.org/mailman/listinfo/qemu-devel
> --
> Antony T Curtis, BSc.                   UNIX, Linux, *BSD, Networking
> antony.t.curtis@ntlworld.com            C++, J2EE, Perl, MySQL, Apache
>                                         IT Consultancy.
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch
@ 2005-03-25 13:50 ecs user
  0 siblings, 0 replies; 7+ messages in thread
From: ecs user @ 2005-03-25 13:50 UTC (permalink / raw)
  To: qemu-devel


> From: Antony T Curtis <antony.t.curtis@ntlworld.com>
> I have Warp 4 with full WPS running fine on current
> CVS of QEMU - but only in VGA mode - I cannot get
the
> Cirrus Logic video drivers to recognise the emulated

> card - I'll try with SciTech's driver someday soon.

My image had the video working at 1024x768 resolution

Could you test my image?

thanks



		
__________________________________ 
Do you Yahoo!? 
Make Yahoo! your home page 
http://www.yahoo.com/r/hs

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-03-25 14:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-23 19:29 [Qemu-devel] kqemu port to FreeBSD 5.x + qemu patch Pierre Beyssac
2005-03-24  1:35 ` Antony T Curtis
2005-03-24  1:51   ` Antony T Curtis
  -- strict thread matches above, loose matches on Subject: below --
2005-03-25  9:15 ecs user
2005-03-25  9:49 ` Antony T Curtis
2005-03-25 11:48   ` Hetz Ben Hamo
2005-03-25 13:50 ecs user

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).