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