[LINUX PATCH 2/2] xen: add support for XENFEAT_xenstore_late_init

Stefano Stabellini posted 2 patches 2 years, 10 months ago
[LINUX PATCH 2/2] xen: add support for XENFEAT_xenstore_late_init
Posted by Stefano Stabellini 2 years, 10 months ago
From: Luca Miccio <lucmiccio@gmail.com>

XENFEAT_xenstore_late_init requires xenstore to be initialized later,
after receiving an event channel notification on the xenstore event
channel (which is available since boot).

This patch adds support for delaying the Xenstore initialization as
required when XENFEAT_xenstore_late_init is set.

Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
---
 drivers/xen/xenbus/xenbus_probe.c | 78 ++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 7 deletions(-)

diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index fe360c33ce71..d4a982a883b7 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -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);
-- 
2.25.1