[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



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.