[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



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.

> +typedef uint32_t __be32;
> +typedef __be32 gic_interrupt_t[3];

Identifiers starting with __, and ones ending _t, are reserved for the
C implementation.

> +static void set_cell(__be32 **cellp, int size, uint64_t val)
> +{
> +    int cells = size;
> +
> +    while ( size-- )

The spaces inside ( ) aren't expected inside libxl.

> +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 ?

> +/*
> + * 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.

> +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.)

> +    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 ?

> +#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.

> +    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.

> +        }
> +
> +        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.)

> 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.


Thanks,
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®.