[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 2/2] xen: add support for initializing xenstore later as HVM domain
Hi Luca, On 05.05.2022 02:23, Stefano Stabellini wrote: > From: Luca Miccio <lucmiccio@xxxxxxxxx> > > 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 <lucmiccio@xxxxxxxxx> > Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx> > --- > Changes in v4: > - improve in-code comments > - move header sync to separate patch > - use XENSTORE_CONNECTED > > Changes in v3: > - check for the connection field, if it is not zero, wait for event > > Changes in v2: > - remove XENFEAT_xenstore_late_init > --- > drivers/xen/xenbus/xenbus_probe.c | 91 ++++++++++++++++++++++++------- > 1 file changed, 71 insertions(+), 20 deletions(-) > > diff --git a/drivers/xen/xenbus/xenbus_probe.c > b/drivers/xen/xenbus/xenbus_probe.c > index fe360c33ce71..0a785d5e3e40 100644 > --- a/drivers/xen/xenbus/xenbus_probe.c > +++ b/drivers/xen/xenbus/xenbus_probe.c > @@ -65,6 +65,7 @@ > #include "xenbus.h" > > > +static int xs_init_irq; > int xen_store_evtchn; > EXPORT_SYMBOL_GPL(xen_store_evtchn); > > @@ -750,6 +751,20 @@ static void xenbus_probe(void) > { > xenstored_ready = 1; > > + if (!xen_store_interface) { > + 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 from xb_init_comms. Note that calling > + * unbind_from_irqhandler now would result in xen_evtchn_close() > + * being called and the event channel not being enabled again > + * afterwards, resulting in missed event notifications. > + */ > + free_irq(xs_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 +813,22 @@ 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 > + * xen_store_interface is not ready. > */ > 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_store_interface != NULL)) > 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 when xen_store_interface is not ready, 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_store_interface == NULL) { > struct task_struct *probe_task; > > probe_task = kthread_run(xenbus_probe_thread, NULL, > @@ -907,10 +924,25 @@ 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; No need to set up initial value as it is being reassigned without using the initial value. > + uint64_t v = 0; > + > + 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; > uint64_t v = 0; > + bool wait = false; > xen_store_domain_type = XS_UNKNOWN; > > if (!xen_domain()) > @@ -957,25 +989,44 @@ static int __init xenbus_init(void) > * been properly initialized. Instead of attempting to map a > * wrong guest physical address return error. > * > - * Also recognize all bits set as an invalid value. > + * Also recognize all bits set as an invalid/uninitialized > value. > */ > - if (!v || !~v) { > + if (!v) { > err = -ENOENT; > goto out_error; > } > - /* Avoid truncation on 32-bit. */ > + if (v == ~0ULL) { No need for brackets for a single instruction. > + wait = true; > + } else { > + /* Avoid truncation on 32-bit. */ > #if BITS_PER_LONG == 32 > - if (v > ULONG_MAX) { > - pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > > ULONG_MAX\n", > - __func__, v); > - err = -EINVAL; > - goto out_error; > - } > + if (v > ULONG_MAX) { > + pr_err("%s: cannot handle > HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n", > + __func__, v); __func shall be aligned with "%s... as it was before. > + err = -EINVAL; > + goto out_error; > + } > #endif > - xen_store_gfn = (unsigned long)v; > - xen_store_interface = > - xen_remap(xen_store_gfn << XEN_PAGE_SHIFT, > - XEN_PAGE_SIZE); > + xen_store_gfn = (unsigned long)v; > + xen_store_interface = > + xen_remap(xen_store_gfn << XEN_PAGE_SHIFT, > + XEN_PAGE_SIZE); > + if (xen_store_interface->connection != > XENSTORE_CONNECTED) > + wait = true; > + } > + if (wait) { > + err = bind_evtchn_to_irqhandler(xen_store_evtchn, > + 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; > + } > + > + xs_init_irq = err; > + } > break; > default: > pr_warn("Xenstore state unknown\n"); Cheers, Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |