* [Qemu-devel] Accelerator for FreeBSD?
@ 2005-03-21 1:42 Ryan Rempel
2005-03-21 4:22 ` Mikko Työläjärvi
2005-03-21 14:57 ` KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?) Antony T Curtis
0 siblings, 2 replies; 6+ messages in thread
From: Ryan Rempel @ 2005-03-21 1:42 UTC (permalink / raw)
To: qemu-devel
There is a reference here [1] to the possibility of porting the
Accelerator to *BSD by porting a small "C stub".
Is anyone working on this at the moment? If not, would it be possible
to make the "C stub" available so that someone could give it a try?
I'd be interested in taking a crack at it myself, but there may be
others better situated (I've not done FreeBSD kernel development
before, but I have done some Darwin kernel development).
That's assuming that the reference is at all accurate :-)
[1] http://www.dad-answers.com/qemu-forum/viewtopic.php?t=333
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] Accelerator for FreeBSD?
2005-03-21 1:42 [Qemu-devel] Accelerator for FreeBSD? Ryan Rempel
@ 2005-03-21 4:22 ` Mikko Työläjärvi
2005-03-21 14:57 ` KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?) Antony T Curtis
1 sibling, 0 replies; 6+ messages in thread
From: Mikko Työläjärvi @ 2005-03-21 4:22 UTC (permalink / raw)
To: Ryan Rempel, qemu-devel
On Sun, 20 Mar 2005, Ryan Rempel wrote:
> There is a reference here [1] to the possibility of porting the
> Accelerator to *BSD by porting a small "C stub".
That would be "kmod.c".
> Is anyone working on this at the moment? If not, would it be possible
> to make the "C stub" available so that someone could give it a try?
> I'd be interested in taking a crack at it myself, but there may be
> others better situated (I've not done FreeBSD kernel development
> before, but I have done some Darwin kernel development).
>
> That's assuming that the reference is at all accurate :-)
>
> [1] http://www.dad-answers.com/qemu-forum/viewtopic.php?t=333
I've only seen this attempt:
<http://lists.gnu.org/archive/html/qemu-devel/2005-03/msg00049.html>
Which apparently needs a little more work.
$.02,
/Mikko
^ permalink raw reply [flat|nested] 6+ messages in thread
* KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?)
2005-03-21 1:42 [Qemu-devel] Accelerator for FreeBSD? Ryan Rempel
2005-03-21 4:22 ` Mikko Työläjärvi
@ 2005-03-21 14:57 ` Antony T Curtis
2005-03-23 1:27 ` Ryan Rempel
1 sibling, 1 reply; 6+ messages in thread
From: Antony T Curtis @ 2005-03-21 14:57 UTC (permalink / raw)
To: Ryan Rempel, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1371 bytes --]
On Sun, 2005-03-20 at 19:42 -0600, Ryan Rempel wrote:
> There is a reference here [1] to the possibility of porting the
> Accelerator to *BSD by porting a small "C stub".
>
> Is anyone working on this at the moment? If not, would it be possible
> to make the "C stub" available so that someone could give it a try?
> I'd be interested in taking a crack at it myself, but there may be
> others better situated (I've not done FreeBSD kernel development
> before, but I have done some Darwin kernel development).
>
> That's assuming that the reference is at all accurate :-)
>
> [1] http://www.dad-answers.com/qemu-forum/viewtopic.php?t=333
I have made some headway... The attached stub appears to work but in my
limited testing so far, it may be a bit unstable. The driver stub is for
FreeBSD 4 (tested on 4.9) and I may work on a 5.3+ one soon.
YMMV. Use with caution...
Simply copy the attached files into the same directory that the kqemu
distribution is untarred and build with
# make -f Makefile.bsd
Install with
# make -f Makefile.bsd
# kldload kqemu
You will need to create the /dev nodes
# mknod /dev/kqemu c 250 0 root:wheel
# chmod ug+rw /dev/kqemu
--
Antony T Curtis, BSc. UNIX, Linux, *BSD, Networking
antony.t.curtis@ntlworld.com C++, J2EE, Perl, MySQL, Apache
IT Consultancy.
[-- Attachment #2: Makefile.bsd --]
[-- Type: text/plain, Size: 89 bytes --]
#
KMOD= kqemu
SRCS= kqemu.h kmod_bsd.c kqemu-mod-i386.o
NOMAN=
.include <bsd.kmod.mk>
[-- Attachment #3: kmod_bsd.c --]
[-- Type: text/x-csrc, Size: 8450 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>
#include <sys/buf.h>
#include <sys/uio.h>
#include <sys/conf.h>
#include <sys/ctype.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/ioccom.h>
#include <sys/signalvar.h>
#include <sys/resourcevar.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 MALLOC_DEFINE(M_KQEMU, "KQEMU", "KQEMU Resources");
/* 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 (long)(paddr >> PAGE_SHIFT);
}
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);
}
unsigned long CDECL kqemu_alloc_zeroed_page(void)
{
void *addr;
/*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);
return ((long) addr) >> PAGE_SHIFT;
}
void CDECL kqemu_free_page(unsigned long page_index)
{
/*kqemu_log("kqemu_free_page(0x%08x)\n", page_index);*/
contigfree((void *)(page_index << PAGE_SHIFT), PAGE_SIZE, M_KQEMU);
}
void * CDECL kqemu_page_kaddr(unsigned long page_index)
{
caddr_t addr;
/*kqemu_log("kqemu_page_kaddr(0x%08x)\n", page_index);*/
addr = (caddr_t)(page_index << PAGE_SHIFT);
return (void *)addr;
}
/* 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)
{
vm_offset_t paddr = (vm_offset_t)vaddr;
return (long)(paddr >> PAGE_SHIFT);
}
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;
}
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;
static dev_t kqemu_dev;
static d_open_t kqemu_open;
static d_close_t kqemu_close;
static d_ioctl_t kqemu_ioctl;
static struct cdevsw kqemu_cdevsw = {
/* 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
};
int
kqemu_open(dev, flags, fmt, p)
dev_t dev;
int flags, fmt;
struct proc *p;
{
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;
kqemu_ref_count++;
kqemu_log("opened by pid=%d\n", p->p_pid);
return(0);
}
int
kqemu_close(dev, flags, fmt, p)
dev_t dev;
int flags, fmt;
struct proc *p;
{
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;
kqemu_ref_count--;
kqemu_log("closed by pid=%d\n", p->p_pid);
return(0);
}
int
kqemu_ioctl(dev, cmd, cmdarg, flags, p)
dev_t dev;
unsigned long cmd;
caddr_t cmdarg;
int flags;
struct proc *p;
{
struct kqemu_instance *ks = (struct kqemu_instance *) dev->si_drv1;
struct kqemu_state *s = ks->state;
long ret;
/*int error;*/
switch (cmd) {
case KQEMU_INIT:
/*kqemu_log("KQEMU_INIT data=0x%08x\n",cmdarg);*/
{
if (s)
return(EIO);
if (!(s = kqemu_init((struct kqemu_init *)cmdarg, max_locked_pages)))
return(ENOMEM);
ks->state = s;
ret = 0;
break;
}
case KQEMU_EXEC:
/*kqemu_log("KQEMU_EXEC data=0x%08x\n",cmdarg);*/
{
struct kqemu_cpu_state *ctx;
if (!s)
return(EIO);
ctx = kqemu_get_cpu_state(s);
memcpy((void *)ctx, (void *)cmdarg, sizeof(struct kqemu_cpu_state));
ret = kqemu_exec(s);
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;
ret = 0;
break;
}
default:
/*kqemu_log("ioctl unknown 0x%08x\n",cmd);*/
return(ENXIO);
}
return(ret);
}
static int
init_module(void)
{
int rc;
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);
max_locked_pages = physmem / (2 * KQEMU_MAX_INSTANCES);
if (max_locked_pages > 32768)
max_locked_pages = 32768;
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, 0600, "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)
{
int rc;
destroy_dev(kqemu_dev);
if ((rc = cdevsw_remove(&kqemu_cdevsw)))
kqemu_log("error unregistering, rc=%d\n", rc);
}
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] 6+ messages in thread
* Re: KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?)
2005-03-21 14:57 ` KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?) Antony T Curtis
@ 2005-03-23 1:27 ` Ryan Rempel
2005-03-23 12:15 ` Antony T Curtis
2005-03-23 13:58 ` Antony T Curtis
0 siblings, 2 replies; 6+ messages in thread
From: Ryan Rempel @ 2005-03-23 1:27 UTC (permalink / raw)
To: Antony T Curtis; +Cc: qemu-devel
On Mon, 21 Mar 2005 14:57:33 +0000, Antony T Curtis
<antony.t.curtis@ntlworld.com> wrote:
> On Sun, 2005-03-20 at 19:42 -0600, Ryan Rempel wrote:
> > There is a reference here [1] to the possibility of porting the
> > Accelerator to *BSD by porting a small "C stub".
> >
> > Is anyone working on this at the moment?
> I have made some headway... The attached stub appears to work but in my
> limited testing so far, it may be a bit unstable. The driver stub is for
> FreeBSD 4 (tested on 4.9) and I may work on a 5.3+ one soon.
Thanks! I would need one that works with 5.3 -- I'll take a look when
I get a chance and see what I can figure out.
When you say "a bit unstable", do you mean unstable for the guest OS
or unstable for the host as well? Just curious ...
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?)
2005-03-23 1:27 ` Ryan Rempel
@ 2005-03-23 12:15 ` Antony T Curtis
2005-03-23 13:58 ` Antony T Curtis
1 sibling, 0 replies; 6+ messages in thread
From: Antony T Curtis @ 2005-03-23 12:15 UTC (permalink / raw)
To: Ryan Rempel; +Cc: qemu-devel
On Tue, 2005-03-22 at 19:27 -0600, Ryan Rempel wrote:
> On Mon, 21 Mar 2005 14:57:33 +0000, Antony T Curtis
> <antony.t.curtis@ntlworld.com> wrote:
>
> > On Sun, 2005-03-20 at 19:42 -0600, Ryan Rempel wrote:
> > > There is a reference here [1] to the possibility of porting the
> > > Accelerator to *BSD by porting a small "C stub".
> > >
> > > Is anyone working on this at the moment?
>
> > I have made some headway... The attached stub appears to work but in my
> > limited testing so far, it may be a bit unstable. The driver stub is for
> > FreeBSD 4 (tested on 4.9) and I may work on a 5.3+ one soon.
>
> Thanks! I would need one that works with 5.3 -- I'll take a look when
> I get a chance and see what I can figure out.
>
> When you say "a bit unstable", do you mean unstable for the guest OS
> or unstable for the host as well? Just curious ...
Unstable for the host - but since I am using a fairly old FreeBSD, it
could be partly to blame. I'll need to see if it misbehaves as much on
4-STABLE.
It seems to work fine, until the guest tries to change video mode (going
from text to graphics) - this behaviour happens with Windows, Linux and
OS/2 as guest - at which time, the host experiences a sudden reset.
I have FreeBSD 5 which I will get up to date and then try out... I am
also going to try setting up the guest as a text-only setup and use
xdm...
--
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] 6+ messages in thread
* Re: KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?)
2005-03-23 1:27 ` Ryan Rempel
2005-03-23 12:15 ` Antony T Curtis
@ 2005-03-23 13:58 ` Antony T Curtis
1 sibling, 0 replies; 6+ messages in thread
From: Antony T Curtis @ 2005-03-23 13:58 UTC (permalink / raw)
To: Ryan Rempel; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1028 bytes --]
On Tue, 2005-03-22 at 19:27 -0600, Ryan Rempel wrote:
> On Mon, 21 Mar 2005 14:57:33 +0000, Antony T Curtis
> <antony.t.curtis@ntlworld.com> wrote:
>
> > On Sun, 2005-03-20 at 19:42 -0600, Ryan Rempel wrote:
> > > There is a reference here [1] to the possibility of porting the
> > > Accelerator to *BSD by porting a small "C stub".
> > >
> > > Is anyone working on this at the moment?
>
> > I have made some headway... The attached stub appears to work but in my
> > limited testing so far, it may be a bit unstable. The driver stub is for
> > FreeBSD 4 (tested on 4.9) and I may work on a 5.3+ one soon.
>
> Thanks! I would need one that works with 5.3 -- I'll take a look when
> I get a chance and see what I can figure out.
Okay - the new files compile on both 4.9 and 5.3, currently untested on
5.3. YMMV.
Enjoy!
--
Antony T Curtis, BSc. UNIX, Linux, *BSD, Networking
antony.t.curtis@ntlworld.com C++, J2EE, Perl, MySQL, Apache
IT Consultancy.
[-- Attachment #2: Makefile.bsd --]
[-- Type: text/plain, Size: 89 bytes --]
#
KMOD= kqemu
SRCS= kqemu.h kmod_bsd.c kqemu-mod-i386.o
NOMAN=
.include <bsd.kmod.mk>
[-- Attachment #3: kmod_bsd.c --]
[-- Type: text/x-csrc, Size: 9898 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>
#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 MALLOC_DEFINE(M_KQEMU, "KQEMU", "KQEMU Resources");
/* 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 (long)(paddr >> PAGE_SHIFT);
}
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);
}
unsigned long CDECL kqemu_alloc_zeroed_page(void)
{
void *addr;
/*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);
return ((long) addr) >> PAGE_SHIFT;
}
void CDECL kqemu_free_page(unsigned long page_index)
{
/*kqemu_log("kqemu_free_page(0x%08x)\n", page_index);*/
contigfree((void *)(page_index << PAGE_SHIFT), PAGE_SIZE, M_KQEMU);
}
void * CDECL kqemu_page_kaddr(unsigned long page_index)
{
caddr_t addr;
/*kqemu_log("kqemu_page_kaddr(0x%08x)\n", page_index);*/
addr = (caddr_t)(page_index << PAGE_SHIFT);
return (void *)addr;
}
/* 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)
{
vm_offset_t paddr = (vm_offset_t)vaddr;
return (long)(paddr >> PAGE_SHIFT);
}
#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 = 0, sig;
PROC_LOCK(p);
mtx_lock(&p->p_sigacts->ps_mtx);
if ((rc = ((sig= cursig(td)) != 0))) {
do {
postsig(sig);
} while ((sig= 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;
kqemu_ref_count++;
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;
kqemu_ref_count--;
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;*/
switch (cmd) {
case KQEMU_INIT:
/*kqemu_log("KQEMU_INIT data=0x%08x\n",cmdarg);*/
{
if (s)
return(EIO);
if (!(s = kqemu_init((struct kqemu_init *)cmdarg, max_locked_pages)))
return(ENOMEM);
ks->state = s;
ret = 0;
break;
}
case KQEMU_EXEC:
/*kqemu_log("KQEMU_EXEC data=0x%08x\n",cmdarg);*/
{
struct kqemu_cpu_state *ctx;
if (!s)
return(EIO);
ctx = kqemu_get_cpu_state(s);
memcpy((void *)ctx, (void *)cmdarg, sizeof(struct kqemu_cpu_state));
ret = kqemu_exec(s);
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;
ret = 0;
break;
}
default:
/*kqemu_log("ioctl unknown 0x%08x\n",cmd);*/
return(ENXIO);
}
return(ret);
}
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);
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, 0600, "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
}
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] 6+ messages in thread
end of thread, other threads:[~2005-03-23 14:19 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-21 1:42 [Qemu-devel] Accelerator for FreeBSD? Ryan Rempel
2005-03-21 4:22 ` Mikko Työläjärvi
2005-03-21 14:57 ` KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?) Antony T Curtis
2005-03-23 1:27 ` Ryan Rempel
2005-03-23 12:15 ` Antony T Curtis
2005-03-23 13:58 ` Antony T Curtis
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).