aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen/xenstore/xenstore.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/xen/xenstore/xenstore.c')
-rw-r--r--sys/dev/xen/xenstore/xenstore.c68
1 files changed, 66 insertions, 2 deletions
diff --git a/sys/dev/xen/xenstore/xenstore.c b/sys/dev/xen/xenstore/xenstore.c
index f7425da7b98f..8ff766c0855a 100644
--- a/sys/dev/xen/xenstore/xenstore.c
+++ b/sys/dev/xen/xenstore/xenstore.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <sys/unistd.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
#include <machine/stdarg.h>
@@ -249,6 +251,20 @@ struct xs_softc {
* with the XenStore service) are available.
*/
struct intr_config_hook xs_attachcb;
+
+ /**
+ * Xenstore is a user-space process that usually runs in Dom0,
+ * so if this domain is booting as Dom0, xenstore wont we accessible,
+ * and we have to defer the initialization of xenstore related
+ * devices to later (when xenstore is started).
+ */
+ bool initialized;
+
+ /**
+ * Task to run when xenstore is initialized (Dom0 only), will
+ * take care of attaching xenstore related devices.
+ */
+ struct task xs_late_init;
};
/*-------------------------------- Global Data ------------------------------*/
@@ -352,6 +368,16 @@ static void
xs_intr(void * arg __unused /*__attribute__((unused))*/)
{
+ /* If xenstore has not been initialized, initialize it now */
+ if (!xs.initialized) {
+ xs.initialized = true;
+ /*
+ * Since this task is probing and attaching devices we
+ * have to hold the Giant lock.
+ */
+ taskqueue_enqueue(taskqueue_swi_giant, &xs.xs_late_init);
+ }
+
/*
* Hold ring lock across wakeup so that clients
* cannot miss a wakeup.
@@ -1112,6 +1138,15 @@ xs_attach_deferred(void *arg)
config_intrhook_disestablish(&xs.xs_attachcb);
}
+static void
+xs_attach_late(void *arg, int pending)
+{
+
+ KASSERT((pending == 1), ("xs late attach queued several times"));
+ bus_generic_probe(xs.xs_dev);
+ bus_generic_attach(xs.xs_dev);
+}
+
/**
* Attach to the XenStore.
*
@@ -1130,12 +1165,37 @@ xs_attach(device_t dev)
/* Initialize the interface to xenstore. */
struct proc *p;
+ xs.initialized = false;
if (xen_hvm_domain()) {
xs.evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
xs.gpfn = hvm_get_parameter(HVM_PARAM_STORE_PFN);
xen_store = pmap_mapdev(xs.gpfn * PAGE_SIZE, PAGE_SIZE);
+ xs.initialized = true;
} else if (xen_pv_domain()) {
- xs.evtchn = HYPERVISOR_start_info->store_evtchn;
+ if (HYPERVISOR_start_info->store_evtchn == 0) {
+ struct evtchn_alloc_unbound alloc_unbound;
+
+ /* Allocate a local event channel for xenstore */
+ alloc_unbound.dom = DOMID_SELF;
+ alloc_unbound.remote_dom = DOMID_SELF;
+ error = HYPERVISOR_event_channel_op(
+ EVTCHNOP_alloc_unbound, &alloc_unbound);
+ if (error != 0)
+ panic(
+ "unable to alloc event channel for Dom0: %d",
+ error);
+
+ HYPERVISOR_start_info->store_evtchn =
+ alloc_unbound.port;
+ xs.evtchn = alloc_unbound.port;
+
+ /* Allocate memory for the xs shared ring */
+ xen_store = malloc(PAGE_SIZE, M_XENSTORE,
+ M_WAITOK | M_ZERO);
+ } else {
+ xs.evtchn = HYPERVISOR_start_info->store_evtchn;
+ xs.initialized = true;
+ }
} else {
panic("Unknown domain type, cannot initialize xenstore.");
}
@@ -1167,7 +1227,11 @@ xs_attach(device_t dev)
xs.xs_attachcb.ich_func = xs_attach_deferred;
xs.xs_attachcb.ich_arg = NULL;
- config_intrhook_establish(&xs.xs_attachcb);
+ if (xs.initialized) {
+ config_intrhook_establish(&xs.xs_attachcb);
+ } else {
+ TASK_INIT(&xs.xs_late_init, 0, xs_attach_late, NULL);
+ }
return (error);
}