[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v3 14/14] libxl: build a device tree for ARM guests



On Thu, 2013-11-07 at 17:30 +0000, Ian Jackson wrote:
> Ian Campbell writes ("[PATCH v3 14/14] libxl: build a device tree for ARM 
> guests"):
> > Uses xc_dom_devicetree_mem which was just added. The call to this needs to 
> > be
> > carefully sequenced to be after xc_dom_parse_image (so we can tell which 
> > kind
> > of guest we are building, although we don't use this yet) and before
> > xc_dom_mem_init which tries to decide where to place the FDT in guest RAM.
> ...
> > diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
> > index abe6685..3de2d76 100644
> > --- a/tools/libxl/libxl_arch.h
> > +++ b/tools/libxl/libxl_arch.h
> > @@ -19,4 +19,8 @@
> >  int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
> >                 uint32_t domid);
> >  
> > +/* */
> > +int libxl__arch_domain_configure(libxl__gc *gc,
> > +                                 libxl_domain_build_info *info,
> > +                                 struct xc_dom_image *dom);
> 
> Missing content for comment ?  Or maybe the comment just wants to go.

I'll nuke it.

> 
> > +typedef uint32_t __be32;
> > +typedef __be32 gic_interrupt_t[3];
> 
> Identifiers starting with __, and ones ending _t, are reserved for the
> C implementation.

Oops, types carried over from the h/v side.

> > +static int make_memory_node(libxl__gc *gc, void *fdt,
> > +                            unsigned long long base,
> > +                            unsigned long long size)
> > +{
> > +    int res;
> > +    char name[strlen("memory@") + 8 + 1];
> > +
> > +    snprintf(name, sizeof(name), "memory@%08llx", base);
> 
> Why not use GCSPRINTF ?

Another hypervisor-ism which I carried over without enough thought.

> 
> > +/*
> > + * Call "call" handling FDR_ERR_*. Will either:
> > + * - loop back to retry_resize
> > + * - set rc and goto out
> > + * - fall through successfully
> > + *
> > + * On FDT_ERR_NOSPACE we start again from scratch rather than
> > + * realloc+libfdt_open_into because "call" may have failed half way
> > + * through a series of steps leaving the partial tree in an
> > + * inconsistent state, e.g. leaving a node open.
> > + */
> > +#define FDT( call ) do {                                        \
> > +    int fdt_res = (call);                                       \
> > +    if (fdt_res == -FDT_ERR_NOSPACE && fdt_size < FDT_MAX_SIZE) \
> > +        goto retry_resize;                                      \
> > +    else if (fdt_res < 0) {                                     \
> > +        LOG(ERROR, "FDT: %s failed: %d = %s",                   \
> > +            #call, fdt_res, fdt_strerror(fdt_res));             \
> > +        rc = ERROR_FAIL;                                        \
> > +        goto out;                                               \
> > +    }                                                           \
> > +} while(0)
> 
> My preference would be for this to be defined inside
> libxl__arch_domain_configure and #undef'd at the end, so as to limit
> the scope of the implicit reference to the label retry_resize.

Good idea.

> > +int libxl__arch_domain_configure(libxl__gc *gc,
> > +                                 libxl_domain_build_info *info,
> > +                                 struct xc_dom_image *dom)
> > +{
> > +    void *fdt;
> > +    int rc, res, fd;
> > +    size_t fdt_size = 0;
> > +
> > +    const libxl_version_info *vers;
> > +    const struct arch_info *ainfo;
> > +
> > +    assert(info->type == LIBXL_DOMAIN_TYPE_PV);
> > +
> > +    vers = libxl_get_version_info(CTX);
> > +    if (vers == NULL) return ERROR_FAIL;
> > +
> > +    ainfo = get_arch_info(gc, dom);
> > +    if (ainfo == NULL) return ERROR_FAIL;
> > +
> > +    LOG(DEBUG, "constructing DTB for Xen version %d.%d guest",
> > +        vers->xen_version_major, vers->xen_version_minor);
> > +
> > +retry_resize:
> 
> For form's sake, how about making this an explicit loop ?  e.g.
> 
>        for (;;) {
>            next_resize:;
>            blah blah
>            if (something)
>                goto next_resize;
> 
> Then the end of the loop would be more obvious.  You'd have to write
> "break".  (And you can #undef FDT at the end of the loop rather than
> the end of the function, as the label becomes semantically void after
> the end of the loop.)
> 
> (If C had labelled loops you could do
>        for resize (;;) {
>            blah blah
>            next resize;
> but it doesn't.  Emulating this with goto is a lot nicer IMO than
> the naked goto.)

I agree, I'll change things along these lines.

> 
> > +    if (fdt_size) {
> > +        fdt_size <<= 1;
> > +        LOG(DEBUG, "Increasing FDT size to %zd and retrying", fdt_size);
> > +    } else {
> > +        fdt_size = 4096;
> > +    }
> 
> Can we rule out this loop getting out of control ?

The FDT macro has a check and error if it gets too big. I'll see about
moving the <<= into the macro, which I suspect will seem more natural
with a loop called "retry".

> 
> > +#ifndef NDEBUG
> 
> Please don't key off NDEBUG.  libxl ought never to be compiled
> with NDEBUG.  I don't see why you can't just have this code present
> all the time.

I wasn't entirely sure about keeping it at all, I wrote it for my own
debugging purposes. I'm happy with it unconditional if you are.

> > +    if ( getenv("LIBXL_DEBUG_DUMP_DTB") ) {
> > +        const char *dtb = getenv("LIBXL_DEBUG_DUMP_DTB");
> > +
> > +        fd = open(dtb, O_CREAT|O_TRUNC|O_WRONLY, 0666);
> > +        if ( fd < 0 ) {
> > +            LOGE(DEBUG, "cannot open %s for LIBXL_DEBUG_DUMP_DTB", dtb);
> > +            goto no_debug_dump;
> 
> This construction with "goto" is pretty ugly.  Perhaps if you made
> the whole thing a separate function it would be less so.

Yes, I suspect it will.

> > +        }
> > +
> > +        rc = libxl_write_exactly(CTX, fd, fdt, fdt_totalsize(fdt),
> > +                            dtb, "dtb");
> > +        if ( rc < 0 ) {
> > +            LOG(DEBUG, "unable to write DTB debug dump output %d", rc);
> > +            goto no_debug_dump;
> 
> For example, if you had made it a separate function with the "goto
> out" error handling style you wouldn't leak fd in this particular
> error case :-).

:-)

>   (Also, no spaces inside ( ) in ifs, please.)

Ack. Will do a thorough sweep.

> > diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> > index 10f976c..6351ebd 100644
> > --- a/tools/libxl/libxl_dom.c
> > +++ b/tools/libxl/libxl_dom.c
> > @@ -400,6 +400,10 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
> >          LOGE(ERROR, "xc_dom_parse_image failed");
> >          goto out;
> >      }
> > +    if ( (ret = libxl__arch_domain_configure(gc, info, dom)) != 0 ) {
> > +        LOGE(ERROR, "libxl__arch_domain_configure failed");
> > +        goto out;
> > +    }
> >      if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) {
> >          LOGE(ERROR, "xc_dom_mem_init failed");
> >          goto out;
> 
> The style in this function is anomalous:
> 
>   * spaces inside ( )
> 
>   * use of
>       if ((ret = blah) !=0 )
>     which hides the meat in the if and has !=0 clobber, instead of
>       rc = blah;
>       if (rc) goto out;
> 
>   * use of "ret" for a libxl error code, rather than rc.
> 
> But I won't insist on you fixing it.  Adding an extra occurrence is
> probably better than having one call which is different to all the
> others.

I agree.

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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