Skip to content

Commit 5b33539

Browse files
lmicciojgross1
authored andcommitted
xen: add support for initializing xenstore later as HVM domain
When running as dom0less guest (HVM domain on ARM) the xenstore event channel is available at domain creation but the shared xenstore interface page only becomes available later on. In that case, wait for a notification on the xenstore event channel, then complete the xenstore initialization later, when the shared page is actually available. The xenstore page has few extra field. Add them to the shared struct. One of the field is "connection", when the connection is ready, it is zero. If the connection is not-zero, wait for a notification. Signed-off-by: Luca Miccio <[email protected]> Signed-off-by: Stefano Stabellini <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Juergen Gross <[email protected]>
1 parent 62db0fa commit 5b33539

File tree

1 file changed

+71
-20
lines changed

1 file changed

+71
-20
lines changed

drivers/xen/xenbus/xenbus_probe.c

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "xenbus.h"
6666

6767

68+
static int xs_init_irq;
6869
int xen_store_evtchn;
6970
EXPORT_SYMBOL_GPL(xen_store_evtchn);
7071

@@ -750,6 +751,20 @@ static void xenbus_probe(void)
750751
{
751752
xenstored_ready = 1;
752753

754+
if (!xen_store_interface) {
755+
xen_store_interface = xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
756+
XEN_PAGE_SIZE);
757+
/*
758+
* Now it is safe to free the IRQ used for xenstore late
759+
* initialization. No need to unbind: it is about to be
760+
* bound again from xb_init_comms. Note that calling
761+
* unbind_from_irqhandler now would result in xen_evtchn_close()
762+
* being called and the event channel not being enabled again
763+
* afterwards, resulting in missed event notifications.
764+
*/
765+
free_irq(xs_init_irq, &xb_waitq);
766+
}
767+
753768
/*
754769
* In the HVM case, xenbus_init() deferred its call to
755770
* xs_init() in case callbacks were not operational yet.
@@ -798,20 +813,22 @@ static int __init xenbus_probe_initcall(void)
798813
{
799814
/*
800815
* Probe XenBus here in the XS_PV case, and also XS_HVM unless we
801-
* need to wait for the platform PCI device to come up.
816+
* need to wait for the platform PCI device to come up or
817+
* xen_store_interface is not ready.
802818
*/
803819
if (xen_store_domain_type == XS_PV ||
804820
(xen_store_domain_type == XS_HVM &&
805-
!xs_hvm_defer_init_for_callback()))
821+
!xs_hvm_defer_init_for_callback() &&
822+
xen_store_interface != NULL))
806823
xenbus_probe();
807824

808825
/*
809-
* For XS_LOCAL, spawn a thread which will wait for xenstored
810-
* or a xenstore-stubdom to be started, then probe. It will be
811-
* triggered when communication starts happening, by waiting
812-
* on xb_waitq.
826+
* For XS_LOCAL or when xen_store_interface is not ready, spawn a
827+
* thread which will wait for xenstored or a xenstore-stubdom to be
828+
* started, then probe. It will be triggered when communication
829+
* starts happening, by waiting on xb_waitq.
813830
*/
814-
if (xen_store_domain_type == XS_LOCAL) {
831+
if (xen_store_domain_type == XS_LOCAL || xen_store_interface == NULL) {
815832
struct task_struct *probe_task;
816833

817834
probe_task = kthread_run(xenbus_probe_thread, NULL,
@@ -907,10 +924,25 @@ static struct notifier_block xenbus_resume_nb = {
907924
.notifier_call = xenbus_resume_cb,
908925
};
909926

927+
static irqreturn_t xenbus_late_init(int irq, void *unused)
928+
{
929+
int err;
930+
uint64_t v = 0;
931+
932+
err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
933+
if (err || !v || !~v)
934+
return IRQ_HANDLED;
935+
xen_store_gfn = (unsigned long)v;
936+
937+
wake_up(&xb_waitq);
938+
return IRQ_HANDLED;
939+
}
940+
910941
static int __init xenbus_init(void)
911942
{
912943
int err;
913944
uint64_t v = 0;
945+
bool wait = false;
914946
xen_store_domain_type = XS_UNKNOWN;
915947

916948
if (!xen_domain())
@@ -957,25 +989,44 @@ static int __init xenbus_init(void)
957989
* been properly initialized. Instead of attempting to map a
958990
* wrong guest physical address return error.
959991
*
960-
* Also recognize all bits set as an invalid value.
992+
* Also recognize all bits set as an invalid/uninitialized value.
961993
*/
962-
if (!v || !~v) {
994+
if (!v) {
963995
err = -ENOENT;
964996
goto out_error;
965997
}
966-
/* Avoid truncation on 32-bit. */
998+
if (v == ~0ULL) {
999+
wait = true;
1000+
} else {
1001+
/* Avoid truncation on 32-bit. */
9671002
#if BITS_PER_LONG == 32
968-
if (v > ULONG_MAX) {
969-
pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n",
970-
__func__, v);
971-
err = -EINVAL;
972-
goto out_error;
973-
}
1003+
if (v > ULONG_MAX) {
1004+
pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n",
1005+
__func__, v);
1006+
err = -EINVAL;
1007+
goto out_error;
1008+
}
9741009
#endif
975-
xen_store_gfn = (unsigned long)v;
976-
xen_store_interface =
977-
xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
978-
XEN_PAGE_SIZE);
1010+
xen_store_gfn = (unsigned long)v;
1011+
xen_store_interface =
1012+
xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
1013+
XEN_PAGE_SIZE);
1014+
if (xen_store_interface->connection != XENSTORE_CONNECTED)
1015+
wait = true;
1016+
}
1017+
if (wait) {
1018+
err = bind_evtchn_to_irqhandler(xen_store_evtchn,
1019+
xenbus_late_init,
1020+
0, "xenstore_late_init",
1021+
&xb_waitq);
1022+
if (err < 0) {
1023+
pr_err("xenstore_late_init couldn't bind irq err=%d\n",
1024+
err);
1025+
return err;
1026+
}
1027+
1028+
xs_init_irq = err;
1029+
}
9791030
break;
9801031
default:
9811032
pr_warn("Xenstore state unknown\n");

0 commit comments

Comments
 (0)