diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index fdb64fed1d..c51106e49e 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,7 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
-XL_OBJS += xl_psr.o
+XL_OBJS += xl_psr.o xl_info.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index f6942ffbe8..1de5445e7f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -222,80 +222,6 @@ release_lock:
     return rc;
 }
 
-static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
-                                            libxl_domain_config *d_config)
-{
-    yajl_gen_status s;
-
-    s = yajl_gen_map_open(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"domid",
-                        sizeof("domid")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    if (domid != -1)
-        s = yajl_gen_integer(hand, domid);
-    else
-        s = yajl_gen_null(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"config",
-                        sizeof("config")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    s = libxl_domain_config_gen_json(hand, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_map_close(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-out:
-    return s;
-}
-
-static void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh)
-{
-    if (output_format == OUTPUT_FORMAT_SXP)
-        return printf_info_sexp(domid, d_config, fh);
-
-    const char *buf;
-    libxl_yajl_length len = 0;
-    yajl_gen_status s;
-    yajl_gen hand;
-
-    hand = libxl_yajl_gen_alloc(NULL);
-    if (!hand) {
-        fprintf(stderr, "unable to allocate JSON generator\n");
-        return;
-    }
-
-    s = printf_info_one_json(hand, domid, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    fputs(buf, fh);
-
-out:
-    yajl_gen_free(hand);
-
-    if (s != yajl_gen_status_ok)
-        fprintf(stderr,
-                "unable to format domain config as JSON (YAJL:%d)\n", s);
-
-    xflush_stream(fh);
-}
-
 static int do_daemonize(char *name, const char *pidfile)
 {
     char *fullname;
@@ -1320,165 +1246,6 @@ static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
     }
 }
 
-static void list_domains_details(const libxl_dominfo *info, int nb_domain)
-{
-    libxl_domain_config d_config;
-
-    int i, rc;
-
-    yajl_gen hand = NULL;
-    yajl_gen_status s;
-    const char *buf;
-    libxl_yajl_length yajl_len = 0;
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        hand = libxl_yajl_gen_alloc(NULL);
-        if (!hand) {
-            fprintf(stderr, "unable to allocate JSON generator\n");
-            return;
-        }
-
-        s = yajl_gen_array_open(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    } else
-        s = yajl_gen_status_ok;
-
-    for (i = 0; i < nb_domain; i++) {
-        libxl_domain_config_init(&d_config);
-        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
-        if (rc)
-            continue;
-        if (default_output_format == OUTPUT_FORMAT_JSON)
-            s = printf_info_one_json(hand, info[i].domid, &d_config);
-        else
-            printf_info_sexp(info[i].domid, &d_config, stdout);
-        libxl_domain_config_dispose(&d_config);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    }
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        s = yajl_gen_array_close(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        puts(buf);
-    }
-
-out:
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        yajl_gen_free(hand);
-        if (s != yajl_gen_status_ok)
-            fprintf(stderr,
-                    "unable to format domain config as JSON (YAJL:%d)\n", s);
-    }
-}
-
-static void list_domains(bool verbose, bool context, bool claim, bool numa,
-                         bool cpupool, const libxl_dominfo *info, int nb_domain)
-{
-    int i;
-    static const char shutdown_reason_letters[]= "-rscwS";
-    libxl_bitmap nodemap;
-    libxl_physinfo physinfo;
-
-    libxl_bitmap_init(&nodemap);
-    libxl_physinfo_init(&physinfo);
-
-    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
-    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
-    if (context && !verbose) printf("   Security Label");
-    if (claim) printf("  Claimed");
-    if (cpupool) printf("         Cpupool");
-    if (numa) {
-        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
-            exit(EXIT_FAILURE);
-        }
-        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-            fprintf(stderr, "libxl_physinfo failed.\n");
-            libxl_bitmap_dispose(&nodemap);
-            exit(EXIT_FAILURE);
-        }
-
-        printf(" NODE Affinity");
-    }
-    printf("\n");
-    for (i = 0; i < nb_domain; i++) {
-        char *domname;
-        libxl_shutdown_reason shutdown_reason;
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
-        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
-                domname,
-                info[i].domid,
-                (unsigned long) ((info[i].current_memkb +
-                    info[i].outstanding_memkb)/ 1024),
-                info[i].vcpu_online,
-                info[i].running ? 'r' : '-',
-                info[i].blocked ? 'b' : '-',
-                info[i].paused ? 'p' : '-',
-                info[i].shutdown ? 's' : '-',
-                (shutdown_reason >= 0 &&
-                 shutdown_reason < sizeof(shutdown_reason_letters)-1
-                 ? shutdown_reason_letters[shutdown_reason] : '?'),
-                info[i].dying ? 'd' : '-',
-                ((float)info[i].cpu_time / 1e9));
-        free(domname);
-        if (verbose) {
-            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
-            if (info[i].shutdown) printf(" %8x", shutdown_reason);
-            else printf(" %8s", "-");
-        }
-        if (claim)
-            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
-        if (verbose || context)
-            printf(" %16s", info[i].ssid_label ? : "-");
-        if (cpupool) {
-            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
-            printf("%16s", poolname);
-            free(poolname);
-        }
-        if (numa) {
-            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
-
-            putchar(' ');
-            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
-        }
-        putchar('\n');
-    }
-
-    libxl_bitmap_dispose(&nodemap);
-    libxl_physinfo_dispose(&physinfo);
-}
-
-static void list_vm(void)
-{
-    libxl_vminfo *info;
-    char *domname;
-    int nb_vm, i;
-
-    info = libxl_list_vm(ctx, &nb_vm);
-
-    if (!info) {
-        fprintf(stderr, "libxl_list_vm failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    printf("UUID                                  ID    name\n");
-    for (i = 0; i < nb_vm; i++) {
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
-            info[i].domid, domname);
-        free(domname);
-    }
-    libxl_vminfo_list_free(info, nb_vm);
-}
-
 static void core_dump_domain(uint32_t domid, const char *filename)
 {
     int rc;
@@ -2412,99 +2179,6 @@ int main_reboot(int argc, char **argv)
     return main_shutdown_or_reboot(1, argc, argv);
 }
 
-int main_list(int argc, char **argv)
-{
-    int opt;
-    bool verbose = false;
-    bool context = false;
-    bool details = false;
-    bool cpupool = false;
-    bool numa = false;
-    static struct option opts[] = {
-        {"long", 0, 0, 'l'},
-        {"verbose", 0, 0, 'v'},
-        {"context", 0, 0, 'Z'},
-        {"cpupool", 0, 0, 'c'},
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-
-    libxl_dominfo info_buf;
-    libxl_dominfo *info, *info_free=0;
-    int nb_domain, rc;
-
-    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
-    case 'l':
-        details = true;
-        break;
-    case 'v':
-        verbose = true;
-        break;
-    case 'Z':
-        context = true;
-        break;
-    case 'c':
-        cpupool = true;
-        break;
-    case 'n':
-        numa = true;
-        break;
-    }
-
-    libxl_dominfo_init(&info_buf);
-
-    if (optind >= argc) {
-        info = libxl_list_domain(ctx, &nb_domain);
-        if (!info) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-        info_free = info;
-    } else if (optind == argc-1) {
-        uint32_t domid = xfind_domain(argv[optind]);
-        rc = libxl_domain_info(ctx, &info_buf, domid);
-        if (rc == ERROR_DOMAIN_NOTFOUND) {
-            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
-                argv[optind]);
-            return EXIT_FAILURE;
-        }
-        if (rc) {
-            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
-            return EXIT_FAILURE;
-        }
-        info = &info_buf;
-        nb_domain = 1;
-    } else {
-        help("list");
-        return EXIT_FAILURE;
-    }
-
-    if (details)
-        list_domains_details(info, nb_domain);
-    else
-        list_domains(verbose, context, false /* claim */, numa, cpupool,
-                     info, nb_domain);
-
-    if (info_free)
-        libxl_dominfo_list_free(info, nb_domain);
-
-    libxl_dominfo_dispose(&info_buf);
-
-    return EXIT_SUCCESS;
-}
-
-int main_vm_list(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
-        /* No options */
-    }
-
-    list_vm();
-    return EXIT_SUCCESS;
-}
-
 int main_create(int argc, char **argv)
 {
     const char *filename = NULL;
@@ -2600,6 +2274,9 @@ int main_create(int argc, char **argv)
     return 0;
 }
 
