>From libxc's point of view, it only needs to know vnode to pnode mapping and size of each vnode to allocate memory accordingly. Add these fields to xc_dom structure.
The caller might not pass in vNUMA information. In that case, a dummy layout is generated for the convenience of libxc's allocation code. The upper layer (libxl etc) still sees the domain has no vNUMA configuration. Signed-off-by: Wei Liu <wei.l...@citrix.com> Cc: Ian Campbell <ian.campb...@citrix.com> Cc: Ian Jackson <ian.jack...@eu.citrix.com> Cc: Dario Faggioli <dario.faggi...@citrix.com> Cc: Elena Ufimtseva <ufimts...@gmail.com> --- Changes in v4: 1. Pack fields into a struct. 2. Use "page" as unit. 3. __FUNCTION__ -> __func__. 4. Don't print total_pages. 5. Improve comment. Changes in v3: 1. Rewrite commit log. 2. Shorten some error messages. --- tools/libxc/include/xc_dom.h | 6 +++ tools/libxc/include/xenguest.h | 6 +++ tools/libxc/xc_dom_x86.c | 85 ++++++++++++++++++++++++++++++++++------ tools/libxc/xc_private.h | 2 + 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h index 07d7224..dba2e27 100644 --- a/tools/libxc/include/xc_dom.h +++ b/tools/libxc/include/xc_dom.h @@ -50,6 +50,8 @@ struct xc_dom_phys { xen_pfn_t count; }; +struct xc_vnuma_info; + struct xc_dom_image { /* files */ void *kernel_blob; @@ -167,6 +169,10 @@ struct xc_dom_image { struct xc_dom_loader *kernel_loader; void *private_loader; + /* vNUMA information */ + struct xc_vnuma_info *vnuma_info; + unsigned int nr_vnuma_info; + /* kernel loader */ struct xc_dom_arch *arch_hooks; /* allocate up to virt_alloc_end */ diff --git a/tools/libxc/include/xenguest.h b/tools/libxc/include/xenguest.h index 40bbac8..9b7edff 100644 --- a/tools/libxc/include/xenguest.h +++ b/tools/libxc/include/xenguest.h @@ -217,6 +217,12 @@ struct xc_hvm_firmware_module { uint64_t guest_addr_out; }; +struct xc_vnuma_info { + unsigned int vnode; + unsigned int pnode; + uint64_t pages; +}; + struct xc_hvm_build_args { uint64_t mem_size; /* Memory size in bytes. */ uint64_t mem_target; /* Memory target in bytes. */ diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index bf06fe4..6b42187 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -759,7 +759,8 @@ static int x86_shadow(xc_interface *xch, domid_t domid) int arch_setup_meminit(struct xc_dom_image *dom) { int rc; - xen_pfn_t pfn, allocsz, i, j, mfn; + xen_pfn_t pfn, allocsz, mfn, total, pfn_base; + int i, j; rc = x86_compat(dom->xch, dom->guest_domid, dom->guest_type); if ( rc ) @@ -811,18 +812,80 @@ int arch_setup_meminit(struct xc_dom_image *dom) /* setup initial p2m */ for ( pfn = 0; pfn < dom->total_pages; pfn++ ) dom->p2m_host[pfn] = pfn; - + + /* Setup dummy vNUMA information if it's not provided. Note + * that this is a valid state if libxl doesn't provide any + * vNUMA information. + * + * The dummy values make libxc allocate all pages from + * arbitrary physical. This is the expected behaviour if no + * vNUMA configuration is provided to libxc. + * + * Note that the following hunk is just for the convenience of + * allocation code. No defaulting is happening in libxc. + */ + if ( dom->nr_vnuma_info == 0 ) + { + dom->nr_vnuma_info = 1; + dom->vnuma_info = xc_dom_malloc(dom, sizeof(*dom->vnuma_info)); + dom->vnuma_info[0].vnode = 0; + dom->vnuma_info[0].pnode = XC_VNUMA_NO_NODE; + dom->vnuma_info[0].pages = dom->total_pages; + } + + total = 0; + for ( i = 0; i < dom->nr_vnuma_info; i++ ) + total += dom->vnuma_info[i].pages; + if ( total != dom->total_pages ) + { + xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, + "%s: vNUMA page count mismatch (0x%"PRIpfn" != 0x%"PRIpfn")\n", + __func__, total, dom->total_pages); + return -EINVAL; + } + /* allocate guest memory */ - for ( i = rc = allocsz = 0; - (i < dom->total_pages) && !rc; - i += allocsz ) + pfn_base = 0; + for ( i = 0; i < dom->nr_vnuma_info; i++ ) { - allocsz = dom->total_pages - i; - if ( allocsz > 1024*1024 ) - allocsz = 1024*1024; - rc = xc_domain_populate_physmap_exact( - dom->xch, dom->guest_domid, allocsz, - 0, 0, &dom->p2m_host[i]); + unsigned int memflags; + uint64_t pages; + + memflags = 0; + if ( dom->vnuma_info[i].pnode != XC_VNUMA_NO_NODE ) + { + memflags |= XENMEMF_exact_node(dom->vnuma_info[i].pnode); + memflags |= XENMEMF_exact_node_request; + } + + pages = dom->vnuma_info[i].pages; + + for ( j = 0; j < pages; j += allocsz ) + { + allocsz = pages - j; + if ( allocsz > 1024*1024 ) + allocsz = 1024*1024; + + rc = xc_domain_populate_physmap_exact(dom->xch, + dom->guest_domid, allocsz, 0, memflags, + &dom->p2m_host[pfn_base+j]); + + if ( rc ) + { + if ( dom->vnuma_info[i].pnode != XC_VNUMA_NO_NODE ) + xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, + "%s: failed to allocate 0x%"PRIx64" pages (v=%d, p=%d)\n", + __func__, pages, i, + dom->vnuma_info[i].pnode); + else + xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, + "%s: failed to allocate 0x%"PRIx64" pages\n", + __func__, pages); + return rc; + } + } + + pfn_base += pages; } /* Ensure no unclaimed pages are left unused. diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 45b8644..1809674 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -35,6 +35,8 @@ #include <xen/sys/privcmd.h> +#define XC_VNUMA_NO_NODE (~0U) + #if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG) && !defined(__MINIOS__) /* Compile in Valgrind client requests? */ #include <valgrind/memcheck.h> -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel