@@ -65,6 +65,7 @@
#include "xenbus.h"
+static int late_init_irq;
int xen_store_evtchn;
EXPORT_SYMBOL_GPL(xen_store_evtchn);
@@ -750,6 +751,17 @@ static void xenbus_probe(void)
{
xenstored_ready = 1;
+ if (xen_feature(XENFEAT_xenstore_late_init)) {
+ xen_store_interface = xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
+ XEN_PAGE_SIZE);
+ /*
+ * Now it is safe to free the IRQ used for xenstore late
+ * initialization. No need to unbind: it is about to be
+ * bound again.
+ */
+ free_irq(late_init_irq, &xb_waitq);
+ }
+
/*
* In the HVM case, xenbus_init() deferred its call to
* xs_init() in case callbacks were not operational yet.
@@ -798,20 +810,23 @@ static int __init xenbus_probe_initcall(void)
{
/*
* Probe XenBus here in the XS_PV case, and also XS_HVM unless we
- * need to wait for the platform PCI device to come up.
+ * need to wait for the platform PCI device to come up or
+ * XENFEAT_xenstore_late_init is set.
*/
if (xen_store_domain_type == XS_PV ||
(xen_store_domain_type == XS_HVM &&
- !xs_hvm_defer_init_for_callback()))
+ !xs_hvm_defer_init_for_callback() &&
+ !xen_feature(XENFEAT_xenstore_late_init)))
xenbus_probe();
/*
- * For XS_LOCAL, spawn a thread which will wait for xenstored
- * or a xenstore-stubdom to be started, then probe. It will be
- * triggered when communication starts happening, by waiting
- * on xb_waitq.
+ * For XS_LOCAL or domains with XENFEAT_xenstore_late_init, spawn a
+ * thread which will wait for xenstored or a xenstore-stubdom to be
+ * started, then probe. It will be triggered when communication
+ * starts happening, by waiting on xb_waitq.
*/
- if (xen_store_domain_type == XS_LOCAL) {
+ if (xen_store_domain_type == XS_LOCAL ||
+ xen_feature(XENFEAT_xenstore_late_init) ) {
struct task_struct *probe_task;
probe_task = kthread_run(xenbus_probe_thread, NULL,
@@ -907,6 +922,24 @@ static struct notifier_block xenbus_resume_nb = {
.notifier_call = xenbus_resume_cb,
};
+static irqreturn_t xenbus_late_init(int irq, void *unused)
+{
+ int err = 0;
+ uint64_t v = 0;
+
+ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+ if (err)
+ return IRQ_HANDLED;
+ xen_store_evtchn = (int)v;
+ err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
+ if (err || !v || !~v)
+ return IRQ_HANDLED;
+ xen_store_gfn = (unsigned long)v;
+
+ wake_up(&xb_waitq);
+ return IRQ_HANDLED;
+}
+
static int __init xenbus_init(void)
{
int err;
@@ -929,6 +962,36 @@ static int __init xenbus_init(void)
if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
+ /*
+ * If a domain has been configured to initialize xenstore later
+ * (e.g. dom0less domains), wait until the xenstore event channel is
+ * triggered for the first time. The IRQ handler will take care for
+ * initializing xenstore common variabiles that, in a standard
+ * scenario, are configured here.
+ */
+ if (xen_feature(XENFEAT_xenstore_late_init)) {
+ if (xen_store_domain_type != XS_HVM || xen_feature(XENFEAT_dom0)) {
+ pr_err("xenstore_late_init not supported this domain\n");
+ return -EINVAL;
+ }
+
+ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+ if (err < 0) {
+ pr_err("xenstore_late_init err=%d\n", err);
+ return err;
+ }
+
+ err = bind_evtchn_to_irqhandler(v, xenbus_late_init,
+ 0, "xenstore_late_init", &xb_waitq);
+ if (err < 0) {
+ pr_err("xenstore_late_init couldn't bind irq err=%d\n", err);
+ return err;
+ }
+
+ late_init_irq = err;
+ goto out_late_init;
+ }
+
switch (xen_store_domain_type) {
case XS_LOCAL:
err = xenstored_local_init();
@@ -995,6 +1058,7 @@ static int __init xenbus_init(void)
}
}
+out_late_init:
if ((xen_store_domain_type != XS_LOCAL) &&
(xen_store_domain_type != XS_UNKNOWN))
xen_resume_notifier_register(&xenbus_resume_nb);