+extern void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh);
 int main_config_update(int argc, char **argv)
 {
     uint32_t domid;
@@ -2737,309 +2414,6 @@ int main_button_press(int argc, char **argv)
     return 0;
 }
 
-/* Possibly select a specific piece of `xl info` to print. */
-static const char *info_name;
-static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
-static int maybe_printf(const char *fmt, ...)
-{
-    va_list ap;
-    char *str;
-    int count = 0;
-
-    va_start(ap, fmt);
-    if (vasprintf(&str, fmt, ap) != -1) {
-        if (info_name) {
-            char *s;
-
-            if (!strncmp(str, info_name, strlen(info_name)) &&
-                (s = strchr(str, ':')) && s[1] == ' ')
-                count = fputs(&s[2], stdout);
-        } else
-            count = fputs(str, stdout);
-
-        free(str);
-    }
-    va_end(ap);
-
-    return count;
-}
-
-static void output_xeninfo(void)
-{
-    const libxl_version_info *info;
-    libxl_scheduler sched;
-    int rc;
-
-    if (!(info = libxl_get_version_info(ctx))) {
-        fprintf(stderr, "libxl_get_version_info failed.\n");
-        return;
-    }
-
-    rc = libxl_get_scheduler(ctx);
-    if (rc < 0) {
-        fprintf(stderr, "get_scheduler sysctl failed.\n");
-        return;
-    }
-    sched = rc;
-
-    maybe_printf("xen_major              : %d\n", info->xen_version_major);
-    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
-    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
-    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
-           info->xen_version_minor, info->xen_version_extra);
-    maybe_printf("xen_caps               : %s\n", info->capabilities);
-    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
-    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
-    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
-    maybe_printf("xen_changeset          : %s\n", info->changeset);
-    maybe_printf("xen_commandline        : %s\n", info->commandline);
-    maybe_printf("cc_compiler            : %s\n", info->compiler);
-    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
-    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
-    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
-    maybe_printf("build_id               : %s\n", info->build_id);
-
-    return;
-}
-
-static void output_nodeinfo(void)
-{
-    struct utsname utsbuf;
-
-    if (uname(&utsbuf) < 0)
-        return;
-
-    maybe_printf("host                   : %s\n", utsbuf.nodename);
-    maybe_printf("release                : %s\n", utsbuf.release);
-    maybe_printf("version                : %s\n", utsbuf.version);
-    maybe_printf("machine                : %s\n", utsbuf.machine);
-}
-
-static void output_physinfo(void)
-{
-    libxl_physinfo info;
-    const libxl_version_info *vinfo;
-    unsigned int i;
-    libxl_bitmap cpumap;
-    int n = 0;
-
-    if (libxl_get_physinfo(ctx, &info) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        return;
-    }
-    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
-    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
-    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
-    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
-    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
-    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
-
-    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
-         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
-         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
-        );
-
-    maybe_printf("virt_caps              :%s%s\n",
-         info.cap_hvm ? " hvm" : "",
-         info.cap_hvm_directio ? " hvm_directio" : ""
-        );
-
-    vinfo = libxl_get_version_info(ctx);
-    if (vinfo) {
-        i = (1 << 20) / vinfo->pagesize;
-        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
-        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
-        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
-        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
-        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
-    }
-    if (!libxl_get_freecpus(ctx, &cpumap)) {
-        libxl_for_each_bit(i, cpumap)
-            if (libxl_bitmap_test(&cpumap, i))
-                n++;
-        maybe_printf("free_cpus              : %d\n", n);
-        free(cpumap.map);
-    }
-    libxl_physinfo_dispose(&info);
-    return;
-}
-
-static void output_numainfo(void)
-{
-    libxl_numainfo *info;
-    int i, j, nr;
-
-    info = libxl_get_numainfo(ctx, &nr);
-    if (info == NULL) {
-        fprintf(stderr, "libxl_get_numainfo failed.\n");
-        return;
-    }
-
-    printf("numa_info              :\n");
-    printf("node:    memsize    memfree    distances\n");
-
-    for (i = 0; i < nr; i++) {
-        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
-            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
-                   info[i].size >> 20, info[i].free >> 20,
-                   info[i].dists[0]);
-            for (j = 1; j < info[i].num_dists; j++)
-                printf(",%d", info[i].dists[j]);
-            printf("\n");
-        }
-    }
-
-    libxl_numainfo_list_free(info, nr);
-
-    return;
-}
-
-static void output_topologyinfo(void)
-{
-    libxl_cputopology *cpuinfo;
-    int i, nr;
-    libxl_pcitopology *pciinfo;
-    int valid_devs = 0;
-
-
-    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
-    if (cpuinfo == NULL) {
-        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
-        return;
-    }
-
-    printf("cpu_topology           :\n");
-    printf("cpu:    core    socket     node\n");
-
-    for (i = 0; i < nr; i++) {
-        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
-            printf("%3d:    %4d     %4d     %4d\n", i,
-                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
-    }
-
-    libxl_cputopology_list_free(cpuinfo, nr);
-
-    pciinfo = libxl_get_pci_topology(ctx, &nr);
-    if (pciinfo == NULL) {
-        fprintf(stderr, "libxl_get_pci_topology failed.\n");
-        return;
-    }
-
-    printf("device topology        :\n");
-    printf("device           node\n");
-    for (i = 0; i < nr; i++) {
-        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
-            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
-                   pciinfo[i].bus,
-                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
-                   pciinfo[i].node);
-            valid_devs++;
-        }
-    }
-
-    if (valid_devs == 0)
-        printf("No device topology data available\n");
-
-    libxl_pcitopology_list_free(pciinfo, nr);
-
-    return;
-}
-
-static void print_info(int numa)
-{
-    output_nodeinfo();
-
-    output_physinfo();
-
-    if (numa) {
-        output_topologyinfo();
-        output_numainfo();
-    }
-    output_xeninfo();
-
-    maybe_printf("xend_config_format     : 4\n");
-
-    return;
-}
-
-int main_info(int argc, char **argv)
-{
-    int opt;
-    static struct option opts[] = {
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-    int numa = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
-    case 'n':
-        numa = 1;
-        break;
-    }
-
-    /*
-     * If an extra argument is provided, filter out a specific piece of
-     * information.
-     */
-    if (numa == 0 && argc > optind)
-        info_name = argv[optind];
-
-    print_info(numa);
-    return 0;
-}
-
-int main_domid(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *domname = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
-        /* No options */
-    }
-
-    domname = argv[optind];
-
-    if (libxl_name_to_domid(ctx, domname, &domid)) {
-        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
-        return EXIT_FAILURE;
-    }
-
-    printf("%u\n", domid);
-
-    return EXIT_SUCCESS;
-}
-
-int main_domname(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    char *domname = NULL;
-    char *endptr = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
-        /* No options */
-    }
-
-    domid = strtol(argv[optind], &endptr, 10);
-    if (domid == 0 && !strcmp(endptr, argv[optind])) {
-        /*no digits at all*/
-        fprintf(stderr, "Invalid domain id.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    domname = libxl_domid_to_name(ctx, domid);
-    if (!domname) {
-        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
-        return EXIT_FAILURE;
-    }
-
-    printf("%s\n", domname);
-    free(domname);
-
-    return EXIT_SUCCESS;
-}
-
 int main_rename(int argc, char **argv)
 {
     uint32_t domid;
@@ -3140,43 +2514,6 @@ int main_debug_keys(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_dmesg(int argc, char **argv)
-{
-    unsigned int clear = 0;
-    libxl_xen_console_reader *cr;
-    char *line;
-    int opt, ret = 1;
-
-    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
-    case 'c':
-        clear = 1;
-        break;
-    }
-
-    cr = libxl_xen_console_read_start(ctx, clear);
-    if (!cr)
-        goto finish;
-
-    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
-        printf("%s", line);
-
-finish:
-    if (cr)
-        libxl_xen_console_read_finish(ctx, cr);
-    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-int main_top(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
-        /* No options */
-    }
-
-    return system("xentop");
-}
-
 int main_channellist(int argc, char **argv)
 {
     int opt;
@@ -3221,220 +2558,6 @@ int main_channellist(int argc, char **argv)
     return 0;
 }
 
-static char *uptime_to_string(unsigned long uptime, int short_mode)
-{
-    int sec, min, hour, day;
-    char *time_string;
-
-    day = (int)(uptime / 86400);
-    uptime -= (day * 86400);
-    hour = (int)(uptime / 3600);
-    uptime -= (hour * 3600);
-    min = (int)(uptime / 60);
-    uptime -= (min * 60);
-    sec = uptime;
-
-    if (short_mode)
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
-        else
-            xasprintf(&time_string, "%2d:%02d", hour, min);
-    else
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
-        else
-            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
-
-    return time_string;
-}
-
-int main_claims(int argc, char **argv)
-{
-    libxl_dominfo *info;
-    int opt;
-    int nb_domain;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
-        /* No options */
-    }
-
-    if (!claim_mode)
-        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-
-    list_domains(false /* verbose */, false /* context */, true /* claim */,
-                 false /* numa */, false /* cpupool */, info, nb_domain);
-
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-static char *current_time_to_string(time_t now)
-{
-    char now_str[100];
-    struct tm *tmp;
-
-    tmp = localtime(&now);
-    if (tmp == NULL) {
-        fprintf(stderr, "Get localtime error");
-        exit(-1);
-    }
-    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
-        fprintf(stderr, "strftime returned 0");
-        exit(-1);
-    }
-    return strdup(now_str);
-}
-
-static void print_dom0_uptime(int short_mode, time_t now)
-{
-    int fd;
-    ssize_t nr;
-    char buf[512];
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    fd = open("/proc/uptime", O_RDONLY);
-    if (fd == -1)
-        goto err;
-
-    nr = read(fd, buf, sizeof(buf) - 1);
-    if (nr == -1) {
-        close(fd);
-        goto err;
-    }
-    close(fd);
-
-    buf[nr] = '\0';
-
-    strtok(buf, " ");
-    uptime = strtoul(buf, NULL, 10);
-
-    domname = libxl_domid_to_name(ctx, 0);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, 0);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               0, uptime_str);
-    }
-
-    free(now_str);
-    free(uptime_str);
-    free(domname);
-    return;
-err:
-    fprintf(stderr, "Can not get Dom0 uptime.\n");
-    exit(-1);
-}
-
-static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
-{
-    uint32_t s_time = 0;
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    s_time = libxl_vm_get_start_time(ctx, domuid);
-    if (s_time == -1)
-        return;
-    uptime = now - s_time;
-    domname = libxl_domid_to_name(ctx, domuid);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, domuid);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               domuid, uptime_str);
-    }
-
-    free(domname);
-    free(now_str);
-    free(uptime_str);
-    return;
-}
-
-static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
-{
-    libxl_vminfo *info;
-    time_t now;
-    int nb_vm, i;
-
-    now = time(NULL);
-
-    if (!short_mode)
-        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
-
-    if (nb_doms == 0) {
-        print_dom0_uptime(short_mode, now);
-        info = libxl_list_vm(ctx, &nb_vm);
-        if (info == NULL) {
-            fprintf(stderr, "Could not list vms.\n");
-            return;
-        }
-        for (i = 0; i < nb_vm; i++) {
-            if (info[i].domid == 0) continue;
-            print_domU_uptime(info[i].domid, short_mode, now);
-        }
-        libxl_vminfo_list_free(info, nb_vm);
-    } else {
-        for (i = 0; i < nb_doms; i++) {
-            if (doms[i] == 0)
-                print_dom0_uptime(short_mode, now);
-            else
-                print_domU_uptime(doms[i], short_mode, now);
-        }
-    }
-}
-
-int main_uptime(int argc, char **argv)
-{
-    const char *dom;
-    int short_mode = 0;
-    uint32_t domains[100];
-    int nb_doms = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
-    case 's':
-        short_mode = 1;
-        break;
-    }
-
-    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
-        domains[nb_doms] = xfind_domain(dom);
-
-    print_uptime(short_mode, domains, nb_doms);
-
-    return 0;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_info.c b/tools/xl/xl_info.c
new file mode 100644
index 0000000000..e5d5a41e49
--- /dev/null
+++ b/tools/xl/xl_info.c
@@ -0,0 +1,925 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_json.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+/* Possibly select a specific piece of `xl info` to print. */
+static const char *info_name;
+static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
+static int maybe_printf(const char *fmt, ...)
+{
+    va_list ap;
+    char *str;
+    int count = 0;
+
+    va_start(ap, fmt);
+    if (vasprintf(&str, fmt, ap) != -1) {
+        if (info_name) {
+            char *s;
+
+            if (!strncmp(str, info_name, strlen(info_name)) &&
+                (s = strchr(str, ':')) && s[1] == ' ')
+                count = fputs(&s[2], stdout);
+        } else
+            count = fputs(str, stdout);
+
+        free(str);
+    }
+    va_end(ap);
+
+    return count;
+}
+
+static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
+                                            libxl_domain_config *d_config)
+{
+    yajl_gen_status s;
+
+    s = yajl_gen_map_open(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"domid",
+                        sizeof("domid")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    if (domid != -1)
+        s = yajl_gen_integer(hand, domid);
+    else
+        s = yajl_gen_null(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"config",
+                        sizeof("config")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    s = libxl_domain_config_gen_json(hand, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_map_close(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+out:
+    return s;
+}
+
+void printf_info(enum output_format output_format,
+                 int domid,
+                 libxl_domain_config *d_config, FILE *fh);
+void printf_info(enum output_format output_format,
+                 int domid,
+                 libxl_domain_config *d_config, FILE *fh)
+{
+    if (output_format == OUTPUT_FORMAT_SXP)
+        return printf_info_sexp(domid, d_config, fh);
+
+    const char *buf;
+    libxl_yajl_length len = 0;
+    yajl_gen_status s;
+    yajl_gen hand;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        fprintf(stderr, "unable to allocate JSON generator\n");
+        return;
+    }
+
+    s = printf_info_one_json(hand, domid, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    fputs(buf, fh);
+
+out:
+    yajl_gen_free(hand);
+
+    if (s != yajl_gen_status_ok)
+        fprintf(stderr,
+                "unable to format domain config as JSON (YAJL:%d)\n", s);
+
+    xflush_stream(fh);
+}
+
+static void output_xeninfo(void)
+{
+    const libxl_version_info *info;
+    libxl_scheduler sched;
+    int rc;
+
+    if (!(info = libxl_get_version_info(ctx))) {
+        fprintf(stderr, "libxl_get_version_info failed.\n");
+        return;
+    }
+
+    rc = libxl_get_scheduler(ctx);
+    if (rc < 0) {
+        fprintf(stderr, "get_scheduler sysctl failed.\n");
+        return;
+    }
+    sched = rc;
+
+    maybe_printf("xen_major              : %d\n", info->xen_version_major);
+    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
+    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
+    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
+           info->xen_version_minor, info->xen_version_extra);
+    maybe_printf("xen_caps               : %s\n", info->capabilities);
+    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
+    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
+    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
+    maybe_printf("xen_changeset          : %s\n", info->changeset);
+    maybe_printf("xen_commandline        : %s\n", info->commandline);
+    maybe_printf("cc_compiler            : %s\n", info->compiler);
+    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
+    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
+    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
+    maybe_printf("build_id               : %s\n", info->build_id);
+
+    return;
+}
+
+static void output_nodeinfo(void)
+{
+    struct utsname utsbuf;
+
+    if (uname(&utsbuf) < 0)
+        return;
+
+    maybe_printf("host                   : %s\n", utsbuf.nodename);
+    maybe_printf("release                : %s\n", utsbuf.release);
+    maybe_printf("version                : %s\n", utsbuf.version);
+    maybe_printf("machine                : %s\n", utsbuf.machine);
+}
+
+static void output_physinfo(void)
+{
+    libxl_physinfo info;
+    const libxl_version_info *vinfo;
+    unsigned int i;
+    libxl_bitmap cpumap;
+    int n = 0;
+
+    if (libxl_get_physinfo(ctx, &info) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        return;
+    }
+    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
+    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
+    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
+    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
+    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
+    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
+
+    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
+         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
+         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
+        );
+
+    maybe_printf("virt_caps              :%s%s\n",
+         info.cap_hvm ? " hvm" : "",
+         info.cap_hvm_directio ? " hvm_directio" : ""
+        );
+
+    vinfo = libxl_get_version_info(ctx);
+    if (vinfo) {
+        i = (1 << 20) / vinfo->pagesize;
+        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
+        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
+        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
+        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
+        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
+    }
+    if (!libxl_get_freecpus(ctx, &cpumap)) {
+        libxl_for_each_bit(i, cpumap)
+            if (libxl_bitmap_test(&cpumap, i))
+                n++;
+        maybe_printf("free_cpus              : %d\n", n);
+        free(cpumap.map);
+    }
+    libxl_physinfo_dispose(&info);
+    return;
+}
+
+static void output_numainfo(void)
+{
+    libxl_numainfo *info;
+    int i, j, nr;
+
+    info = libxl_get_numainfo(ctx, &nr);
+    if (info == NULL) {
+        fprintf(stderr, "libxl_get_numainfo failed.\n");
+        return;
+    }
+
+    printf("numa_info              :\n");
+    printf("node:    memsize    memfree    distances\n");
+
+    for (i = 0; i < nr; i++) {
+        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
+            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
+                   info[i].size >> 20, info[i].free >> 20,
+                   info[i].dists[0]);
+            for (j = 1; j < info[i].num_dists; j++)
+                printf(",%d", info[i].dists[j]);
+            printf("\n");
+        }
+    }
+
+    libxl_numainfo_list_free(info, nr);
+
+    return;
+}
+
+static void output_topologyinfo(void)
+{
+    libxl_cputopology *cpuinfo;
+    int i, nr;
+    libxl_pcitopology *pciinfo;
+    int valid_devs = 0;
+
+
+    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
+    if (cpuinfo == NULL) {
+        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
+        return;
+    }
+
+    printf("cpu_topology           :\n");
+    printf("cpu:    core    socket     node\n");
+
+    for (i = 0; i < nr; i++) {
+        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
+            printf("%3d:    %4d     %4d     %4d\n", i,
+                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
+    }
+
+    libxl_cputopology_list_free(cpuinfo, nr);
+
+    pciinfo = libxl_get_pci_topology(ctx, &nr);
+    if (pciinfo == NULL) {
+        fprintf(stderr, "libxl_get_pci_topology failed.\n");
+        return;
+    }
+
+    printf("device topology        :\n");
+    printf("device           node\n");
+    for (i = 0; i < nr; i++) {
+        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
+            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
+                   pciinfo[i].bus,
+                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
+                   pciinfo[i].node);
+            valid_devs++;
+        }
+    }
+
+    if (valid_devs == 0)
+        printf("No device topology data available\n");
+
+    libxl_pcitopology_list_free(pciinfo, nr);
+
+    return;
+}
+
+static void print_info(int numa)
+{
+    output_nodeinfo();
+
+    output_physinfo();
+
+    if (numa) {
+        output_topologyinfo();
+        output_numainfo();
+    }
+    output_xeninfo();
+
+    maybe_printf("xend_config_format     : 4\n");
+
+    return;
+}
+
+static void list_vm(void)
+{
+    libxl_vminfo *info;
+    char *domname;
+    int nb_vm, i;
+
+    info = libxl_list_vm(ctx, &nb_vm);
+
+    if (!info) {
+        fprintf(stderr, "libxl_list_vm failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    printf("UUID                                  ID    name\n");
+    for (i = 0; i < nb_vm; i++) {
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
+            info[i].domid, domname);
+        free(domname);
+    }
+    libxl_vminfo_list_free(info, nb_vm);
+}
+
+static void list_domains(bool verbose, bool context, bool claim, bool numa,
+                         bool cpupool, const libxl_dominfo *info, int nb_domain)
+{
+    int i;
+    static const char shutdown_reason_letters[]= "-rscwS";
+    libxl_bitmap nodemap;
+    libxl_physinfo physinfo;
+
+    libxl_bitmap_init(&nodemap);
+    libxl_physinfo_init(&physinfo);
+
+    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
+    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
+    if (context && !verbose) printf("   Security Label");
+    if (claim) printf("  Claimed");
+    if (cpupool) printf("         Cpupool");
+    if (numa) {
+        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
+            exit(EXIT_FAILURE);
+        }
+        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+            fprintf(stderr, "libxl_physinfo failed.\n");
+            libxl_bitmap_dispose(&nodemap);
+            exit(EXIT_FAILURE);
+        }
+
+        printf(" NODE Affinity");
+    }
+    printf("\n");
+    for (i = 0; i < nb_domain; i++) {
+        char *domname;
+        libxl_shutdown_reason shutdown_reason;
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
+        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
+                domname,
+                info[i].domid,
+                (unsigned long) ((info[i].current_memkb +
+                    info[i].outstanding_memkb)/ 1024),
+                info[i].vcpu_online,
+                info[i].running ? 'r' : '-',
+                info[i].blocked ? 'b' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].shutdown ? 's' : '-',
+                (shutdown_reason >= 0 &&
+                 shutdown_reason < sizeof(shutdown_reason_letters)-1
+                 ? shutdown_reason_letters[shutdown_reason] : '?'),
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+        free(domname);
+        if (verbose) {
+            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
+            if (info[i].shutdown) printf(" %8x", shutdown_reason);
+            else printf(" %8s", "-");
+        }
+        if (claim)
+            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
+        if (verbose || context)
+            printf(" %16s", info[i].ssid_label ? : "-");
+        if (cpupool) {
+            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
+            printf("%16s", poolname);
+            free(poolname);
+        }
+        if (numa) {
+            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
+
+            putchar(' ');
+            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
+        }
+        putchar('\n');
+    }
+
+    libxl_bitmap_dispose(&nodemap);
+    libxl_physinfo_dispose(&physinfo);
+}
+
+static void list_domains_details(const libxl_dominfo *info, int nb_domain)
+{
+    libxl_domain_config d_config;
+
+    int i, rc;
+
+    yajl_gen hand = NULL;
+    yajl_gen_status s;
+    const char *buf;
+    libxl_yajl_length yajl_len = 0;
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        hand = libxl_yajl_gen_alloc(NULL);
+        if (!hand) {
+            fprintf(stderr, "unable to allocate JSON generator\n");
+            return;
+        }
+
+        s = yajl_gen_array_open(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    } else
+        s = yajl_gen_status_ok;
+
+    for (i = 0; i < nb_domain; i++) {
+        libxl_domain_config_init(&d_config);
+        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
+        if (rc)
+            continue;
+        if (default_output_format == OUTPUT_FORMAT_JSON)
+            s = printf_info_one_json(hand, info[i].domid, &d_config);
+        else
+            printf_info_sexp(info[i].domid, &d_config, stdout);
+        libxl_domain_config_dispose(&d_config);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    }
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        s = yajl_gen_array_close(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        puts(buf);
+    }
+
+out:
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        yajl_gen_free(hand);
+        if (s != yajl_gen_status_ok)
+            fprintf(stderr,
+                    "unable to format domain config as JSON (YAJL:%d)\n", s);
+    }
+}
+
+
+int main_list(int argc, char **argv)
+{
+    int opt;
+    bool verbose = false;
+    bool context = false;
+    bool details = false;
+    bool cpupool = false;
+    bool numa = false;
+    static struct option opts[] = {
+        {"long", 0, 0, 'l'},
+        {"verbose", 0, 0, 'v'},
+        {"context", 0, 0, 'Z'},
+        {"cpupool", 0, 0, 'c'},
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+
+    libxl_dominfo info_buf;
+    libxl_dominfo *info, *info_free=0;
+    int nb_domain, rc;
+
+    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
+    case 'l':
+        details = true;
+        break;
+    case 'v':
+        verbose = true;
+        break;
+    case 'Z':
+        context = true;
+        break;
+    case 'c':
+        cpupool = true;
+        break;
+    case 'n':
+        numa = true;
+        break;
+    }
+
+    libxl_dominfo_init(&info_buf);
+
+    if (optind >= argc) {
+        info = libxl_list_domain(ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+        info_free = info;
+    } else if (optind == argc-1) {
+        uint32_t domid = xfind_domain(argv[optind]);
+        rc = libxl_domain_info(ctx, &info_buf, domid);
+        if (rc == ERROR_DOMAIN_NOTFOUND) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return EXIT_FAILURE;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return EXIT_FAILURE;
+        }
+        info = &info_buf;
+        nb_domain = 1;
+    } else {
+        help("list");
+        return EXIT_FAILURE;
+    }
+
+    if (details)
+        list_domains_details(info, nb_domain);
+    else
+        list_domains(verbose, context, false /* claim */, numa, cpupool,
+                     info, nb_domain);
+
+    if (info_free)
+        libxl_dominfo_list_free(info, nb_domain);
+
+    libxl_dominfo_dispose(&info_buf);
+
+    return EXIT_SUCCESS;
+}
+
+int main_vm_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
+        /* No options */
+    }
+
+    list_vm();
+    return EXIT_SUCCESS;
+}
+
+int main_info(int argc, char **argv)
+{
+    int opt;
+    static struct option opts[] = {
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+    int numa = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
+    case 'n':
+        numa = 1;
+        break;
+    }
+
+    /*
+     * If an extra argument is provided, filter out a specific piece of
+     * information.
+     */
+    if (numa == 0 && argc > optind)
+        info_name = argv[optind];
+
+    print_info(numa);
+    return 0;
+}
+
+int main_domid(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *domname = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
+        /* No options */
+    }
+
+    domname = argv[optind];
+
+    if (libxl_name_to_domid(ctx, domname, &domid)) {
+        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
+        return EXIT_FAILURE;
+    }
+
+    printf("%u\n", domid);
+
+    return EXIT_SUCCESS;
+}
+
+int main_domname(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    char *domname = NULL;
+    char *endptr = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
+        /* No options */
+    }
+
+    domid = strtol(argv[optind], &endptr, 10);
+    if (domid == 0 && !strcmp(endptr, argv[optind])) {
+        /*no digits at all*/
+        fprintf(stderr, "Invalid domain id.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    domname = libxl_domid_to_name(ctx, domid);
+    if (!domname) {
+        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
+        return EXIT_FAILURE;
+    }
+
+    printf("%s\n", domname);
+    free(domname);
+
+    return EXIT_SUCCESS;
+}
+
+static char *uptime_to_string(unsigned long uptime, int short_mode)
+{
+    int sec, min, hour, day;
+    char *time_string;
+
+    day = (int)(uptime / 86400);
+    uptime -= (day * 86400);
+    hour = (int)(uptime / 3600);
+    uptime -= (hour * 3600);
+    min = (int)(uptime / 60);
+    uptime -= (min * 60);
+    sec = uptime;
+
+    if (short_mode)
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
+        else
+            xasprintf(&time_string, "%2d:%02d", hour, min);
+    else
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
+        else
+            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
+
+    return time_string;
+}
+
+int main_claims(int argc, char **argv)
+{
+    libxl_dominfo *info;
+    int opt;
+    int nb_domain;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
+        /* No options */
+    }
+
+    if (!claim_mode)
+        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+
+    list_domains(false /* verbose */, false /* context */, true /* claim */,
+                 false /* numa */, false /* cpupool */, info, nb_domain);
+
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+static char *current_time_to_string(time_t now)
+{
+    char now_str[100];
+    struct tm *tmp;
+
+    tmp = localtime(&now);
+    if (tmp == NULL) {
+        fprintf(stderr, "Get localtime error");
+        exit(-1);
+    }
+    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
+        fprintf(stderr, "strftime returned 0");
+        exit(-1);
+    }
+    return strdup(now_str);
+}
+
+static void print_dom0_uptime(int short_mode, time_t now)
+{
+    int fd;
+    ssize_t nr;
+    char buf[512];
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    fd = open("/proc/uptime", O_RDONLY);
+    if (fd == -1)
+        goto err;
+
+    nr = read(fd, buf, sizeof(buf) - 1);
+    if (nr == -1) {
+        close(fd);
+        goto err;
+    }
+    close(fd);
+
+    buf[nr] = '\0';
+
+    strtok(buf, " ");
+    uptime = strtoul(buf, NULL, 10);
+
+    domname = libxl_domid_to_name(ctx, 0);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, 0);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               0, uptime_str);
+    }
+
+    free(now_str);
+    free(uptime_str);
+    free(domname);
+    return;
+err:
+    fprintf(stderr, "Can not get Dom0 uptime.\n");
+    exit(-1);
+}
+
+static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
+{
+    uint32_t s_time = 0;
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    s_time = libxl_vm_get_start_time(ctx, domuid);
+    if (s_time == -1)
+        return;
+    uptime = now - s_time;
+    domname = libxl_domid_to_name(ctx, domuid);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, domuid);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               domuid, uptime_str);
+    }
+
+    free(domname);
+    free(now_str);
+    free(uptime_str);
+    return;
+}
+
+static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
+{
+    libxl_vminfo *info;
+    time_t now;
+    int nb_vm, i;
+
+    now = time(NULL);
+
+    if (!short_mode)
+        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
+
+    if (nb_doms == 0) {
+        print_dom0_uptime(short_mode, now);
+        info = libxl_list_vm(ctx, &nb_vm);
+        if (info == NULL) {
+            fprintf(stderr, "Could not list vms.\n");
+            return;
+        }
+        for (i = 0; i < nb_vm; i++) {
+            if (info[i].domid == 0) continue;
+            print_domU_uptime(info[i].domid, short_mode, now);
+        }
+        libxl_vminfo_list_free(info, nb_vm);
+    } else {
+        for (i = 0; i < nb_doms; i++) {
+            if (doms[i] == 0)
+                print_dom0_uptime(short_mode, now);
+            else
+                print_domU_uptime(doms[i], short_mode, now);
+        }
+    }
+}
+
+int main_uptime(int argc, char **argv)
+{
+    const char *dom;
+    int short_mode = 0;
+    uint32_t domains[100];
+    int nb_doms = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
+    case 's':
+        short_mode = 1;
+        break;
+    }
+
+    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
+        domains[nb_doms] = xfind_domain(dom);
+
+    print_uptime(short_mode, domains, nb_doms);
+
+    return 0;
+}
+
+int main_dmesg(int argc, char **argv)
+{
+    unsigned int clear = 0;
+    libxl_xen_console_reader *cr;
+    char *line;
+    int opt, ret = 1;
+
+    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
+    case 'c':
+        clear = 1;
+        break;
+    }
+
+    cr = libxl_xen_console_read_start(ctx, clear);
+    if (!cr)
+        goto finish;
+
+    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
+        printf("%s", line);
+
+finish:
+    if (cr)
+        libxl_xen_console_read_finish(ctx, cr);
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+int main_top(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
+        /* No options */
+    }
+
+    return system("xentop");
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
