From: Antony T Curtis <antony.t.curtis@ntlworld.com>
To: Ryan Rempel <rgrempel@gmail.com>, qemu-devel@nongnu.org
Subject: KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?)
Date: Mon, 21 Mar 2005 14:57:33 +0000 [thread overview]
Message-ID: <1111417053.397.7.camel@pcgem.xiphis.org> (raw)
In-Reply-To: <fb5ec42305032017423b7e66a2@mail.gmail.com>
[-- 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);
next prev parent reply other threads:[~2005-03-21 15:19 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2005-03-23 1:27 ` KQEMU on FreeBSD partially works. (Was: [Qemu-devel] Accelerator for FreeBSD?) Ryan Rempel
2005-03-23 12:15 ` Antony T Curtis
2005-03-23 13:58 ` Antony T Curtis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1111417053.397.7.camel@pcgem.xiphis.org \
--to=antony.t.curtis@ntlworld.com \
--cc=qemu-devel@nongnu.org \
--cc=rgrempel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.