qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] KQemu FreeBSD wrapper cloning support
@ 2005-06-11  3:42 Craig Boston
  0 siblings, 0 replies; only message in thread
From: Craig Boston @ 2005-06-11  3:42 UTC (permalink / raw)
  To: nox, antony.t.curtis; +Cc: qemu-devel

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

Hello,

Attached is an experimental patch I threw together this evening that
adds support for FreeBSD 5.x+ device cloning to Antony's kqemu wrapper.

I haven't done just a whole lot of testing, but it passes the "works for
me" test.  With it I'm able to load the module, start up a few
concurrent qemu instances (all using the accelerator), close some, open
one or two more, then close them all and unload the module.

So far the only problem I've run into is a panic if you repeatedly ls -l
/dev/kqemu and /dev/kqemu[0-9].  However, I am able to cause the same
panic by doing that with the tun device, so it appears to be a bug in
FreeBSD (possibly specific to 6.0-current).

It still has the 4 instance limit, which appears to have been copied
from the Linux module.  I debated removing it, but figured there must be
some reason it's in there...

Just thought you might be interested.

Craig

[-- Attachment #2: kmod_bsd_clone.patch --]
[-- Type: text/plain, Size: 4060 bytes --]

--- kmod_bsd.c.orig	Fri Jun 10 19:14:08 2005
+++ kmod_bsd.c	Fri Jun 10 22:27:13 2005
@@ -284,6 +284,10 @@
 #define KQEMU_MAX_INSTANCES 4
 
 struct kqemu_instance {
+#if __FreeBSD_version > 500000
+    TAILQ_ENTRY(kqemu_instance) kqemu_ent;
+    struct cdev *kqemu_dev;
+#endif
     struct kqemu_state *state;
 };
 
@@ -292,7 +296,9 @@
 #if __FreeBSD_version < 500000
 static dev_t kqemu_dev;
 #else
-static struct cdev *kqemu_dev;
+static struct clonedevs *kqemuclones;
+static TAILQ_HEAD(,kqemu_instance) kqemuhead = TAILQ_HEAD_INITIALIZER(kqemuhead);
+static eventhandler_tag clonetag;
 #endif
 
 
@@ -325,6 +331,61 @@
 #endif
 };
 
+#if __FreeBSD_version > 500000
+static void
+kqemu_clone(void *arg, char *name, int namelen, struct cdev **dev)
+{
+    int unit, r;
+    if (*dev != NULL)
+	return;
+
+    if (strcmp(name, "kqemu") == 0)
+	unit = -1;
+    else if (dev_stdclone(name, NULL, "kqemu", &unit) != 1)
+	return;		/* Bad name */
+    if (unit != -1 && unit > KQEMU_MAX_INSTANCES)
+	return;
+
+    r = clone_create(&kqemuclones, &kqemu_cdevsw, &unit, dev, 0);
+    if (r) {
+	    *dev = make_dev(&kqemu_cdevsw, unit2minor(unit),
+		    UID_ROOT, GID_WHEEL, 0660, "kqemu%d", unit);
+	    if (*dev != NULL) {
+		    dev_ref(*dev);
+		    (*dev)->si_flags |= SI_CHEAPCLONE;
+	    }
+    }
+}
+#endif
+
+static void kqemu_destroy(struct kqemu_instance *ks)
+{
+    struct cdev *dev = ks->kqemu_dev;
+
+    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);
+    TAILQ_REMOVE(&kqemuhead, ks, kqemu_ent);
+#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);
+
+    destroy_dev(dev);
+#endif
+}
+
 int
 #if __FreeBSD_version < 500000
 kqemu_open(dev, flags, fmt, p)
@@ -355,7 +416,9 @@
     
     dev->si_drv1 = ks;
 #if __FreeBSD_version > 500000
+    ks->kqemu_dev = dev;
     mtx_lock_spin(&cache_lock);
+    TAILQ_INSERT_TAIL(&kqemuhead, ks, kqemu_ent);
 #endif
     kqemu_ref_count++;
 #if __FreeBSD_version > 500000
@@ -382,25 +445,8 @@
 #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_destroy(ks);
+
     kqemu_log("closed by pid=%d\n", p->p_pid);
     return(0);
 }
@@ -513,9 +559,14 @@
     	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");
+#else
+    clone_setup(&kqemuclones);
+    clonetag = EVENTHANDLER_REGISTER(dev_clone, kqemu_clone, 0, 1000);
+    if (!clonetag)
+	return ENOMEM;
+#endif
 
     kqemu_log("KQEMU installed, max_instances=%d max_locked_mem=%dkB.\n",
               KQEMU_MAX_INSTANCES, max_locked_pages * 4);
@@ -529,12 +580,25 @@
 {
 #if __FreeBSD_version < 500000
     int rc;
+#else
+    struct kqemu_instance *ks;
 #endif
     
-    destroy_dev(kqemu_dev);
 #if __FreeBSD_version < 500000
+    destroy_dev(kqemu_dev);
     if ((rc = cdevsw_remove(&kqemu_cdevsw)))
 	kqemu_log("error unregistering, rc=%d\n", rc);
+#else
+    EVENTHANDLER_DEREGISTER(dev_clone, clonetag);
+    mtx_lock_spin(&cache_lock);
+    while ((ks = TAILQ_FIRST(&kqemuhead)) != NULL) {
+	mtx_unlock_spin(&cache_lock);
+	kqemu_destroy(ks);
+	mtx_lock_spin(&cache_lock);
+    }
+    mtx_unlock_spin(&cache_lock);
+    mtx_destroy(&cache_lock);
+    clone_cleanup(&kqemuclones);
 #endif
 
     kqemu_vfree(pagecache);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-06-11  4:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-11  3:42 [Qemu-devel] KQemu FreeBSD wrapper cloning support Craig Boston

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).