[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 7/7] libxl: Introduce libxl__arch_domain_create
Introduce an arch specific internal domain creation function. At the moment only x86 provides an implementation. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- tools/libxl/Makefile | 6 +- tools/libxl/libxl_arch.h | 22 ++++ tools/libxl/libxl_create.c | 12 +-- tools/libxl/libxl_noarch.c | 8 ++ tools/libxl/libxl_pci.c | 242 ----------------------------------------- tools/libxl/libxl_x86.c | 258 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 293 insertions(+), 255 deletions(-) create mode 100644 tools/libxl/libxl_arch.h create mode 100644 tools/libxl/libxl_noarch.c create mode 100644 tools/libxl/libxl_x86.c diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index 41b6ac4..ba5852b 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -34,9 +34,9 @@ LIBXL_OBJS-y += libxl_blktap2.o else LIBXL_OBJS-y += libxl_noblktap2.o endif -LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o -LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o -LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o +LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o +LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o libxl_noarch.o +LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_noarch.o ifeq ($(CONFIG_NetBSD),y) LIBXL_OBJS-y += libxl_netbsd.o diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h new file mode 100644 index 0000000..d1bbdf7 --- /dev/null +++ b/tools/libxl/libxl_arch.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Citrix Ltd. + * + * 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. + */ + +#ifndef LIBXL_ARCH_H +#define LIBXL_ARCH_H + +/* arch specific internal domain creation function */ +int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, + uint32_t domid); + +#endif diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index f28d814..ff589a8 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -18,6 +18,7 @@ #include "libxl_osdeps.h" /* must come before any other headers */ #include "libxl_internal.h" +#include "libxl_arch.h" #include <xc_dom.h> #include <xenguest.h> @@ -616,16 +617,7 @@ static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config, goto error_out; } } - - if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && - d_config->b_info.u.pv.e820_host) { - int rc; - rc = libxl__e820_alloc(gc, domid, d_config); - if (rc) - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, - "Failed while collecting E820 with: %d (errno:%d)\n", - rc, errno); - } + libxl__arch_domain_create(gc, d_config, domid); if ( cb && (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM || (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && d_config->b_info.u.pv.bootloader ))) { diff --git a/tools/libxl/libxl_noarch.c b/tools/libxl/libxl_noarch.c new file mode 100644 index 0000000..7893535 --- /dev/null +++ b/tools/libxl/libxl_noarch.c @@ -0,0 +1,8 @@ +#include "libxl_internal.h" +#include "libxl_arch.h" + +int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, + uint32_t domid) +{ + return 0; +} diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c index 33425f5..d960f4b 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -1147,248 +1147,6 @@ int libxl__device_pci_destroy_all(libxl__gc *gc, uint32_t domid) return 0; } -static const char *e820_names(int type) -{ - switch (type) { - case E820_RAM: return "RAM"; - case E820_RESERVED: return "Reserved"; - case E820_ACPI: return "ACPI"; - case E820_NVS: return "ACPI NVS"; - case E820_UNUSABLE: return "Unusable"; - default: break; - } - return "Unknown"; -} - -static int e820_sanitize(libxl_ctx *ctx, struct e820entry src[], - uint32_t *nr_entries, - unsigned long map_limitkb, - unsigned long balloon_kb) -{ - uint64_t delta_kb = 0, start = 0, start_kb = 0, last = 0, ram_end; - uint32_t i, idx = 0, nr; - struct e820entry e820[E820MAX]; - - if (!src || !map_limitkb || !balloon_kb || !nr_entries) - return ERROR_INVAL; - - nr = *nr_entries; - if (!nr) - return ERROR_INVAL; - - if (nr > E820MAX) - return ERROR_NOMEM; - - /* Weed out anything under 1MB */ - for (i = 0; i < nr; i++) { - if (src[i].addr > 0x100000) - continue; - - src[i].type = 0; - src[i].size = 0; - src[i].addr = -1ULL; - } - - /* Find the lowest and highest entry in E820, skipping over - * undesired entries. */ - start = -1ULL; - last = 0; - for (i = 0; i < nr; i++) { - if ((src[i].type == E820_RAM) || - (src[i].type == E820_UNUSABLE) || - (src[i].type == 0)) - continue; - - start = src[i].addr < start ? src[i].addr : start; - last = src[i].addr + src[i].size > last ? - src[i].addr + src[i].size > last : last; - } - if (start > 1024) - start_kb = start >> 10; - - /* Add the memory RAM region for the guest */ - e820[idx].addr = 0; - e820[idx].size = (uint64_t)map_limitkb << 10; - e820[idx].type = E820_RAM; - - /* .. and trim if neccessary */ - if (start_kb && map_limitkb > start_kb) { - delta_kb = map_limitkb - start_kb; - if (delta_kb) - e820[idx].size -= (uint64_t)(delta_kb << 10); - } - /* Note: We don't touch balloon_kb here. Will add it at the end. */ - ram_end = e820[idx].addr + e820[idx].size; - idx ++; - - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Memory: %"PRIu64"kB End of RAM: " \ - "0x%"PRIx64" (PFN) Delta: %"PRIu64"kB, PCI start: %"PRIu64"kB " \ - "(0x%"PRIx64" PFN), Balloon %"PRIu64"kB\n", (uint64_t)map_limitkb, - ram_end >> 12, delta_kb, start_kb ,start >> 12, - (uint64_t)balloon_kb); - - - /* This whole code below is to guard against if the Intel IGD is passed into - * the guest. If we don't pass in IGD, this whole code can be ignored. - * - * The reason for this code is that Intel boxes fill their E820 with - * E820_RAM amongst E820_RESERVED and we can't just ditch those E820_RAM. - * That is b/c any "gaps" in the E820 is considered PCI I/O space by - * Linux and it would be utilized by the Intel IGD as I/O space while - * in reality it was an RAM region. - * - * What this means is that we have to walk the E820 and for any region - * that is RAM and below 4GB and above ram_end, needs to change its type - * to E820_UNUSED. We also need to move some of the E820_RAM regions if - * the overlap with ram_end. */ - for (i = 0; i < nr; i++) { - uint64_t end = src[i].addr + src[i].size; - - /* We don't care about E820_UNUSABLE, but we need to - * change the type to zero b/c the loop after this - * sticks E820_UNUSABLE on the guest's E820 but ignores - * the ones with type zero. */ - if ((src[i].type == E820_UNUSABLE) || - /* Any region that is within the "RAM region" can - * be safely ditched. */ - (end < ram_end)) { - src[i].type = 0; - continue; - } - - /* Look only at RAM regions. */ - if (src[i].type != E820_RAM) - continue; - - /* We only care about RAM regions below 4GB. */ - if (src[i].addr >= (1ULL<<32)) - continue; - - /* E820_RAM overlaps with our RAM region. Move it */ - if (src[i].addr < ram_end) { - uint64_t delta; - - src[i].type = E820_UNUSABLE; - delta = ram_end - src[i].addr; - /* The end < ram_end should weed this out */ - if (src[i].size - delta < 0) - src[i].type = 0; - else { - src[i].size -= delta; - src[i].addr = ram_end; - } - if (src[i].addr + src[i].size != end) { - /* We messed up somewhere */ - src[i].type = 0; - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Computed E820 wrongly. Continuing on."); - } - } - /* Lastly, convert the RAM to UNSUABLE. Look in the Linux kernel - at git commit 2f14ddc3a7146ea4cd5a3d1ecd993f85f2e4f948 - "xen/setup: Inhibit resource API from using System RAM E820 - gaps as PCI mem gaps" for full explanation. */ - if (end > ram_end) - src[i].type = E820_UNUSABLE; - } - - /* Check if there is a region between ram_end and start. */ - if (start > ram_end) { - int add_unusable = 1; - for (i = 0; i < nr && add_unusable; i++) { - if (src[i].type != E820_UNUSABLE) - continue; - if (ram_end != src[i].addr) - continue; - if (start != src[i].addr + src[i].size) { - /* there is one, adjust it */ - src[i].size = start - src[i].addr; - } - add_unusable = 0; - } - /* .. and if not present, add it in. This is to guard against - the Linux guest assuming that the gap between the end of - RAM region and the start of the E820_[ACPI,NVS,RESERVED] - is PCI I/O space. Which it certainly is _not_. */ - if (add_unusable) { - e820[idx].type = E820_UNUSABLE; - e820[idx].addr = ram_end; - e820[idx].size = start - ram_end; - idx++; - } - } - /* Almost done: copy them over, ignoring the undesireable ones */ - for (i = 0; i < nr; i++) { - if ((src[i].type == E820_RAM) || - (src[i].type == 0)) - continue; - - e820[idx].type = src[i].type; - e820[idx].addr = src[i].addr; - e820[idx].size = src[i].size; - idx++; - } - /* At this point we have the mapped RAM + E820 entries from src. */ - if (balloon_kb) { - /* and if we truncated the RAM region, then add it to the end. */ - e820[idx].type = E820_RAM; - e820[idx].addr = (uint64_t)(1ULL << 32) > last ? - (uint64_t)(1ULL << 32) : last; - /* also add the balloon memory to the end. */ - e820[idx].size = (uint64_t)(delta_kb << 10) + - (uint64_t)(balloon_kb << 10); - idx++; - - } - nr = idx; - - for (i = 0; i < nr; i++) { - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, ":\t[%"PRIx64" -> %"PRIx64"] %s", - e820[i].addr >> 12, (e820[i].addr + e820[i].size) >> 12, - e820_names(e820[i].type)); - } - - /* Done: copy the sanitized version. */ - *nr_entries = nr; - memcpy(src, e820, nr * sizeof(struct e820entry)); - return 0; -} - -int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config) -{ - libxl_ctx *ctx = libxl__gc_owner(gc); - int rc; - uint32_t nr; - struct e820entry map[E820MAX]; - libxl_domain_build_info *b_info; - - if (d_config == NULL || d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) - return ERROR_INVAL; - - b_info = &d_config->b_info; - if (!b_info->u.pv.e820_host) - return ERROR_INVAL; - - rc = xc_get_machine_memory_map(ctx->xch, map, E820MAX); - if (rc < 0) { - errno = rc; - return ERROR_FAIL; - } - nr = rc; - rc = e820_sanitize(ctx, map, &nr, b_info->target_memkb, - (b_info->max_memkb - b_info->target_memkb) + - b_info->u.pv.slack_memkb); - if (rc) - return ERROR_FAIL; - - rc = xc_domain_set_memory_map(ctx->xch, domid, map, nr); - - if (rc < 0) { - errno = rc; - return ERROR_FAIL; - } - return 0; -} - /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c new file mode 100644 index 0000000..dd8eef9 --- /dev/null +++ b/tools/libxl/libxl_x86.c @@ -0,0 +1,258 @@ +#include "libxl_arch.h" +#include "libxl_internal.h" + +static const char *e820_names(int type) +{ + switch (type) { + case E820_RAM: return "RAM"; + case E820_RESERVED: return "Reserved"; + case E820_ACPI: return "ACPI"; + case E820_NVS: return "ACPI NVS"; + case E820_UNUSABLE: return "Unusable"; + default: break; + } + return "Unknown"; +} + +static int e820_sanitize(libxl_ctx *ctx, struct e820entry src[], + uint32_t *nr_entries, + unsigned long map_limitkb, + unsigned long balloon_kb) +{ + uint64_t delta_kb = 0, start = 0, start_kb = 0, last = 0, ram_end; + uint32_t i, idx = 0, nr; + struct e820entry e820[E820MAX]; + + if (!src || !map_limitkb || !balloon_kb || !nr_entries) + return ERROR_INVAL; + + nr = *nr_entries; + if (!nr) + return ERROR_INVAL; + + if (nr > E820MAX) + return ERROR_NOMEM; + + /* Weed out anything under 1MB */ + for (i = 0; i < nr; i++) { + if (src[i].addr > 0x100000) + continue; + + src[i].type = 0; + src[i].size = 0; + src[i].addr = -1ULL; + } + + /* Find the lowest and highest entry in E820, skipping over + * undesired entries. */ + start = -1ULL; + last = 0; + for (i = 0; i < nr; i++) { + if ((src[i].type == E820_RAM) || + (src[i].type == E820_UNUSABLE) || + (src[i].type == 0)) + continue; + + start = src[i].addr < start ? src[i].addr : start; + last = src[i].addr + src[i].size > last ? + src[i].addr + src[i].size > last : last; + } + if (start > 1024) + start_kb = start >> 10; + + /* Add the memory RAM region for the guest */ + e820[idx].addr = 0; + e820[idx].size = (uint64_t)map_limitkb << 10; + e820[idx].type = E820_RAM; + + /* .. and trim if neccessary */ + if (start_kb && map_limitkb > start_kb) { + delta_kb = map_limitkb - start_kb; + if (delta_kb) + e820[idx].size -= (uint64_t)(delta_kb << 10); + } + /* Note: We don't touch balloon_kb here. Will add it at the end. */ + ram_end = e820[idx].addr + e820[idx].size; + idx ++; + + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Memory: %"PRIu64"kB End of RAM: " \ + "0x%"PRIx64" (PFN) Delta: %"PRIu64"kB, PCI start: %"PRIu64"kB " \ + "(0x%"PRIx64" PFN), Balloon %"PRIu64"kB\n", (uint64_t)map_limitkb, + ram_end >> 12, delta_kb, start_kb ,start >> 12, + (uint64_t)balloon_kb); + + + /* This whole code below is to guard against if the Intel IGD is passed into + * the guest. If we don't pass in IGD, this whole code can be ignored. + * + * The reason for this code is that Intel boxes fill their E820 with + * E820_RAM amongst E820_RESERVED and we can't just ditch those E820_RAM. + * That is b/c any "gaps" in the E820 is considered PCI I/O space by + * Linux and it would be utilized by the Intel IGD as I/O space while + * in reality it was an RAM region. + * + * What this means is that we have to walk the E820 and for any region + * that is RAM and below 4GB and above ram_end, needs to change its type + * to E820_UNUSED. We also need to move some of the E820_RAM regions if + * the overlap with ram_end. */ + for (i = 0; i < nr; i++) { + uint64_t end = src[i].addr + src[i].size; + + /* We don't care about E820_UNUSABLE, but we need to + * change the type to zero b/c the loop after this + * sticks E820_UNUSABLE on the guest's E820 but ignores + * the ones with type zero. */ + if ((src[i].type == E820_UNUSABLE) || + /* Any region that is within the "RAM region" can + * be safely ditched. */ + (end < ram_end)) { + src[i].type = 0; + continue; + } + + /* Look only at RAM regions. */ + if (src[i].type != E820_RAM) + continue; + + /* We only care about RAM regions below 4GB. */ + if (src[i].addr >= (1ULL<<32)) + continue; + + /* E820_RAM overlaps with our RAM region. Move it */ + if (src[i].addr < ram_end) { + uint64_t delta; + + src[i].type = E820_UNUSABLE; + delta = ram_end - src[i].addr; + /* The end < ram_end should weed this out */ + if (src[i].size - delta < 0) + src[i].type = 0; + else { + src[i].size -= delta; + src[i].addr = ram_end; + } + if (src[i].addr + src[i].size != end) { + /* We messed up somewhere */ + src[i].type = 0; + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Computed E820 wrongly. Continuing on."); + } + } + /* Lastly, convert the RAM to UNSUABLE. Look in the Linux kernel + at git commit 2f14ddc3a7146ea4cd5a3d1ecd993f85f2e4f948 + "xen/setup: Inhibit resource API from using System RAM E820 + gaps as PCI mem gaps" for full explanation. */ + if (end > ram_end) + src[i].type = E820_UNUSABLE; + } + + /* Check if there is a region between ram_end and start. */ + if (start > ram_end) { + int add_unusable = 1; + for (i = 0; i < nr && add_unusable; i++) { + if (src[i].type != E820_UNUSABLE) + continue; + if (ram_end != src[i].addr) + continue; + if (start != src[i].addr + src[i].size) { + /* there is one, adjust it */ + src[i].size = start - src[i].addr; + } + add_unusable = 0; + } + /* .. and if not present, add it in. This is to guard against + the Linux guest assuming that the gap between the end of + RAM region and the start of the E820_[ACPI,NVS,RESERVED] + is PCI I/O space. Which it certainly is _not_. */ + if (add_unusable) { + e820[idx].type = E820_UNUSABLE; + e820[idx].addr = ram_end; + e820[idx].size = start - ram_end; + idx++; + } + } + /* Almost done: copy them over, ignoring the undesireable ones */ + for (i = 0; i < nr; i++) { + if ((src[i].type == E820_RAM) || + (src[i].type == 0)) + continue; + + e820[idx].type = src[i].type; + e820[idx].addr = src[i].addr; + e820[idx].size = src[i].size; + idx++; + } + /* At this point we have the mapped RAM + E820 entries from src. */ + if (balloon_kb) { + /* and if we truncated the RAM region, then add it to the end. */ + e820[idx].type = E820_RAM; + e820[idx].addr = (uint64_t)(1ULL << 32) > last ? + (uint64_t)(1ULL << 32) : last; + /* also add the balloon memory to the end. */ + e820[idx].size = (uint64_t)(delta_kb << 10) + + (uint64_t)(balloon_kb << 10); + idx++; + + } + nr = idx; + + for (i = 0; i < nr; i++) { + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, ":\t[%"PRIx64" -> %"PRIx64"] %s", + e820[i].addr >> 12, (e820[i].addr + e820[i].size) >> 12, + e820_names(e820[i].type)); + } + + /* Done: copy the sanitized version. */ + *nr_entries = nr; + memcpy(src, e820, nr * sizeof(struct e820entry)); + return 0; +} + +static int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + int rc; + uint32_t nr; + struct e820entry map[E820MAX]; + libxl_domain_build_info *b_info; + + if (d_config == NULL || d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) + return ERROR_INVAL; + + b_info = &d_config->b_info; + if (!b_info->u.pv.e820_host) + return ERROR_INVAL; + + rc = xc_get_machine_memory_map(ctx->xch, map, E820MAX); + if (rc < 0) { + errno = rc; + return ERROR_FAIL; + } + nr = rc; + rc = e820_sanitize(ctx, map, &nr, b_info->target_memkb, + (b_info->max_memkb - b_info->target_memkb) + + b_info->u.pv.slack_memkb); + if (rc) + return ERROR_FAIL; + + rc = xc_domain_set_memory_map(ctx->xch, domid, map, nr); + + if (rc < 0) { + errno = rc; + return ERROR_FAIL; + } + return 0; +} + +int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, + uint32_t domid) +{ + if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && + d_config->b_info.u.pv.e820_host) { + int rc; + rc = libxl__e820_alloc(gc, domid, d_config); + if (rc) + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, + "Failed while collecting E820 with: %d (errno:%d)\n", + rc, errno); + } +} -- 1.7.8.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |