[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v7 10/32] libxl: switch HVM domain building to use xc_dom_* helpers
Now that we have all the code in place HVM domain building in libxl can be switched to use the xc_dom_* family of functions, just like they are used in order to build PV guests. Signed-off-by: Roger Pau Monnà <roger.pau@xxxxxxxxxx> Acked-by: Wei Liu <wei.liu2@xxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> Cc: Ian Campbell <ian.campbell@xxxxxxxxxx> Cc: Wei Liu <wei.liu2@xxxxxxxxxx> --- Changes since v6: - Fix uninitialized usage of rc in libxl__build_hvm. Changes since v4: - Add Wei Liu Acked-by. --- tools/libxl/libxl_arch.h | 2 +- tools/libxl/libxl_arm.c | 2 +- tools/libxl/libxl_dm.c | 18 ++-- tools/libxl/libxl_dom.c | 228 +++++++++++++++++++++++++------------------ tools/libxl/libxl_internal.h | 4 +- tools/libxl/libxl_vnuma.c | 12 ++- tools/libxl/libxl_x86.c | 8 +- 7 files changed, 157 insertions(+), 117 deletions(-) diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h index bd030b6..34a853c 100644 --- a/tools/libxl/libxl_arch.h +++ b/tools/libxl/libxl_arch.h @@ -60,6 +60,6 @@ _hidden int libxl__arch_domain_construct_memmap(libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid, - struct xc_hvm_build_args *args); + struct xc_dom_image *dom); #endif diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 0af8010..1195b37 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -974,7 +974,7 @@ int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq) int libxl__arch_domain_construct_memmap(libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { return 0; } diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 71a1a3e..8e337de 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -18,6 +18,8 @@ #include "libxl_osdeps.h" /* must come before any other headers */ #include "libxl_internal.h" + +#include <xc_dom.h> #include <xen/hvm/e820.h> static const char *libxl_tapif_script(libxl__gc *gc) @@ -181,7 +183,7 @@ add_rdm_entry(libxl__gc *gc, libxl_domain_config *d_config, int libxl__domain_device_construct_rdm(libxl__gc *gc, libxl_domain_config *d_config, uint64_t rdm_mem_boundary, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { int i, j, conflict, rc; struct xen_reserved_device_memory *xrdm = NULL; @@ -189,7 +191,7 @@ int libxl__domain_device_construct_rdm(libxl__gc *gc, uint16_t seg; uint8_t bus, devfn; uint64_t rdm_start, rdm_size; - uint64_t highmem_end = args->highmem_end ? args->highmem_end : (1ull<<32); + uint64_t highmem_end = dom->highmem_end ? dom->highmem_end : (1ull<<32); /* * We just want to construct RDM once since RDM is specific to the @@ -303,7 +305,7 @@ int libxl__domain_device_construct_rdm(libxl__gc *gc, for (i = 0; i < d_config->num_rdms; i++) { rdm_start = d_config->rdms[i].start; rdm_size = d_config->rdms[i].size; - conflict = overlaps_rdm(0, args->lowmem_end, rdm_start, rdm_size); + conflict = overlaps_rdm(0, dom->lowmem_end, rdm_start, rdm_size); if (!conflict) continue; @@ -314,14 +316,14 @@ int libxl__domain_device_construct_rdm(libxl__gc *gc, * We will move downwards lowmem_end so we have to expand * highmem_end. */ - highmem_end += (args->lowmem_end - rdm_start); + highmem_end += (dom->lowmem_end - rdm_start); /* Now move downwards lowmem_end. */ - args->lowmem_end = rdm_start; + dom->lowmem_end = rdm_start; } } /* Sync highmem_end. */ - args->highmem_end = highmem_end; + dom->highmem_end = highmem_end; /* * Finally we can take same policy to check lowmem(< 2G) and @@ -331,11 +333,11 @@ int libxl__domain_device_construct_rdm(libxl__gc *gc, rdm_start = d_config->rdms[i].start; rdm_size = d_config->rdms[i].size; /* Does this entry conflict with lowmem? */ - conflict = overlaps_rdm(0, args->lowmem_end, + conflict = overlaps_rdm(0, dom->lowmem_end, rdm_start, rdm_size); /* Does this entry conflict with highmem? */ conflict |= overlaps_rdm((1ULL<<32), - args->highmem_end - (1ULL<<32), + dom->highmem_end - (1ULL<<32), rdm_start, rdm_size); if (!conflict) diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 01172b0..a9925b7 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -603,6 +603,63 @@ static int set_vnuma_info(libxl__gc *gc, uint32_t domid, return rc; } +static int libxl__build_dom(libxl__gc *gc, uint32_t domid, + libxl_domain_build_info *info, libxl__domain_build_state *state, + struct xc_dom_image *dom) +{ + uint64_t mem_kb; + int ret; + + if ( (ret = xc_dom_boot_xen_init(dom, CTX->xch, domid)) != 0 ) { + LOGE(ERROR, "xc_dom_boot_xen_init failed"); + goto out; + } +#ifdef GUEST_RAM_BASE + if ( (ret = xc_dom_rambase_init(dom, GUEST_RAM_BASE)) != 0 ) { + LOGE(ERROR, "xc_dom_rambase failed"); + goto out; + } +#endif + if ( (ret = xc_dom_parse_image(dom)) != 0 ) { + LOGE(ERROR, "xc_dom_parse_image failed"); + goto out; + } + if ( (ret = libxl__arch_domain_init_hw_description(gc, info, state, dom)) != 0 ) { + LOGE(ERROR, "libxl__arch_domain_init_hw_description failed"); + goto out; + } + + mem_kb = dom->container_type == XC_DOM_HVM_CONTAINER ? + (info->max_memkb - info->video_memkb) : info->target_memkb; + if ( (ret = xc_dom_mem_init(dom, mem_kb / 1024)) != 0 ) { + LOGE(ERROR, "xc_dom_mem_init failed"); + goto out; + } + if ( (ret = xc_dom_boot_mem_init(dom)) != 0 ) { + LOGE(ERROR, "xc_dom_boot_mem_init failed"); + goto out; + } + if ( (ret = libxl__arch_domain_finalise_hw_description(gc, info, dom)) != 0 ) { + LOGE(ERROR, "libxl__arch_domain_finalise_hw_description failed"); + goto out; + } + if ( (ret = xc_dom_build_image(dom)) != 0 ) { + LOGE(ERROR, "xc_dom_build_image failed"); + goto out; + } + if ( (ret = xc_dom_boot_image(dom)) != 0 ) { + LOGE(ERROR, "xc_dom_boot_image failed"); + goto out; + } + if ( (ret = xc_dom_gnttab_init(dom)) != 0 ) { + LOGE(ERROR, "xc_dom_gnttab_init failed"); + goto out; + } + +out: + return ret != 0 ? ERROR_FAIL : 0; +} + int libxl__build_pv(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *info, libxl__domain_build_state *state) { @@ -693,48 +750,9 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, dom->vnode_to_pnode[i] = info->vnuma_nodes[i].pnode; } - if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) { - LOGE(ERROR, "xc_dom_boot_xen_init failed"); - goto out; - } -#ifdef GUEST_RAM_BASE - if ( (ret = xc_dom_rambase_init(dom, GUEST_RAM_BASE)) != 0 ) { - LOGE(ERROR, "xc_dom_rambase failed"); + ret = libxl__build_dom(gc, domid, info, state, dom); + if (ret != 0) goto out; - } -#endif - if ( (ret = xc_dom_parse_image(dom)) != 0 ) { - LOGE(ERROR, "xc_dom_parse_image failed"); - goto out; - } - if ( (ret = libxl__arch_domain_init_hw_description(gc, info, state, dom)) != 0 ) { - LOGE(ERROR, "libxl__arch_domain_init_hw_description failed"); - goto out; - } - if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) { - LOGE(ERROR, "xc_dom_mem_init failed"); - goto out; - } - if ( (ret = xc_dom_boot_mem_init(dom)) != 0 ) { - LOGE(ERROR, "xc_dom_boot_mem_init failed"); - goto out; - } - if ( (ret = libxl__arch_domain_finalise_hw_description(gc, info, dom)) != 0 ) { - LOGE(ERROR, "libxl__arch_domain_finalise_hw_description failed"); - goto out; - } - if ( (ret = xc_dom_build_image(dom)) != 0 ) { - LOGE(ERROR, "xc_dom_build_image failed"); - goto out; - } - if ( (ret = xc_dom_boot_image(dom)) != 0 ) { - LOGE(ERROR, "xc_dom_boot_image failed"); - goto out; - } - if ( (ret = xc_dom_gnttab_init(dom)) != 0 ) { - LOGE(ERROR, "xc_dom_gnttab_init failed"); - goto out; - } if (xc_dom_feature_translated(dom)) { state->console_mfn = dom->console_pfn; @@ -794,39 +812,39 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid, static int hvm_build_set_xs_values(libxl__gc *gc, uint32_t domid, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { char *path = NULL; int ret = 0; - if (args->smbios_module.guest_addr_out) { + if (dom->smbios_module.guest_addr_out) { path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_ADDRESS, domid); ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64, - args->smbios_module.guest_addr_out); + dom->smbios_module.guest_addr_out); if (ret) goto err; path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_LENGTH, domid); ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x", - args->smbios_module.length); + dom->smbios_module.length); if (ret) goto err; } - if (args->acpi_module.guest_addr_out) { + if (dom->acpi_module.guest_addr_out) { path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_ADDRESS, domid); ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64, - args->acpi_module.guest_addr_out); + dom->acpi_module.guest_addr_out); if (ret) goto err; path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_LENGTH, domid); ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x", - args->acpi_module.length); + dom->acpi_module.length); if (ret) goto err; } @@ -840,7 +858,7 @@ err: static int libxl__domain_firmware(libxl__gc *gc, libxl_domain_build_info *info, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { libxl_ctx *ctx = libxl__gc_owner(gc); const char *firmware; @@ -866,8 +884,13 @@ static int libxl__domain_firmware(libxl__gc *gc, break; } } - args->image_file_name = libxl__abs_path(gc, firmware, - libxl__xenfirmwaredir_path()); + + rc = xc_dom_kernel_file(dom, libxl__abs_path(gc, firmware, + libxl__xenfirmwaredir_path())); + if (rc != 0) { + LOGE(ERROR, "xc_dom_kernel_file failed"); + goto out; + } if (info->u.hvm.smbios_firmware) { data = NULL; @@ -881,8 +904,8 @@ static int libxl__domain_firmware(libxl__gc *gc, libxl__ptr_add(gc, data); if (datalen) { /* Only accept non-empty files */ - args->smbios_module.data = data; - args->smbios_module.length = (uint32_t)datalen; + dom->smbios_module.data = data; + dom->smbios_module.length = (uint32_t)datalen; } } @@ -898,8 +921,8 @@ static int libxl__domain_firmware(libxl__gc *gc, libxl__ptr_add(gc, data); if (datalen) { /* Only accept non-empty files */ - args->acpi_module.data = data; - args->acpi_module.length = (uint32_t)datalen; + dom->acpi_module.data = data; + dom->acpi_module.length = (uint32_t)datalen; } } @@ -913,52 +936,63 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, libxl__domain_build_state *state) { libxl_ctx *ctx = libxl__gc_owner(gc); - struct xc_hvm_build_args args = {}; - int ret, rc; - uint64_t mmio_start, lowmem_end, highmem_end; + int rc; + uint64_t mmio_start, lowmem_end, highmem_end, mem_size; libxl_domain_build_info *const info = &d_config->b_info; + struct xc_dom_image *dom = NULL; + + xc_dom_loginit(ctx->xch); + + dom = xc_dom_allocate(ctx->xch, NULL, NULL); + if (!dom) { + LOGE(ERROR, "xc_dom_allocate failed"); + rc = ERROR_NOMEM; + goto out; + } + + dom->container_type = XC_DOM_HVM_CONTAINER; - memset(&args, 0, sizeof(struct xc_hvm_build_args)); /* The params from the configuration file are in Mb, which are then * multiplied by 1 Kb. This was then divided off when calling * the old xc_hvm_build_target_mem() which then turned them to bytes. * Do all this in one step here... */ - args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10; - args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10; - args.claim_enabled = libxl_defbool_val(info->claim_mode); + mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10; + dom->target_pages = (uint64_t)(info->target_memkb - info->video_memkb) >> 2; + dom->claim_enabled = libxl_defbool_val(info->claim_mode); if (info->u.hvm.mmio_hole_memkb) { uint64_t max_ram_below_4g = (1ULL << 32) - (info->u.hvm.mmio_hole_memkb << 10); if (max_ram_below_4g < HVM_BELOW_4G_MMIO_START) - args.mmio_size = info->u.hvm.mmio_hole_memkb << 10; + dom->mmio_size = info->u.hvm.mmio_hole_memkb << 10; } - rc = libxl__domain_firmware(gc, info, &args); + rc = libxl__domain_firmware(gc, info, dom); if (rc != 0) { LOG(ERROR, "initializing domain firmware failed"); goto out; } - if (args.mem_target == 0) - args.mem_target = args.mem_size; - if (args.mmio_size == 0) - args.mmio_size = HVM_BELOW_4G_MMIO_LENGTH; - lowmem_end = args.mem_size; + + if (dom->target_pages == 0) + dom->target_pages = mem_size >> XC_PAGE_SHIFT; + if (dom->mmio_size == 0) + dom->mmio_size = HVM_BELOW_4G_MMIO_LENGTH; + lowmem_end = mem_size; highmem_end = 0; - mmio_start = (1ull << 32) - args.mmio_size; + mmio_start = (1ull << 32) - dom->mmio_size; if (lowmem_end > mmio_start) { highmem_end = (1ull << 32) + (lowmem_end - mmio_start); lowmem_end = mmio_start; } - args.lowmem_end = lowmem_end; - args.highmem_end = highmem_end; - args.mmio_start = mmio_start; + dom->lowmem_end = lowmem_end; + dom->highmem_end = highmem_end; + dom->mmio_start = mmio_start; rc = libxl__domain_device_construct_rdm(gc, d_config, info->u.hvm.rdm_mem_boundary_memkb*1024, - &args); + dom); if (rc) { LOG(ERROR, "checking reserved device memory failed"); goto out; @@ -967,7 +1001,7 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, if (info->num_vnuma_nodes != 0) { int i; - rc = libxl__vnuma_build_vmemrange_hvm(gc, domid, info, state, &args); + rc = libxl__vnuma_build_vmemrange_hvm(gc, domid, info, state, dom); if (rc != 0) { LOG(ERROR, "hvm build vmemranges failed"); goto out; @@ -977,37 +1011,34 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, rc = set_vnuma_info(gc, domid, info, state); if (rc != 0) goto out; - args.nr_vmemranges = state->num_vmemranges; - args.vmemranges = libxl__malloc(gc, sizeof(*args.vmemranges) * - args.nr_vmemranges); + dom->nr_vmemranges = state->num_vmemranges; + dom->vmemranges = libxl__malloc(gc, sizeof(*dom->vmemranges) * + dom->nr_vmemranges); - for (i = 0; i < args.nr_vmemranges; i++) { - args.vmemranges[i].start = state->vmemranges[i].start; - args.vmemranges[i].end = state->vmemranges[i].end; - args.vmemranges[i].flags = state->vmemranges[i].flags; - args.vmemranges[i].nid = state->vmemranges[i].nid; + for (i = 0; i < dom->nr_vmemranges; i++) { + dom->vmemranges[i].start = state->vmemranges[i].start; + dom->vmemranges[i].end = state->vmemranges[i].end; + dom->vmemranges[i].flags = state->vmemranges[i].flags; + dom->vmemranges[i].nid = state->vmemranges[i].nid; } - args.nr_vnodes = info->num_vnuma_nodes; - args.vnode_to_pnode = libxl__malloc(gc, sizeof(*args.vnode_to_pnode) * - args.nr_vnodes); - for (i = 0; i < args.nr_vnodes; i++) - args.vnode_to_pnode[i] = info->vnuma_nodes[i].pnode; - } - - ret = xc_hvm_build(ctx->xch, domid, &args); - if (ret) { - LOGEV(ERROR, ret, "hvm building failed"); - rc = ERROR_FAIL; - goto out; + dom->nr_vnodes = info->num_vnuma_nodes; + dom->vnode_to_pnode = libxl__malloc(gc, sizeof(*dom->vnode_to_pnode) * + dom->nr_vnodes); + for (i = 0; i < dom->nr_vnodes; i++) + dom->vnode_to_pnode[i] = info->vnuma_nodes[i].pnode; } - rc = libxl__arch_domain_construct_memmap(gc, d_config, domid, &args); + rc = libxl__arch_domain_construct_memmap(gc, d_config, domid, dom); if (rc != 0) { LOG(ERROR, "setting domain memory map failed"); goto out; } + rc = libxl__build_dom(gc, domid, info, state, dom); + if (rc != 0) + goto out; + rc = hvm_build_set_params(ctx->xch, domid, info, state->store_port, &state->store_mfn, state->console_port, &state->console_mfn, state->store_domid, @@ -1017,15 +1048,18 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid, goto out; } - rc = hvm_build_set_xs_values(gc, domid, &args); + rc = hvm_build_set_xs_values(gc, domid, dom); if (rc != 0) { LOG(ERROR, "hvm build set xenstore values failed"); goto out; } + xc_dom_release(dom); return 0; + out: assert(rc != 0); + if (dom != NULL) xc_dom_release(dom); return rc; } diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index c2413c2..c5df398 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1609,7 +1609,7 @@ _hidden int libxl__need_xenpv_qemu(libxl__gc *gc, _hidden int libxl__domain_device_construct_rdm(libxl__gc *gc, libxl_domain_config *d_config, uint64_t rdm_mem_guard, - struct xc_hvm_build_args *args); + struct xc_dom_image *dom); /* * This function will cause the whole libxl process to hang @@ -3772,7 +3772,7 @@ int libxl__vnuma_build_vmemrange_hvm(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *b_info, libxl__domain_build_state *state, - struct xc_hvm_build_args *args); + struct xc_dom_image *dom); bool libxl__vnuma_configured(const libxl_domain_build_info *b_info); _hidden int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid, diff --git a/tools/libxl/libxl_vnuma.c b/tools/libxl/libxl_vnuma.c index 56856d2..db22799 100644 --- a/tools/libxl/libxl_vnuma.c +++ b/tools/libxl/libxl_vnuma.c @@ -17,6 +17,8 @@ #include "libxl_arch.h" #include <stdlib.h> +#include <xc_dom.h> + bool libxl__vnuma_configured(const libxl_domain_build_info *b_info) { return b_info->num_vnuma_nodes != 0; @@ -252,7 +254,7 @@ int libxl__vnuma_build_vmemrange_hvm(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *b_info, libxl__domain_build_state *state, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { uint64_t hole_start, hole_end, next; int nid, nr_vmemrange; @@ -264,10 +266,10 @@ int libxl__vnuma_build_vmemrange_hvm(libxl__gc *gc, * Guest physical address space layout: * [0, hole_start) [hole_start, hole_end) [hole_end, highmem_end) */ - hole_start = args->lowmem_end < args->mmio_start ? - args->lowmem_end : args->mmio_start; - hole_end = (args->mmio_start + args->mmio_size) > (1ULL << 32) ? - (args->mmio_start + args->mmio_size) : (1ULL << 32); + hole_start = dom->lowmem_end < dom->mmio_start ? + dom->lowmem_end : dom->mmio_start; + hole_end = (dom->mmio_start + dom->mmio_size) > (1ULL << 32) ? + (dom->mmio_start + dom->mmio_size) : (1ULL << 32); assert(state->vmemranges == NULL); diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c index 896f34c..9276126 100644 --- a/tools/libxl/libxl_x86.c +++ b/tools/libxl/libxl_x86.c @@ -1,6 +1,8 @@ #include "libxl_internal.h" #include "libxl_arch.h" +#include <xc_dom.h> + int libxl__arch_domain_prepare_config(libxl__gc *gc, libxl_domain_config *d_config, xc_domain_configuration_t *xc_config) @@ -473,7 +475,7 @@ int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq) int libxl__arch_domain_construct_memmap(libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid, - struct xc_hvm_build_args *args) + struct xc_dom_image *dom) { int rc = 0; unsigned int nr = 0, i; @@ -481,7 +483,7 @@ int libxl__arch_domain_construct_memmap(libxl__gc *gc, unsigned int e820_entries = 1; struct e820entry *e820 = NULL; uint64_t highmem_size = - args->highmem_end ? args->highmem_end - (1ull << 32) : 0; + dom->highmem_end ? dom->highmem_end - (1ull << 32) : 0; /* Add all rdm entries. */ for (i = 0; i < d_config->num_rdms; i++) @@ -503,7 +505,7 @@ int libxl__arch_domain_construct_memmap(libxl__gc *gc, /* Low memory */ e820[nr].addr = GUEST_LOW_MEM_START_DEFAULT; - e820[nr].size = args->lowmem_end - GUEST_LOW_MEM_START_DEFAULT; + e820[nr].size = dom->lowmem_end - GUEST_LOW_MEM_START_DEFAULT; e820[nr].type = E820_RAM; nr++; -- 1.9.5 (Apple Git-50.3) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |