From: Wei Liu Date: Mon, 16 Mar 2015 09:52:28 +0000 (+0000) Subject: libxl: functions to build vmemranges for PV guest X-Git-Tag: 4.6.0-rc1~956 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=6525cd308d5c457c49cdd72af20da9f1912e0e24;p=xen.git libxl: functions to build vmemranges for PV guest Introduce a arch-independent routine to generate one vmemrange per vnode. Also introduce arch-dependent routines for different architectures because part of the process is arch-specific -- ARM has yet have NUMA support and E820 is x86 only. For those x86 guests who care about machine E820 map (i.e. with e820_host=1), vnode is further split into several vmemranges to accommodate memory holes. A few stubs for libxl_arm.c are created. Signed-off-by: Wei Liu Reviewed-by: Dario Faggioli Cc: Ian Campbell Cc: Ian Jackson Cc: Dario Faggioli Cc: Elena Ufimtseva Acked-by: Ian Campbell --- diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h index d3bc1369ec..e2490487c2 100644 --- a/tools/libxl/libxl_arch.h +++ b/tools/libxl/libxl_arch.h @@ -27,4 +27,10 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc, int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, libxl_domain_build_info *info, struct xc_dom_image *dom); + +/* build vNUMA vmemrange with arch specific information */ +int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state); #endif diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 65a762b7e4..7da254fc06 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -707,6 +707,14 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, return 0; } +int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *info, + libxl__domain_build_state *state) +{ + return libxl__vnuma_build_vmemrange_pv_generic(gc, domid, info, state); +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 52c823917c..4a2f9ed851 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -3421,6 +3421,14 @@ void libxl__numa_candidate_put_nodemap(libxl__gc *gc, int libxl__vnuma_config_check(libxl__gc *gc, const libxl_domain_build_info *b_info, const libxl__domain_build_state *state); +int libxl__vnuma_build_vmemrange_pv_generic(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state); +int libxl__vnuma_build_vmemrange_pv(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state); _hidden int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid, const libxl_ms_vm_genid *id); diff --git a/tools/libxl/libxl_vnuma.c b/tools/libxl/libxl_vnuma.c index 89532ef76c..bef3cc548e 100644 --- a/tools/libxl/libxl_vnuma.c +++ b/tools/libxl/libxl_vnuma.c @@ -14,6 +14,7 @@ */ #include "libxl_osdeps.h" /* must come before any other headers */ #include "libxl_internal.h" +#include "libxl_arch.h" #include /* Sort vmemranges in ascending order with "start" */ @@ -142,6 +143,45 @@ out: return rc; } +int libxl__vnuma_build_vmemrange_pv_generic(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state) +{ + int i; + uint64_t next; + xen_vmemrange_t *v = NULL; + + /* Generate one vmemrange for each virtual node. */ + GCREALLOC_ARRAY(v, b_info->num_vnuma_nodes); + next = 0; + for (i = 0; i < b_info->num_vnuma_nodes; i++) { + libxl_vnode_info *p = &b_info->vnuma_nodes[i]; + + v[i].start = next; + v[i].end = next + (p->memkb << 10); + v[i].flags = 0; + v[i].nid = i; + + next = v[i].end; + } + + state->vmemranges = v; + state->num_vmemranges = i; + + return 0; +} + +/* Build vmemranges for PV guest */ +int libxl__vnuma_build_vmemrange_pv(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state) +{ + assert(state->vmemranges == NULL); + return libxl__arch_vnuma_build_vmemrange(gc, domid, b_info, state); +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c index d012b4ddae..fd45ead2d6 100644 --- a/tools/libxl/libxl_x86.c +++ b/tools/libxl/libxl_x86.c @@ -339,6 +339,84 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, return 0; } +/* Return 0 on success, ERROR_* on failure. */ +int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc, + uint32_t domid, + libxl_domain_build_info *b_info, + libxl__domain_build_state *state) +{ + int nid, nr_vmemrange, rc; + uint32_t nr_e820, e820_count; + struct e820entry map[E820MAX]; + xen_vmemrange_t *vmemranges; + unsigned int array_size; + + /* If e820_host is not set, call the generic function */ + if (!(b_info->type == LIBXL_DOMAIN_TYPE_PV && + libxl_defbool_val(b_info->u.pv.e820_host))) + return libxl__vnuma_build_vmemrange_pv_generic(gc, domid, b_info, + state); + + assert(state->vmemranges == NULL); + + nr_e820 = E820MAX; + rc = e820_host_sanitize(gc, b_info, map, &nr_e820); + if (rc) goto out; + + e820_count = 0; + nr_vmemrange = 0; + vmemranges = NULL; + array_size = 0; + for (nid = 0; nid < b_info->num_vnuma_nodes; nid++) { + libxl_vnode_info *p = &b_info->vnuma_nodes[nid]; + uint64_t remaining_bytes = (p->memkb << 10), bytes; + + while (remaining_bytes > 0) { + if (e820_count >= nr_e820) { + rc = ERROR_NOMEM; + goto out; + } + + /* Skip non RAM region */ + if (map[e820_count].type != E820_RAM) { + e820_count++; + continue; + } + + if (nr_vmemrange >= array_size) { + array_size += 32; + GCREALLOC_ARRAY(vmemranges, array_size); + } + + bytes = map[e820_count].size >= remaining_bytes ? + remaining_bytes : map[e820_count].size; + + vmemranges[nr_vmemrange].start = map[e820_count].addr; + vmemranges[nr_vmemrange].end = map[e820_count].addr + bytes; + + if (map[e820_count].size >= remaining_bytes) { + map[e820_count].addr += bytes; + map[e820_count].size -= bytes; + } else { + e820_count++; + } + + remaining_bytes -= bytes; + + vmemranges[nr_vmemrange].flags = 0; + vmemranges[nr_vmemrange].nid = nid; + nr_vmemrange++; + } + } + + state->vmemranges = vmemranges; + state->num_vmemranges = nr_vmemrange; + + rc = 0; +out: + return rc; +} + /* * Local variables: * mode: C