(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"

Reply via email to