(the diff for the qemu main program will come in the next message)
This is a tentative port of the kqemu accelerator module to OpenBSD.
It seems to work, i. e. not worse than the similar module on linux.
To build the lkm, you should do a
$ ./configure
$ make -f Makefile.openbsd
The load it, you should do a 'make -f Makefile.openbsd load' as root,
at security level = 0.
If you make the kqemu-openbsd.sh script executable, it will be
called by modload to create a /dev/kqemu device with the correct
major number, and a 'kqemu' group to own it.
To use the accelerator, you have to add yourself to that group.
Adi
-------------------------------
diff -Nrup a/Makefile.openbsd kqemu-1.3.0pre11/Makefile.openbsd
--- a/Makefile.openbsd Thu Jan 1 02:00:00 1970
+++ kqemu-1.3.0pre11/Makefile.openbsd Wed Oct 24 20:01:12 2007
@@ -0,0 +1,22 @@
+CFLAGS += -Wall
+NOMAN = noman
+
+POSTINSTALL = kqemu-openbsd.sh
+COMMON = kqemu-mod-i386.o
+SRCS = kqemu-openbsd.c
+OBJS = $(COMMON)
+LKM = kqemu
+COMBINED = kqemu.o
+
+.include <bsd.lkm.mk>
+
+$(COMMON):
+ gmake -C common all
+tests:
+ gmake -C tests all
+ tests/kqemutest
+clean: common.clean tests.clean
+common.clean:
+ gmake -C common clean
+tests.clean:
+ gmake -C tests clean
diff -Nrup a/common/Makefile kqemu-1.3.0pre11/common/Makefile
--- a/common/Makefile Tue Feb 6 23:02:00 2007
+++ kqemu-1.3.0pre11/common/Makefile Wed Oct 24 20:01:12 2007
@@ -41,7 +41,7 @@ LD=ld
endif
DEFINES=-D__KERNEL__
-INCLUDES=-nostdinc -iwithprefix include -I. -I..
+INCLUDES=-I. -I..
TOOLS_CFLAGS=-Wall -O2 -Werror -g
COMMON_CFLAGS=-Wall -O2 -fomit-frame-pointer -fno-strict-aliasing -Werror
ifeq ($(ARCH), x86_64)
diff -Nrup a/configure kqemu-1.3.0pre11/configure
--- a/configure Tue Feb 6 23:02:00 2007
+++ kqemu-1.3.0pre11/configure Wed Oct 24 20:05:56 2007
@@ -112,6 +112,9 @@ oss="yes"
OpenBSD)
bsd="yes"
oss="yes"
+if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+ kqemu="yes"
+fi
;;
Darwin)
bsd="yes"
diff -Nrup a/kqemu-openbsd.c kqemu-1.3.0pre11/kqemu-openbsd.c
--- a/kqemu-openbsd.c Thu Jan 1 02:00:00 1970
+++ kqemu-1.3.0pre11/kqemu-openbsd.c Wed Oct 24 20:01:13 2007
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2007 Enache Adrian <[EMAIL PROTECTED]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/lkm.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/stdarg.h>
+#include <uvm/uvm.h>
+#include "kqemu-kernel.h"
+
+struct kqemu_page* CDECL
+kqemu_alloc_zeroed_page(unsigned long *ppage_index)
+{
+ vaddr_t va;
+ paddr_t pa;
+ if(!(va = uvm_km_zalloc(kernel_map, PAGE_SIZE)))
+ return 0;
+ pmap_extract(pmap_kernel(), va, &pa);
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_page*)va;
+}
+
+void CDECL
+kqemu_free_page(struct kqemu_page *page)
+{
+ uvm_km_free(kernel_map, (vaddr_t)page, PAGE_SIZE);
+}
+
+void* CDECL
+kqemu_io_map(unsigned long page_index, unsigned int size)
+{
+ return 0; /*XXX*/
+}
+
+void CDECL
+kqemu_io_unmap(void *ptr, unsigned int size)
+{
+ /*XXX*/
+}
+
+struct kqemu_user_page *CDECL
+kqemu_lock_user_page(unsigned long *ppage_index, unsigned long user_addr)
+{
+ vaddr_t va = (vaddr_t)user_addr;
+ vm_map_t map = &curproc->p_vmspace->vm_map;
+ paddr_t pa;
+ if(uvm_map_pageable(map, va, va + PAGE_SIZE, FALSE, 0))
+ return 0;
+ pmap_extract(vm_map_pmap(map), va, &pa);
+ *ppage_index = pa >> PAGE_SHIFT;
+ return (struct kqemu_user_page*)va;
+}
+
+void CDECL
+kqemu_log(const char *fmt, ...)
+{
+ va_list va;
+ printf("kqemu: ");
+ va_start(va, fmt); vprintf(fmt, va); va_end(va);
+}
+
+void * CDECL
+kqemu_page_kaddr(struct kqemu_page *page)
+{
+ return page; /*XXX*/
+}
+
+int CDECL
+kqemu_schedule(void)
+{
+ return CURSIG(curproc); /*XXX*/
+}
+
+void CDECL
+kqemu_unlock_user_page(struct kqemu_user_page *page)
+{
+ vaddr_t va = (vaddr_t)page;
+ vm_map_t map = &curproc->p_vmspace->vm_map;
+ if(uvm_map_pageable(map, va, va + PAGE_SIZE, TRUE, 0))
+ printf("kqemu: failed to unwire page at 0x%08lx\n", va);
+}
+
+void CDECL kqemu_vfree(void *ptr)
+{
+ free(ptr, M_TEMP);
+}
+
+void* CDECL
+kqemu_vmalloc(unsigned int size)
+{
+ return malloc(size, M_TEMP, M_WAITOK);
+}
+
+unsigned long CDECL
+kqemu_vmalloc_to_phys(const void *vaddr)
+{
+ return vtophys((vaddr_t)vaddr) >> PAGE_SHIFT;
+}
+
+/* /dev/kqemu device operations */
+
+#define QEMU_MAGIC 0x554d4551
+struct kqemu_instance {
+ int magic;
+ struct kqemu_state *state;
+};
+
+static struct kqemu_global_state *kqemu_gs;
+
+static int
+kqemuopen(dev_t dev, int flag, int devtype, struct proc* p)
+{
+ struct kqemu_instance *ks;
+ if ((flag & (FREAD|FWRITE)) == FREAD)
+ return EPERM;
+ if(p->p_emuldata)
+ return EBUSY;
+ if(!(ks = malloc(sizeof *ks, M_EMULDATA, M_WAITOK)))
+ return ENOMEM;
+ ks->magic = QEMU_MAGIC;
+ ks->state = 0;
+ p->p_emuldata = ks;
+ return 0;
+}
+
+static int
+kqemuclose(dev_t dev, int flag, int devtype, struct proc* p)
+{
+ struct kqemu_instance *ks = p->p_emuldata;
+ if(!ks || ks->magic != QEMU_MAGIC){
+ printf("kqemu: the kqemu instance was lost\n");
+ return EIO;
+ }
+ if(ks->state) kqemu_delete(ks->state);
+ free(ks, M_EMULDATA);
+ p->p_emuldata = 0;
+ return 0;
+}
+
+static int
+kqemuioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ struct kqemu_cpu_state *ctx;
+ struct kqemu_instance *ks = p->p_emuldata;
+ if(!ks || ks->magic != QEMU_MAGIC){
+ printf("kqemu: the kqemu instance was lost\n");
+ return EIO;
+ }
+ switch(cmd){
+ case KQEMU_INIT:
+ if(ks->state) return EIO;
+ ks->state = kqemu_init((struct kqemu_init*)data, kqemu_gs);
+ if(!ks->state) return ENOMEM;
+ break;
+ case KQEMU_EXEC:
+ if(!ks->state) return EIO;
+ ctx = kqemu_get_cpu_state(ks->state);
+ *ctx = *(struct kqemu_cpu_state*)data;
+ KERNEL_PROC_UNLOCK(p);
+ kqemu_exec(ks->state);
+ KERNEL_PROC_LOCK(p);
+ *(struct kqemu_cpu_state*)data = *ctx;
+ break;
+ case KQEMU_GET_VERSION:
+ *(int*)data = KQEMU_VERSION;
+ break;
+ default:
+ return ENOTTY;
+ }
+ return 0;
+}
+
+static struct cdevsw kqemu_cdevsw = {
+ kqemuopen,
+ kqemuclose,
+ (dev_type_read((*)))enodev,
+ (dev_type_write((*)))enodev,
+ kqemuioctl,
+ (dev_type_stop((*)))enodev,
+ 0,
+ seltrue,
+ (dev_type_mmap((*)))enodev,
+};
+
+MOD_DEV("kqemu", LM_DT_CHAR, -1, &kqemu_cdevsw);
+int lkmexists(struct lkm_table *);
+
+static int
+kqemu_mod(struct lkm_table *lkmtp, int cmd)
+{
+ int max_locked_pages = physmem / 2;
+ switch(cmd){
+ case LKM_E_LOAD:
+ if(lkmexists(lkmtp))
+ return EEXIST;
+ kqemu_gs = kqemu_global_init(max_locked_pages);
+ printf("kqemu: kqemu version 0x%08x loaded,"
+ " max locked mem=%dkB\n",
+ KQEMU_VERSION, max_locked_pages << (PAGE_SHIFT - 10));
+ break;
+ case LKM_E_UNLOAD:
+ kqemu_global_delete(kqemu_gs);
+ break;
+ }
+ return 0;
+}
+
+int
+kqemu(struct lkm_table *lkmtp, int cmd, int ver)
+{
+ DISPATCH(lkmtp, cmd, ver, kqemu_mod, kqemu_mod, lkm_nofunc);
+}
diff -Nrup a/kqemu-openbsd.sh kqemu-1.3.0pre11/kqemu-openbsd.sh
--- a/kqemu-openbsd.sh Thu Jan 1 02:00:00 1970
+++ kqemu-1.3.0pre11/kqemu-openbsd.sh Wed Oct 24 20:01:13 2007
@@ -0,0 +1,19 @@
+#! /bin/sh
+# script to be run as the -p argument to modload
+# BEWARE: it adds users, and creates and removes special files in /dev
+
+set -e
+id="$1"
+type="$2"
+maj="$3"
+
+if [ -c /dev/kqemu ]; then
+ if [ "`stat -f%Z,%Sg /dev/kqemu`" != "$maj,0,kqemu" ]; then
+ rm /dev/kqemu
+ else
+ exit 0
+ fi
+fi
+mknod /dev/kqemu c "$maj" 0
+groupinfo -e kqemu || groupadd kqemu
+chgrp kqemu /dev/kqemu
diff -Nrup a/tests/Makefile kqemu-1.3.0pre11/tests/Makefile
--- a/tests/Makefile Tue Feb 6 23:02:00 2007
+++ kqemu-1.3.0pre11/tests/Makefile Wed Oct 24 20:01:13 2007
@@ -3,9 +3,9 @@ include ../config-host.mak
#CC=gcc34
LD=ld
CC_32=$(CC) -m32
-LD_32=$(LD) -m elf_i386
+LD_32=$(LD) -m elf_i386_obsd
CFLAGS=-O2 -Wall -Werror -fno-optimize-sibling-calls -fno-common \
- -fno-strict-aliasing -fno-builtin -g -I..
+ -fno-stack-protector -fno-strict-aliasing -fno-builtin -g -I..
KERNEL_CFLAGS_32=$(CFLAGS)
KERNEL_CFLAGS_64=$(CFLAGS) -mno-red-zone -mcmodel=kernel
diff -Nrup a/tests/kqemutest.c kqemu-1.3.0pre11/tests/kqemutest.c
--- a/tests/kqemutest.c Tue Feb 6 23:02:00 2007
+++ kqemu-1.3.0pre11/tests/kqemutest.c Wed Oct 24 20:01:13 2007
@@ -10,7 +10,7 @@
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
-#include <elf.h>
+#include <elf_abi.h>
#include "kqemu.h"
#include "kqemutest.h"