Hi all, this patch series allows tools/ to compile on ARM, mostly providing an empty implementation for all the arch specific functions that are needed. Changes in v6: - rebase on 33659563f589 (this is a mercurial id). Changes in v5: - libxc: return -1 and set errno on error; - add few missing emacs runes in new files. Changes in v4: - rebased on 55a36564fb4f85722c67f16fe508f3ecbd204549; - minor compile fixes. Changes in v3: - move libxl_cpuid_policy_list_gen_json to libxl_(no)cpuid.c; - rename xc_hvm_build.c to xc_hvm_build_x86.c; - remove xc_nohvm, introduce xc_hvm_build_arm.c instead; - remove "libxl: do not allocate e820 for non x86 guests."; - introduce libxl__arch_domain_create. Changes in v2: - rebased on a22587ae517170a7755d3a88611ae0e2d5bb555e; - dropped "arm: arch_dump_shared_mem_info as a no-op" that is already in xen-unstable; - define xen_callback_t as uint64_t; - define guest_word_t as uint64_t. Stefano Stabellini (5): arm: compile libxenguest arm: compile memshr arm: compile xentrace arm: compile libxl libxl: Introduce libxl__arch_domain_create tools/libxc/Makefile | 12 +- tools/libxc/xc_dom_arm.c | 50 +++++ tools/libxc/xc_hvm_build.c | 463 ---------------------------------------- tools/libxc/xc_hvm_build_arm.c | 61 ++++++ tools/libxc/xc_hvm_build_x86.c | 463 ++++++++++++++++++++++++++++++++++++++++ tools/libxc/xc_nomigrate.c | 53 +++++ tools/libxl/Makefile | 5 +- tools/libxl/libxl_arch.h | 22 ++ tools/libxl/libxl_cpuid.c | 60 +++++ tools/libxl/libxl_create.c | 11 +- tools/libxl/libxl_internal.h | 2 - tools/libxl/libxl_json.c | 60 ----- tools/libxl/libxl_noarch.c | 8 + tools/libxl/libxl_nocpuid.c | 8 +- tools/libxl/libxl_pci.c | 242 --------------------- tools/libxl/libxl_x86.c | 259 ++++++++++++++++++++++ tools/memshr/bidir-hash.c | 31 +++ tools/xentrace/xenctx.c | 12 + 18 files changed, 1040 insertions(+), 782 deletions(-) Cheers, Stefano
Introduce an empty implementation of the arch specific ARM functions in xc_dom_arm.c. Provide empty implementations of xc_domain_save and xc_domain_restore when CONFIG_MIGRATE is not set. Move xc_hvm_build.c to xc_hvm_build_x86.c because the implementation is x86 specific, introduce xc_hvm_build_arm.c with empty stubs. Changes in v3: - rename xc_hvm_build.c to xc_hvm_build_x86.c; - remove xc_nohvm, introduce xc_hvm_build_arm.c instead; Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com> --- tools/libxc/Makefile | 12 +- tools/libxc/xc_dom_arm.c | 50 +++++ tools/libxc/xc_hvm_build.c | 463 ---------------------------------------- tools/libxc/xc_hvm_build_arm.c | 61 ++++++ tools/libxc/xc_hvm_build_x86.c | 463 ++++++++++++++++++++++++++++++++++++++++ tools/libxc/xc_nomigrate.c | 53 +++++ 6 files changed, 636 insertions(+), 466 deletions(-) create mode 100644 tools/libxc/xc_dom_arm.c delete mode 100644 tools/libxc/xc_hvm_build.c create mode 100644 tools/libxc/xc_hvm_build_arm.c create mode 100644 tools/libxc/xc_hvm_build_x86.c create mode 100644 tools/libxc/xc_nomigrate.c diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index f2e1ba7..02d39a3 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -42,9 +42,12 @@ CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c GUEST_SRCS-y : GUEST_SRCS-y += xg_private.c xc_suspend.c -GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c -GUEST_SRCS-$(CONFIG_MIGRATE) += xc_offline_page.c xc_compression.c -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c +ifeq ($(CONFIG_MIGRATE),y) +GUEST_SRCS-y += xc_domain_restore.c xc_domain_save.c +GUEST_SRCS-y += xc_offline_page.c xc_compression.c +else +GUEST_SRCS-y += xc_nomigrate.c +endif vpath %.c ../../xen/common/libelf CFLAGS += -I../../xen/common/libelf @@ -61,7 +64,10 @@ GUEST_SRCS-y += xc_dom_compat_linux.c GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c GUEST_SRCS-$(CONFIG_X86) += xc_cpuid_x86.c +GUEST_SRCS-$(CONFIG_X86) += xc_hvm_build_x86.c GUEST_SRCS-$(CONFIG_IA64) += xc_dom_ia64.c +GUEST_SRCS-$(CONFIG_ARM) += xc_dom_arm.c +GUEST_SRCS-$(CONFIG_ARM) += xc_hvm_build_arm.c OSDEP_SRCS-y += xenctrl_osdep_ENOSYS.c diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c new file mode 100644 index 0000000..122d0e8 --- /dev/null +++ b/tools/libxc/xc_dom_arm.c @@ -0,0 +1,50 @@ +/* + * Xen domain builder -- ARM + * + * This library 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 of the License. + * + * This library 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Copyright (c) 2011, Citrix Systems + */ +#include <inttypes.h> +#include <xen/xen.h> +#include "xg_private.h" +#include "xc_dom.h" + +int arch_setup_meminit(struct xc_dom_image *dom) +{ + errno = ENOSYS; + return -1; +} + +int arch_setup_bootearly(struct xc_dom_image *dom) +{ + DOMPRINTF("%s: doing nothing", __FUNCTION__); + return 0; +} + +int arch_setup_bootlate(struct xc_dom_image *dom) +{ + DOMPRINTF("%s: doing nothing", __FUNCTION__); + return 0; +} +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c deleted file mode 100644 index 780b23f..0000000 --- a/tools/libxc/xc_hvm_build.c +++ /dev/null @@ -1,463 +0,0 @@ -/****************************************************************************** - * xc_hvm_build.c - * - * This library 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 of the License. - * - * This library 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. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stddef.h> -#include <inttypes.h> -#include <stdlib.h> -#include <unistd.h> -#include <zlib.h> - -#include "xg_private.h" -#include "xc_private.h" - -#include <xen/foreign/x86_32.h> -#include <xen/foreign/x86_64.h> -#include <xen/hvm/hvm_info_table.h> -#include <xen/hvm/params.h> -#include <xen/hvm/e820.h> - -#include <xen/libelf/libelf.h> - -#define SUPERPAGE_2MB_SHIFT 9 -#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT) -#define SUPERPAGE_1GB_SHIFT 18 -#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT) - -#define SPECIALPAGE_BUFIOREQ 0 -#define SPECIALPAGE_XENSTORE 1 -#define SPECIALPAGE_IOREQ 2 -#define SPECIALPAGE_IDENT_PT 3 -#define SPECIALPAGE_CONSOLE 4 -#define NR_SPECIAL_PAGES 5 -#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x)) - -static void build_hvm_info(void *hvm_info_page, uint64_t mem_size, - uint64_t mmio_start, uint64_t mmio_size) -{ - struct hvm_info_table *hvm_info = (struct hvm_info_table *) - (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET); - uint64_t lowmem_end = mem_size, highmem_end = 0; - uint8_t sum; - int i; - - if ( lowmem_end > mmio_start ) - { - highmem_end = (1ull<<32) + (lowmem_end - mmio_start); - lowmem_end = mmio_start; - } - - memset(hvm_info_page, 0, PAGE_SIZE); - - /* Fill in the header. */ - strncpy(hvm_info->signature, "HVM INFO", 8); - hvm_info->length = sizeof(struct hvm_info_table); - - /* Sensible defaults: these can be overridden by the caller. */ - hvm_info->apic_mode = 1; - hvm_info->nr_vcpus = 1; - memset(hvm_info->vcpu_online, 0xff, sizeof(hvm_info->vcpu_online)); - - /* Memory parameters. */ - hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT; - hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT; - hvm_info->reserved_mem_pgstart = special_pfn(0); - - /* Finish with the checksum. */ - for ( i = 0, sum = 0; i < hvm_info->length; i++ ) - sum += ((uint8_t *)hvm_info)[i]; - hvm_info->checksum = -sum; -} - -static int loadelfimage( - xc_interface *xch, - struct elf_binary *elf, uint32_t dom, unsigned long *parray) -{ - privcmd_mmap_entry_t *entries = NULL; - unsigned long pfn_start = elf->pstart >> PAGE_SHIFT; - unsigned long pfn_end = (elf->pend + PAGE_SIZE - 1) >> PAGE_SHIFT; - size_t pages = pfn_end - pfn_start; - int i, rc = -1; - - /* Map address space for initial elf image. */ - entries = calloc(pages, sizeof(privcmd_mmap_entry_t)); - if ( entries == NULL ) - goto err; - - for ( i = 0; i < pages; i++ ) - entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i]; - - elf->dest = xc_map_foreign_ranges( - xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT, - entries, pages); - if ( elf->dest == NULL ) - goto err; - - elf->dest += elf->pstart & (PAGE_SIZE - 1); - - /* Load the initial elf image. */ - rc = elf_load_binary(elf); - if ( rc < 0 ) - PERROR("Failed to load elf binary\n"); - - munmap(elf->dest, pages << PAGE_SHIFT); - elf->dest = NULL; - - err: - free(entries); - - return rc; -} - -/* - * Check whether there exists mmio hole in the specified memory range. - * Returns 1 if exists, else returns 0. - */ -static int check_mmio_hole(uint64_t start, uint64_t memsize, - uint64_t mmio_start, uint64_t mmio_size) -{ - if ( start + memsize <= mmio_start || start >= mmio_start + mmio_size ) - return 0; - else - return 1; -} - -static int setup_guest(xc_interface *xch, - uint32_t dom, const struct xc_hvm_build_args *args, - char *image, unsigned long image_size) -{ - xen_pfn_t *page_array = NULL; - unsigned long i, nr_pages = args->mem_size >> PAGE_SHIFT; - unsigned long target_pages = args->mem_target >> PAGE_SHIFT; - uint64_t mmio_start = (1ull << 32) - args->mmio_size; - uint64_t mmio_size = args->mmio_size; - unsigned long entry_eip, cur_pages, cur_pfn; - void *hvm_info_page; - uint32_t *ident_pt; - struct elf_binary elf; - uint64_t v_start, v_end; - int rc; - xen_capabilities_info_t caps; - unsigned long stat_normal_pages = 0, stat_2mb_pages = 0, - stat_1gb_pages = 0; - int pod_mode = 0; - - if ( nr_pages > target_pages ) - pod_mode = 1; - - memset(&elf, 0, sizeof(elf)); - if ( elf_init(&elf, image, image_size) != 0 ) - goto error_out; - - xc_elf_set_logfile(xch, &elf, 1); - - elf_parse_binary(&elf); - v_start = 0; - v_end = args->mem_size; - - if ( xc_version(xch, XENVER_capabilities, &caps) != 0 ) - { - PERROR("Could not get Xen capabilities"); - goto error_out; - } - - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" - " Loader: %016"PRIx64"->%016"PRIx64"\n" - " TOTAL: %016"PRIx64"->%016"PRIx64"\n" - " ENTRY ADDRESS: %016"PRIx64"\n", - elf.pstart, elf.pend, - v_start, v_end, - elf_uval(&elf, elf.ehdr, e_entry)); - - if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) - { - PERROR("Could not allocate memory."); - goto error_out; - } - - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - for ( i = mmio_start >> PAGE_SHIFT; i < nr_pages; i++ ) - page_array[i] += mmio_size >> PAGE_SHIFT; - - /* - * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. - * - * We attempt to allocate 1GB pages if possible. It falls back on 2MB - * pages if 1GB allocation fails. 4KB pages will be used eventually if - * both fail. - * - * Under 2MB mode, we allocate pages in batches of no more than 8MB to - * ensure that we can be preempted and hence dom0 remains responsive. - */ - rc = xc_domain_populate_physmap_exact( - xch, dom, 0xa0, 0, 0, &page_array[0x00]); - cur_pages = 0xc0; - stat_normal_pages = 0xc0; - while ( (rc == 0) && (nr_pages > cur_pages) ) - { - /* Clip count to maximum 1GB extent. */ - unsigned long count = nr_pages - cur_pages; - unsigned long max_pages = SUPERPAGE_1GB_NR_PFNS; - - if ( count > max_pages ) - count = max_pages; - - cur_pfn = page_array[cur_pages]; - - /* Take care the corner cases of super page tails */ - if ( ((cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && - (count > (-cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1))) ) - count = -cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1); - else if ( ((count & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && - (count > SUPERPAGE_1GB_NR_PFNS) ) - count &= ~(SUPERPAGE_1GB_NR_PFNS - 1); - - /* Attemp to allocate 1GB super page. Because in each pass we only - * allocate at most 1GB, we don''t have to clip super page boundaries. - */ - if ( ((count | cur_pfn) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 && - /* Check if there exists MMIO hole in the 1GB memory range */ - !check_mmio_hole(cur_pfn << PAGE_SHIFT, - SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT, - mmio_start, mmio_size) ) - { - long done; - unsigned long nr_extents = count >> SUPERPAGE_1GB_SHIFT; - xen_pfn_t sp_extents[nr_extents]; - - for ( i = 0; i < nr_extents; i++ ) - sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_1GB_SHIFT)]; - - done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_1GB_SHIFT, - pod_mode ? XENMEMF_populate_on_demand : 0, - sp_extents); - - if ( done > 0 ) - { - stat_1gb_pages += done; - done <<= SUPERPAGE_1GB_SHIFT; - cur_pages += done; - count -= done; - } - } - - if ( count != 0 ) - { - /* Clip count to maximum 8MB extent. */ - max_pages = SUPERPAGE_2MB_NR_PFNS * 4; - if ( count > max_pages ) - count = max_pages; - - /* Clip partial superpage extents to superpage boundaries. */ - if ( ((cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && - (count > (-cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1))) ) - count = -cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1); - else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && - (count > SUPERPAGE_2MB_NR_PFNS) ) - count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */ - - /* Attempt to allocate superpage extents. */ - if ( ((count | cur_pfn) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 ) - { - long done; - unsigned long nr_extents = count >> SUPERPAGE_2MB_SHIFT; - xen_pfn_t sp_extents[nr_extents]; - - for ( i = 0; i < nr_extents; i++ ) - sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_2MB_SHIFT)]; - - done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_2MB_SHIFT, - pod_mode ? XENMEMF_populate_on_demand : 0, - sp_extents); - - if ( done > 0 ) - { - stat_2mb_pages += done; - done <<= SUPERPAGE_2MB_SHIFT; - cur_pages += done; - count -= done; - } - } - } - - /* Fall back to 4kB extents. */ - if ( count != 0 ) - { - rc = xc_domain_populate_physmap_exact( - xch, dom, count, 0, 0, &page_array[cur_pages]); - cur_pages += count; - stat_normal_pages += count; - } - } - - /* Subtract 0x20 from target_pages for the VGA "hole". Xen will - * adjust the PoD cache size so that domain tot_pages will be - * target_pages - 0x20 after this call. */ - if ( pod_mode ) - rc = xc_domain_set_pod_target(xch, dom, target_pages - 0x20, - NULL, NULL, NULL); - - if ( rc != 0 ) - { - PERROR("Could not allocate memory for HVM guest."); - goto error_out; - } - - IPRINTF("PHYSICAL MEMORY ALLOCATION:\n" - " 4KB PAGES: 0x%016lx\n" - " 2MB PAGES: 0x%016lx\n" - " 1GB PAGES: 0x%016lx\n", - stat_normal_pages, stat_2mb_pages, stat_1gb_pages); - - if ( loadelfimage(xch, &elf, dom, page_array) != 0 ) - goto error_out; - - if ( (hvm_info_page = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - HVM_INFO_PFN)) == NULL ) - goto error_out; - build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size); - munmap(hvm_info_page, PAGE_SIZE); - - /* Allocate and clear special pages. */ - for ( i = 0; i < NR_SPECIAL_PAGES; i++ ) - { - xen_pfn_t pfn = special_pfn(i); - rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn); - if ( rc != 0 ) - { - PERROR("Could not allocate %d''th special page.", i); - goto error_out; - } - if ( xc_clear_domain_page(xch, dom, special_pfn(i)) ) - goto error_out; - } - - xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN, - special_pfn(SPECIALPAGE_XENSTORE)); - xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN, - special_pfn(SPECIALPAGE_BUFIOREQ)); - xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN, - special_pfn(SPECIALPAGE_IOREQ)); - xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN, - special_pfn(SPECIALPAGE_CONSOLE)); - - /* - * Identity-map page table is required for running with CR0.PG=0 when - * using Intel EPT. Create a 32-bit non-PAE page directory of superpages. - */ - if ( (ident_pt = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - special_pfn(SPECIALPAGE_IDENT_PT))) == NULL ) - goto error_out; - for ( i = 0; i < PAGE_SIZE / sizeof(*ident_pt); i++ ) - ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | - _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE); - munmap(ident_pt, PAGE_SIZE); - xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, - special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); - - /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */ - entry_eip = elf_uval(&elf, elf.ehdr, e_entry); - if ( entry_eip != 0 ) - { - char *page0 = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, 0); - if ( page0 == NULL ) - goto error_out; - page0[0] = 0xe9; - *(uint32_t *)&page0[1] = entry_eip - 5; - munmap(page0, PAGE_SIZE); - } - - free(page_array); - return 0; - - error_out: - free(page_array); - return -1; -} - -/* xc_hvm_build: - * Create a domain for a virtualized Linux, using files/filenames. - */ -int xc_hvm_build(xc_interface *xch, uint32_t domid, - const struct xc_hvm_build_args *hvm_args) -{ - struct xc_hvm_build_args args = *hvm_args; - void *image; - unsigned long image_size; - int sts; - - if ( domid == 0 ) - return -1; - if ( args.image_file_name == NULL ) - return -1; - - if ( args.mem_target == 0 ) - args.mem_target = args.mem_size; - - if ( args.mmio_size == 0 ) - args.mmio_size = HVM_BELOW_4G_MMIO_LENGTH; - - /* An HVM guest must be initialised with at least 2MB memory. */ - if ( args.mem_size < (2ull << 20) || args.mem_target < (2ull << 20) ) - return -1; - - image = xc_read_image(xch, args.image_file_name, &image_size); - if ( image == NULL ) - return -1; - - sts = setup_guest(xch, domid, &args, image, image_size); - - free(image); - - return sts; -} - -/* xc_hvm_build_target_mem: - * Create a domain for a pre-ballooned virtualized Linux, using - * files/filenames. If target < memsize, domain is created with - * memsize pages marked populate-on-demand, - * calculating pod cache size based on target. - * If target == memsize, pages are populated normally. - */ -int xc_hvm_build_target_mem(xc_interface *xch, - uint32_t domid, - int memsize, - int target, - const char *image_name) -{ - struct xc_hvm_build_args args = {}; - - args.mem_size = (uint64_t)memsize << 20; - args.mem_target = (uint64_t)target << 20; - args.image_file_name = image_name; - - return xc_hvm_build(xch, domid, &args); -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/tools/libxc/xc_hvm_build_arm.c b/tools/libxc/xc_hvm_build_arm.c new file mode 100644 index 0000000..010ebdb --- /dev/null +++ b/tools/libxc/xc_hvm_build_arm.c @@ -0,0 +1,61 @@ +/****************************************************************************** + * This library 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 of the License. + * + * This library 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Copyright (c) 2011, Citrix Systems + */ + +#include <inttypes.h> +#include <errno.h> +#include <xenctrl.h> +#include <xenguest.h> + +int xc_hvm_build(xc_interface *xch, + uint32_t domid, + int memsize, + const char *image_name) +{ + errno = ENOSYS; + return -1; +} + +int xc_hvm_build_target_mem(xc_interface *xch, + uint32_t domid, + int memsize, + int target, + const char *image_name) +{ + errno = ENOSYS; + return -1; +} + +int xc_hvm_build_mem(xc_interface *xch, + uint32_t domid, + int memsize, + const char *image_buffer, + unsigned long image_size) +{ + errno = ENOSYS; + return -1; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c new file mode 100644 index 0000000..780b23f --- /dev/null +++ b/tools/libxc/xc_hvm_build_x86.c @@ -0,0 +1,463 @@ +/****************************************************************************** + * xc_hvm_build.c + * + * This library 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 of the License. + * + * This library 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stddef.h> +#include <inttypes.h> +#include <stdlib.h> +#include <unistd.h> +#include <zlib.h> + +#include "xg_private.h" +#include "xc_private.h" + +#include <xen/foreign/x86_32.h> +#include <xen/foreign/x86_64.h> +#include <xen/hvm/hvm_info_table.h> +#include <xen/hvm/params.h> +#include <xen/hvm/e820.h> + +#include <xen/libelf/libelf.h> + +#define SUPERPAGE_2MB_SHIFT 9 +#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT) +#define SUPERPAGE_1GB_SHIFT 18 +#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT) + +#define SPECIALPAGE_BUFIOREQ 0 +#define SPECIALPAGE_XENSTORE 1 +#define SPECIALPAGE_IOREQ 2 +#define SPECIALPAGE_IDENT_PT 3 +#define SPECIALPAGE_CONSOLE 4 +#define NR_SPECIAL_PAGES 5 +#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x)) + +static void build_hvm_info(void *hvm_info_page, uint64_t mem_size, + uint64_t mmio_start, uint64_t mmio_size) +{ + struct hvm_info_table *hvm_info = (struct hvm_info_table *) + (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET); + uint64_t lowmem_end = mem_size, highmem_end = 0; + uint8_t sum; + int i; + + if ( lowmem_end > mmio_start ) + { + highmem_end = (1ull<<32) + (lowmem_end - mmio_start); + lowmem_end = mmio_start; + } + + memset(hvm_info_page, 0, PAGE_SIZE); + + /* Fill in the header. */ + strncpy(hvm_info->signature, "HVM INFO", 8); + hvm_info->length = sizeof(struct hvm_info_table); + + /* Sensible defaults: these can be overridden by the caller. */ + hvm_info->apic_mode = 1; + hvm_info->nr_vcpus = 1; + memset(hvm_info->vcpu_online, 0xff, sizeof(hvm_info->vcpu_online)); + + /* Memory parameters. */ + hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT; + hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT; + hvm_info->reserved_mem_pgstart = special_pfn(0); + + /* Finish with the checksum. */ + for ( i = 0, sum = 0; i < hvm_info->length; i++ ) + sum += ((uint8_t *)hvm_info)[i]; + hvm_info->checksum = -sum; +} + +static int loadelfimage( + xc_interface *xch, + struct elf_binary *elf, uint32_t dom, unsigned long *parray) +{ + privcmd_mmap_entry_t *entries = NULL; + unsigned long pfn_start = elf->pstart >> PAGE_SHIFT; + unsigned long pfn_end = (elf->pend + PAGE_SIZE - 1) >> PAGE_SHIFT; + size_t pages = pfn_end - pfn_start; + int i, rc = -1; + + /* Map address space for initial elf image. */ + entries = calloc(pages, sizeof(privcmd_mmap_entry_t)); + if ( entries == NULL ) + goto err; + + for ( i = 0; i < pages; i++ ) + entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i]; + + elf->dest = xc_map_foreign_ranges( + xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT, + entries, pages); + if ( elf->dest == NULL ) + goto err; + + elf->dest += elf->pstart & (PAGE_SIZE - 1); + + /* Load the initial elf image. */ + rc = elf_load_binary(elf); + if ( rc < 0 ) + PERROR("Failed to load elf binary\n"); + + munmap(elf->dest, pages << PAGE_SHIFT); + elf->dest = NULL; + + err: + free(entries); + + return rc; +} + +/* + * Check whether there exists mmio hole in the specified memory range. + * Returns 1 if exists, else returns 0. + */ +static int check_mmio_hole(uint64_t start, uint64_t memsize, + uint64_t mmio_start, uint64_t mmio_size) +{ + if ( start + memsize <= mmio_start || start >= mmio_start + mmio_size ) + return 0; + else + return 1; +} + +static int setup_guest(xc_interface *xch, + uint32_t dom, const struct xc_hvm_build_args *args, + char *image, unsigned long image_size) +{ + xen_pfn_t *page_array = NULL; + unsigned long i, nr_pages = args->mem_size >> PAGE_SHIFT; + unsigned long target_pages = args->mem_target >> PAGE_SHIFT; + uint64_t mmio_start = (1ull << 32) - args->mmio_size; + uint64_t mmio_size = args->mmio_size; + unsigned long entry_eip, cur_pages, cur_pfn; + void *hvm_info_page; + uint32_t *ident_pt; + struct elf_binary elf; + uint64_t v_start, v_end; + int rc; + xen_capabilities_info_t caps; + unsigned long stat_normal_pages = 0, stat_2mb_pages = 0, + stat_1gb_pages = 0; + int pod_mode = 0; + + if ( nr_pages > target_pages ) + pod_mode = 1; + + memset(&elf, 0, sizeof(elf)); + if ( elf_init(&elf, image, image_size) != 0 ) + goto error_out; + + xc_elf_set_logfile(xch, &elf, 1); + + elf_parse_binary(&elf); + v_start = 0; + v_end = args->mem_size; + + if ( xc_version(xch, XENVER_capabilities, &caps) != 0 ) + { + PERROR("Could not get Xen capabilities"); + goto error_out; + } + + IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" + " Loader: %016"PRIx64"->%016"PRIx64"\n" + " TOTAL: %016"PRIx64"->%016"PRIx64"\n" + " ENTRY ADDRESS: %016"PRIx64"\n", + elf.pstart, elf.pend, + v_start, v_end, + elf_uval(&elf, elf.ehdr, e_entry)); + + if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) + { + PERROR("Could not allocate memory."); + goto error_out; + } + + for ( i = 0; i < nr_pages; i++ ) + page_array[i] = i; + for ( i = mmio_start >> PAGE_SHIFT; i < nr_pages; i++ ) + page_array[i] += mmio_size >> PAGE_SHIFT; + + /* + * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. + * + * We attempt to allocate 1GB pages if possible. It falls back on 2MB + * pages if 1GB allocation fails. 4KB pages will be used eventually if + * both fail. + * + * Under 2MB mode, we allocate pages in batches of no more than 8MB to + * ensure that we can be preempted and hence dom0 remains responsive. + */ + rc = xc_domain_populate_physmap_exact( + xch, dom, 0xa0, 0, 0, &page_array[0x00]); + cur_pages = 0xc0; + stat_normal_pages = 0xc0; + while ( (rc == 0) && (nr_pages > cur_pages) ) + { + /* Clip count to maximum 1GB extent. */ + unsigned long count = nr_pages - cur_pages; + unsigned long max_pages = SUPERPAGE_1GB_NR_PFNS; + + if ( count > max_pages ) + count = max_pages; + + cur_pfn = page_array[cur_pages]; + + /* Take care the corner cases of super page tails */ + if ( ((cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && + (count > (-cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1))) ) + count = -cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1); + else if ( ((count & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && + (count > SUPERPAGE_1GB_NR_PFNS) ) + count &= ~(SUPERPAGE_1GB_NR_PFNS - 1); + + /* Attemp to allocate 1GB super page. Because in each pass we only + * allocate at most 1GB, we don''t have to clip super page boundaries. + */ + if ( ((count | cur_pfn) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 && + /* Check if there exists MMIO hole in the 1GB memory range */ + !check_mmio_hole(cur_pfn << PAGE_SHIFT, + SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT, + mmio_start, mmio_size) ) + { + long done; + unsigned long nr_extents = count >> SUPERPAGE_1GB_SHIFT; + xen_pfn_t sp_extents[nr_extents]; + + for ( i = 0; i < nr_extents; i++ ) + sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_1GB_SHIFT)]; + + done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_1GB_SHIFT, + pod_mode ? XENMEMF_populate_on_demand : 0, + sp_extents); + + if ( done > 0 ) + { + stat_1gb_pages += done; + done <<= SUPERPAGE_1GB_SHIFT; + cur_pages += done; + count -= done; + } + } + + if ( count != 0 ) + { + /* Clip count to maximum 8MB extent. */ + max_pages = SUPERPAGE_2MB_NR_PFNS * 4; + if ( count > max_pages ) + count = max_pages; + + /* Clip partial superpage extents to superpage boundaries. */ + if ( ((cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && + (count > (-cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1))) ) + count = -cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1); + else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && + (count > SUPERPAGE_2MB_NR_PFNS) ) + count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */ + + /* Attempt to allocate superpage extents. */ + if ( ((count | cur_pfn) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 ) + { + long done; + unsigned long nr_extents = count >> SUPERPAGE_2MB_SHIFT; + xen_pfn_t sp_extents[nr_extents]; + + for ( i = 0; i < nr_extents; i++ ) + sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_2MB_SHIFT)]; + + done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_2MB_SHIFT, + pod_mode ? XENMEMF_populate_on_demand : 0, + sp_extents); + + if ( done > 0 ) + { + stat_2mb_pages += done; + done <<= SUPERPAGE_2MB_SHIFT; + cur_pages += done; + count -= done; + } + } + } + + /* Fall back to 4kB extents. */ + if ( count != 0 ) + { + rc = xc_domain_populate_physmap_exact( + xch, dom, count, 0, 0, &page_array[cur_pages]); + cur_pages += count; + stat_normal_pages += count; + } + } + + /* Subtract 0x20 from target_pages for the VGA "hole". Xen will + * adjust the PoD cache size so that domain tot_pages will be + * target_pages - 0x20 after this call. */ + if ( pod_mode ) + rc = xc_domain_set_pod_target(xch, dom, target_pages - 0x20, + NULL, NULL, NULL); + + if ( rc != 0 ) + { + PERROR("Could not allocate memory for HVM guest."); + goto error_out; + } + + IPRINTF("PHYSICAL MEMORY ALLOCATION:\n" + " 4KB PAGES: 0x%016lx\n" + " 2MB PAGES: 0x%016lx\n" + " 1GB PAGES: 0x%016lx\n", + stat_normal_pages, stat_2mb_pages, stat_1gb_pages); + + if ( loadelfimage(xch, &elf, dom, page_array) != 0 ) + goto error_out; + + if ( (hvm_info_page = xc_map_foreign_range( + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, + HVM_INFO_PFN)) == NULL ) + goto error_out; + build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size); + munmap(hvm_info_page, PAGE_SIZE); + + /* Allocate and clear special pages. */ + for ( i = 0; i < NR_SPECIAL_PAGES; i++ ) + { + xen_pfn_t pfn = special_pfn(i); + rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn); + if ( rc != 0 ) + { + PERROR("Could not allocate %d''th special page.", i); + goto error_out; + } + if ( xc_clear_domain_page(xch, dom, special_pfn(i)) ) + goto error_out; + } + + xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN, + special_pfn(SPECIALPAGE_XENSTORE)); + xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN, + special_pfn(SPECIALPAGE_BUFIOREQ)); + xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN, + special_pfn(SPECIALPAGE_IOREQ)); + xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN, + special_pfn(SPECIALPAGE_CONSOLE)); + + /* + * Identity-map page table is required for running with CR0.PG=0 when + * using Intel EPT. Create a 32-bit non-PAE page directory of superpages. + */ + if ( (ident_pt = xc_map_foreign_range( + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, + special_pfn(SPECIALPAGE_IDENT_PT))) == NULL ) + goto error_out; + for ( i = 0; i < PAGE_SIZE / sizeof(*ident_pt); i++ ) + ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | + _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE); + munmap(ident_pt, PAGE_SIZE); + xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, + special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); + + /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */ + entry_eip = elf_uval(&elf, elf.ehdr, e_entry); + if ( entry_eip != 0 ) + { + char *page0 = xc_map_foreign_range( + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, 0); + if ( page0 == NULL ) + goto error_out; + page0[0] = 0xe9; + *(uint32_t *)&page0[1] = entry_eip - 5; + munmap(page0, PAGE_SIZE); + } + + free(page_array); + return 0; + + error_out: + free(page_array); + return -1; +} + +/* xc_hvm_build: + * Create a domain for a virtualized Linux, using files/filenames. + */ +int xc_hvm_build(xc_interface *xch, uint32_t domid, + const struct xc_hvm_build_args *hvm_args) +{ + struct xc_hvm_build_args args = *hvm_args; + void *image; + unsigned long image_size; + int sts; + + if ( domid == 0 ) + return -1; + if ( args.image_file_name == NULL ) + return -1; + + if ( args.mem_target == 0 ) + args.mem_target = args.mem_size; + + if ( args.mmio_size == 0 ) + args.mmio_size = HVM_BELOW_4G_MMIO_LENGTH; + + /* An HVM guest must be initialised with at least 2MB memory. */ + if ( args.mem_size < (2ull << 20) || args.mem_target < (2ull << 20) ) + return -1; + + image = xc_read_image(xch, args.image_file_name, &image_size); + if ( image == NULL ) + return -1; + + sts = setup_guest(xch, domid, &args, image, image_size); + + free(image); + + return sts; +} + +/* xc_hvm_build_target_mem: + * Create a domain for a pre-ballooned virtualized Linux, using + * files/filenames. If target < memsize, domain is created with + * memsize pages marked populate-on-demand, + * calculating pod cache size based on target. + * If target == memsize, pages are populated normally. + */ +int xc_hvm_build_target_mem(xc_interface *xch, + uint32_t domid, + int memsize, + int target, + const char *image_name) +{ + struct xc_hvm_build_args args = {}; + + args.mem_size = (uint64_t)memsize << 20; + args.mem_target = (uint64_t)target << 20; + args.image_file_name = image_name; + + return xc_hvm_build(xch, domid, &args); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_nomigrate.c b/tools/libxc/xc_nomigrate.c new file mode 100644 index 0000000..e734d73 --- /dev/null +++ b/tools/libxc/xc_nomigrate.c @@ -0,0 +1,53 @@ +/****************************************************************************** + * This library 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 of the License. + * + * This library 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Copyright (c) 2011, Citrix Systems + */ + +#include <inttypes.h> +#include <errno.h> +#include <xenctrl.h> +#include <xenguest.h> + +int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters, + uint32_t max_factor, uint32_t flags, + struct save_callbacks* callbacks, int hvm, + unsigned long vm_generationid_addr) +{ + errno = ENOSYS; + return -1; +} + +int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, + unsigned int store_evtchn, unsigned long *store_mfn, + domid_t store_domid, unsigned int console_evtchn, + unsigned long *console_mfn, domid_t console_domid, + unsigned int hvm, unsigned int pae, int superpages, + int no_incr_generationid, + unsigned long *vm_generationid_addr) +{ + errno = ENOSYS; + return -1; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 1.7.2.5
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <Ian.campbell@citrix.com> --- tools/memshr/bidir-hash.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/tools/memshr/bidir-hash.c b/tools/memshr/bidir-hash.c index 6c0dc3d..45d473e 100644 --- a/tools/memshr/bidir-hash.c +++ b/tools/memshr/bidir-hash.c @@ -109,6 +109,37 @@ static void hash_resize(struct __hash *h); } while (0) static inline void atomic_inc(uint32_t *v) { ia64_fetchadd4_rel(v, 1); } static inline void atomic_dec(uint32_t *v) { ia64_fetchadd4_rel(v, -1); } +#elif defined(__arm__) +static inline void atomic_inc(uint32_t *v) +{ + unsigned long tmp; + int result; + + __asm__ __volatile__("@ atomic_add\n" +"1: ldrex %0, [%3]\n" +" add %0, %0, #1\n" +" strex %1, %0, [%3]\n" +" teq %1, #0\n" +" bne 1b" + : "=&r" (result), "=&r" (tmp), "+Qo" (*v) + : "r" (v) + : "cc"); +} +static inline void atomic_dec(uint32_t *v) +{ + unsigned long tmp; + int result; + + __asm__ __volatile__("@ atomic_sub\n" +"1: ldrex %0, [%3]\n" +" sub %0, %0, #1\n" +" strex %1, %0, [%3]\n" +" teq %1, #0\n" +" bne 1b" + : "=&r" (result), "=&r" (tmp), "+Qo" (*v) + : "r" (v) + : "cc"); +} #else /* __x86__ */ static inline void atomic_inc(uint32_t *v) { -- 1.7.2.5
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/xentrace/xenctx.c | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index a12cc21..530ef65 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -60,6 +60,12 @@ int disp_ar_regs; int disp_br_regs; int disp_bank_regs; int disp_tlb; + +#elif defined(__arm__) +#define NO_TRANSLATION +typedef uint64_t guest_word_t; +#define FMT_32B_WORD "%08llx" +#define FMT_64B_WORD "%016llx" #endif struct symbol { @@ -678,6 +684,12 @@ void print_ctx(vcpu_guest_context_any_t *ctx) print_tr(i, &tr->dtrs[i]); } } +#elif defined(__arm__) +static void print_ctx(vcpu_guest_context_any_t *ctx) +{ + /* XXX: properly implement this */ + print_symbol(0); +} #endif #ifndef NO_TRANSLATION -- 1.7.2.5
libxl_cpuid_destroy has been renamed to libxl_cpuid_dispose; also cpuid functions are only available on x86, so ifdef the new cpuid related function in libxl_json.c. Changes in v3: - move libxl_cpuid_policy_list_gen_json to libxl_(no)cpuid.c. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/Makefile | 1 + tools/libxl/libxl_cpuid.c | 60 +++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_json.c | 60 ------------------------------------------- tools/libxl/libxl_nocpuid.c | 8 +++++- 4 files changed, 68 insertions(+), 61 deletions(-) diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index e44fcfa..8ccc564 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -32,6 +32,7 @@ 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 ifeq ($(CONFIG_NetBSD),y) LIBXL_OBJS-y += libxl_netbsd.o diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c index dcdb9d0..ff7531f 100644 --- a/tools/libxl/libxl_cpuid.c +++ b/tools/libxl/libxl_cpuid.c @@ -333,6 +333,66 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid, (const char**)(cpuid[i].policy), cpuid_res); } +yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand, + libxl_cpuid_policy_list *pcpuid) +{ + libxl_cpuid_policy_list cpuid = *pcpuid; + yajl_gen_status s; + const char *input_names[2] = { "leaf", "subleaf" }; + const char *policy_names[4] = { "eax", "ebx", "ecx", "edx" }; + int i, j; + + /* + * Aiming for: + * [ + * { ''leaf'': ''val-eax'', + * ''subleaf'': ''val-ecx'', + * ''eax'': ''filter'', + * ''ebx'': ''filter'', + * ''ecx'': ''filter'', + * ''edx'': ''filter'' }, + * { ''leaf'': ''val-eax'', ..., ''eax'': ''filter'', ... }, + * ... etc ... + * ] + */ + + s = yajl_gen_array_open(hand); + if (s != yajl_gen_status_ok) goto out; + + if (cpuid == NULL) goto empty; + + for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) { + s = yajl_gen_map_open(hand); + if (s != yajl_gen_status_ok) goto out; + + for (j = 0; j < 2; j++) { + if (cpuid[i].input[j] != XEN_CPUID_INPUT_UNUSED) { + s = libxl__yajl_gen_asciiz(hand, input_names[j]); + if (s != yajl_gen_status_ok) goto out; + s = yajl_gen_integer(hand, cpuid[i].input[j]); + if (s != yajl_gen_status_ok) goto out; + } + } + + for (j = 0; j < 4; j++) { + if (cpuid[i].policy[j] != NULL) { + s = libxl__yajl_gen_asciiz(hand, policy_names[j]); + if (s != yajl_gen_status_ok) goto out; + s = yajl_gen_string(hand, + (const unsigned char *)cpuid[i].policy[j], 32); + if (s != yajl_gen_status_ok) goto out; + } + } + s = yajl_gen_map_close(hand); + if (s != yajl_gen_status_ok) goto out; + } + +empty: + s = yajl_gen_array_close(hand); +out: + return s; +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 7c068d3..f430d4a 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -146,66 +146,6 @@ out: return s; } -yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand, - libxl_cpuid_policy_list *pcpuid) -{ - libxl_cpuid_policy_list cpuid = *pcpuid; - yajl_gen_status s; - const char *input_names[2] = { "leaf", "subleaf" }; - const char *policy_names[4] = { "eax", "ebx", "ecx", "edx" }; - int i, j; - - /* - * Aiming for: - * [ - * { ''leaf'': ''val-eax'', - * ''subleaf'': ''val-ecx'', - * ''eax'': ''filter'', - * ''ebx'': ''filter'', - * ''ecx'': ''filter'', - * ''edx'': ''filter'' }, - * { ''leaf'': ''val-eax'', ..., ''eax'': ''filter'', ... }, - * ... etc ... - * ] - */ - - s = yajl_gen_array_open(hand); - if (s != yajl_gen_status_ok) goto out; - - if (cpuid == NULL) goto empty; - - for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) { - s = yajl_gen_map_open(hand); - if (s != yajl_gen_status_ok) goto out; - - for (j = 0; j < 2; j++) { - if (cpuid[i].input[j] != XEN_CPUID_INPUT_UNUSED) { - s = libxl__yajl_gen_asciiz(hand, input_names[j]); - if (s != yajl_gen_status_ok) goto out; - s = yajl_gen_integer(hand, cpuid[i].input[j]); - if (s != yajl_gen_status_ok) goto out; - } - } - - for (j = 0; j < 4; j++) { - if (cpuid[i].policy[j] != NULL) { - s = libxl__yajl_gen_asciiz(hand, policy_names[j]); - if (s != yajl_gen_status_ok) goto out; - s = yajl_gen_string(hand, - (const unsigned char *)cpuid[i].policy[j], 32); - if (s != yajl_gen_status_ok) goto out; - } - } - s = yajl_gen_map_close(hand); - if (s != yajl_gen_status_ok) goto out; - } - -empty: - s = yajl_gen_array_close(hand); -out: - return s; -} - yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list *pl) { libxl_string_list l = *pl; diff --git a/tools/libxl/libxl_nocpuid.c b/tools/libxl/libxl_nocpuid.c index 9e52f8d..5f7cb6a 100644 --- a/tools/libxl/libxl_nocpuid.c +++ b/tools/libxl/libxl_nocpuid.c @@ -14,7 +14,7 @@ #include "libxl_internal.h" -void libxl_cpuid_destroy(libxl_cpuid_policy_list *p_cpuid_list) +void libxl_cpuid_dispose(libxl_cpuid_policy_list *p_cpuid_list) { } @@ -38,6 +38,12 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid, { } +yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand, + libxl_cpuid_policy_list *pcpuid) +{ + return 0; +} + /* * Local variables: * mode: C -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 16:25 UTC
[PATCH v6 5/5] 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@eu.citrix.com> Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com> --- tools/libxl/Makefile | 6 +- tools/libxl/libxl_arch.h | 22 ++++ tools/libxl/libxl_create.c | 11 +-- tools/libxl/libxl_internal.h | 2 - tools/libxl/libxl_noarch.c | 8 ++ tools/libxl/libxl_pci.c | 242 --------------------------------------- tools/libxl/libxl_x86.c | 259 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 294 insertions(+), 256 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 8ccc564..5421e16 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -30,9 +30,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 8417661..2a97e95 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> @@ -690,15 +691,7 @@ static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config, } } - if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && - libxl_defbool_val(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_internal.h b/tools/libxl/libxl_internal.h index e0a1070..0a6b7df 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1000,8 +1000,6 @@ _hidden int libxl__error_set(libxl__gc *gc, int code); _hidden int libxl__file_reference_map(libxl_file_reference *f); _hidden int libxl__file_reference_unmap(libxl_file_reference *f); -_hidden int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config); - /* parse the string @s as a sequence of 6 colon separated bytes in to @mac */ _hidden int libxl__parse_mac(const char *s, libxl_mac mac); /* compare mac address @a and @b. 0 if the same, -ve if a<b and +ve if a>b */ 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 4175ac3..bc631f4 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -1155,248 +1155,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 (!libxl_defbool_val(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..10d5e5f --- /dev/null +++ b/tools/libxl/libxl_x86.c @@ -0,0 +1,259 @@ +#include "libxl_internal.h" +#include "libxl_arch.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 (!libxl_defbool_val(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) +{ + int rc = 0; + if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && + d_config->b_info.u.pv.e820_host) { + rc = libxl__e820_alloc(gc, domid, d_config); + if (rc) + LIBXL__LOG_ERRNO(libxl__gc_owner(gc), LIBXL__LOG_ERROR, + "Failed while collecting E820 with: %d (errno:%d)\n", + rc, errno); + } + return rc; +} -- 1.7.2.5
Stefano Stabellini writes ("[PATCH v6 2/5] arm: compile memshr"):> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Acked-by: Ian Campbell <Ian.campbell@citrix.com>Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Stefano Stabellini writes ("[PATCH v6 3/5] arm: compile xentrace"):> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Acked-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Stefano Stabellini writes ("[PATCH v6 4/5] arm: compile libxl"):> libxl_cpuid_destroy has been renamed to libxl_cpuid_dispose; also cpuid > functions are only available on x86, so ifdef the new cpuid related > function in libxl_json.c.Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> I see that you don''t really mean "ifdef", which is good. Ian.
On Fri, 2012-03-02 at 16:25 +0000, Stefano Stabellini wrote:> Introduce an empty implementation of the arch specific ARM functions in > xc_dom_arm.c. > Provide empty implementations of xc_domain_save and xc_domain_restore > when CONFIG_MIGRATE is not set. > Move xc_hvm_build.c to xc_hvm_build_x86.c because the implementation is > x86 specific, introduce xc_hvm_build_arm.c with empty stubs. > > > Changes in v3: > > - rename xc_hvm_build.c to xc_hvm_build_x86.c; > > - remove xc_nohvm, introduce xc_hvm_build_arm.c instead; > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com>I think I already acked v5 of this patch, did it change substantially?> --- > tools/libxc/Makefile | 12 +- > tools/libxc/xc_dom_arm.c | 50 +++++ > tools/libxc/xc_hvm_build.c | 463 ---------------------------------------- > tools/libxc/xc_hvm_build_arm.c | 61 ++++++ > tools/libxc/xc_hvm_build_x86.c | 463 ++++++++++++++++++++++++++++++++++++++++ > tools/libxc/xc_nomigrate.c | 53 +++++ > 6 files changed, 636 insertions(+), 466 deletions(-) > create mode 100644 tools/libxc/xc_dom_arm.c > delete mode 100644 tools/libxc/xc_hvm_build.c > create mode 100644 tools/libxc/xc_hvm_build_arm.c > create mode 100644 tools/libxc/xc_hvm_build_x86.c > create mode 100644 tools/libxc/xc_nomigrate.c > > diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile > index f2e1ba7..02d39a3 100644 > --- a/tools/libxc/Makefile > +++ b/tools/libxc/Makefile > @@ -42,9 +42,12 @@ CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c > > GUEST_SRCS-y :> GUEST_SRCS-y += xg_private.c xc_suspend.c > -GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c > -GUEST_SRCS-$(CONFIG_MIGRATE) += xc_offline_page.c xc_compression.c > -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c > +ifeq ($(CONFIG_MIGRATE),y) > +GUEST_SRCS-y += xc_domain_restore.c xc_domain_save.c > +GUEST_SRCS-y += xc_offline_page.c xc_compression.c > +else > +GUEST_SRCS-y += xc_nomigrate.c > +endif > > vpath %.c ../../xen/common/libelf > CFLAGS += -I../../xen/common/libelf > @@ -61,7 +64,10 @@ GUEST_SRCS-y += xc_dom_compat_linux.c > > GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c > GUEST_SRCS-$(CONFIG_X86) += xc_cpuid_x86.c > +GUEST_SRCS-$(CONFIG_X86) += xc_hvm_build_x86.c > GUEST_SRCS-$(CONFIG_IA64) += xc_dom_ia64.c > +GUEST_SRCS-$(CONFIG_ARM) += xc_dom_arm.c > +GUEST_SRCS-$(CONFIG_ARM) += xc_hvm_build_arm.c > > OSDEP_SRCS-y += xenctrl_osdep_ENOSYS.c > > diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c > new file mode 100644 > index 0000000..122d0e8 > --- /dev/null > +++ b/tools/libxc/xc_dom_arm.c > @@ -0,0 +1,50 @@ > +/* > + * Xen domain builder -- ARM > + * > + * This library 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 of the License. > + * > + * This library 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + * > + * Copyright (c) 2011, Citrix Systems > + */ > +#include <inttypes.h> > +#include <xen/xen.h> > +#include "xg_private.h" > +#include "xc_dom.h" > + > +int arch_setup_meminit(struct xc_dom_image *dom) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +int arch_setup_bootearly(struct xc_dom_image *dom) > +{ > + DOMPRINTF("%s: doing nothing", __FUNCTION__); > + return 0; > +} > + > +int arch_setup_bootlate(struct xc_dom_image *dom) > +{ > + DOMPRINTF("%s: doing nothing", __FUNCTION__); > + return 0; > +} > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c > deleted file mode 100644 > index 780b23f..0000000 > --- a/tools/libxc/xc_hvm_build.c > +++ /dev/null > @@ -1,463 +0,0 @@ > -/****************************************************************************** > - * xc_hvm_build.c > - * > - * This library 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 of the License. > - * > - * This library 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. > - * > - * You should have received a copy of the GNU Lesser General Public > - * License along with this library; if not, write to the Free Software > - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > - */ > - > -#include <stddef.h> > -#include <inttypes.h> > -#include <stdlib.h> > -#include <unistd.h> > -#include <zlib.h> > - > -#include "xg_private.h" > -#include "xc_private.h" > - > -#include <xen/foreign/x86_32.h> > -#include <xen/foreign/x86_64.h> > -#include <xen/hvm/hvm_info_table.h> > -#include <xen/hvm/params.h> > -#include <xen/hvm/e820.h> > - > -#include <xen/libelf/libelf.h> > - > -#define SUPERPAGE_2MB_SHIFT 9 > -#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT) > -#define SUPERPAGE_1GB_SHIFT 18 > -#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT) > - > -#define SPECIALPAGE_BUFIOREQ 0 > -#define SPECIALPAGE_XENSTORE 1 > -#define SPECIALPAGE_IOREQ 2 > -#define SPECIALPAGE_IDENT_PT 3 > -#define SPECIALPAGE_CONSOLE 4 > -#define NR_SPECIAL_PAGES 5 > -#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x)) > - > -static void build_hvm_info(void *hvm_info_page, uint64_t mem_size, > - uint64_t mmio_start, uint64_t mmio_size) > -{ > - struct hvm_info_table *hvm_info = (struct hvm_info_table *) > - (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET); > - uint64_t lowmem_end = mem_size, highmem_end = 0; > - uint8_t sum; > - int i; > - > - if ( lowmem_end > mmio_start ) > - { > - highmem_end = (1ull<<32) + (lowmem_end - mmio_start); > - lowmem_end = mmio_start; > - } > - > - memset(hvm_info_page, 0, PAGE_SIZE); > - > - /* Fill in the header. */ > - strncpy(hvm_info->signature, "HVM INFO", 8); > - hvm_info->length = sizeof(struct hvm_info_table); > - > - /* Sensible defaults: these can be overridden by the caller. */ > - hvm_info->apic_mode = 1; > - hvm_info->nr_vcpus = 1; > - memset(hvm_info->vcpu_online, 0xff, sizeof(hvm_info->vcpu_online)); > - > - /* Memory parameters. */ > - hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT; > - hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT; > - hvm_info->reserved_mem_pgstart = special_pfn(0); > - > - /* Finish with the checksum. */ > - for ( i = 0, sum = 0; i < hvm_info->length; i++ ) > - sum += ((uint8_t *)hvm_info)[i]; > - hvm_info->checksum = -sum; > -} > - > -static int loadelfimage( > - xc_interface *xch, > - struct elf_binary *elf, uint32_t dom, unsigned long *parray) > -{ > - privcmd_mmap_entry_t *entries = NULL; > - unsigned long pfn_start = elf->pstart >> PAGE_SHIFT; > - unsigned long pfn_end = (elf->pend + PAGE_SIZE - 1) >> PAGE_SHIFT; > - size_t pages = pfn_end - pfn_start; > - int i, rc = -1; > - > - /* Map address space for initial elf image. */ > - entries = calloc(pages, sizeof(privcmd_mmap_entry_t)); > - if ( entries == NULL ) > - goto err; > - > - for ( i = 0; i < pages; i++ ) > - entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i]; > - > - elf->dest = xc_map_foreign_ranges( > - xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT, > - entries, pages); > - if ( elf->dest == NULL ) > - goto err; > - > - elf->dest += elf->pstart & (PAGE_SIZE - 1); > - > - /* Load the initial elf image. */ > - rc = elf_load_binary(elf); > - if ( rc < 0 ) > - PERROR("Failed to load elf binary\n"); > - > - munmap(elf->dest, pages << PAGE_SHIFT); > - elf->dest = NULL; > - > - err: > - free(entries); > - > - return rc; > -} > - > -/* > - * Check whether there exists mmio hole in the specified memory range. > - * Returns 1 if exists, else returns 0. > - */ > -static int check_mmio_hole(uint64_t start, uint64_t memsize, > - uint64_t mmio_start, uint64_t mmio_size) > -{ > - if ( start + memsize <= mmio_start || start >= mmio_start + mmio_size ) > - return 0; > - else > - return 1; > -} > - > -static int setup_guest(xc_interface *xch, > - uint32_t dom, const struct xc_hvm_build_args *args, > - char *image, unsigned long image_size) > -{ > - xen_pfn_t *page_array = NULL; > - unsigned long i, nr_pages = args->mem_size >> PAGE_SHIFT; > - unsigned long target_pages = args->mem_target >> PAGE_SHIFT; > - uint64_t mmio_start = (1ull << 32) - args->mmio_size; > - uint64_t mmio_size = args->mmio_size; > - unsigned long entry_eip, cur_pages, cur_pfn; > - void *hvm_info_page; > - uint32_t *ident_pt; > - struct elf_binary elf; > - uint64_t v_start, v_end; > - int rc; > - xen_capabilities_info_t caps; > - unsigned long stat_normal_pages = 0, stat_2mb_pages = 0, > - stat_1gb_pages = 0; > - int pod_mode = 0; > - > - if ( nr_pages > target_pages ) > - pod_mode = 1; > - > - memset(&elf, 0, sizeof(elf)); > - if ( elf_init(&elf, image, image_size) != 0 ) > - goto error_out; > - > - xc_elf_set_logfile(xch, &elf, 1); > - > - elf_parse_binary(&elf); > - v_start = 0; > - v_end = args->mem_size; > - > - if ( xc_version(xch, XENVER_capabilities, &caps) != 0 ) > - { > - PERROR("Could not get Xen capabilities"); > - goto error_out; > - } > - > - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" > - " Loader: %016"PRIx64"->%016"PRIx64"\n" > - " TOTAL: %016"PRIx64"->%016"PRIx64"\n" > - " ENTRY ADDRESS: %016"PRIx64"\n", > - elf.pstart, elf.pend, > - v_start, v_end, > - elf_uval(&elf, elf.ehdr, e_entry)); > - > - if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) > - { > - PERROR("Could not allocate memory."); > - goto error_out; > - } > - > - for ( i = 0; i < nr_pages; i++ ) > - page_array[i] = i; > - for ( i = mmio_start >> PAGE_SHIFT; i < nr_pages; i++ ) > - page_array[i] += mmio_size >> PAGE_SHIFT; > - > - /* > - * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. > - * > - * We attempt to allocate 1GB pages if possible. It falls back on 2MB > - * pages if 1GB allocation fails. 4KB pages will be used eventually if > - * both fail. > - * > - * Under 2MB mode, we allocate pages in batches of no more than 8MB to > - * ensure that we can be preempted and hence dom0 remains responsive. > - */ > - rc = xc_domain_populate_physmap_exact( > - xch, dom, 0xa0, 0, 0, &page_array[0x00]); > - cur_pages = 0xc0; > - stat_normal_pages = 0xc0; > - while ( (rc == 0) && (nr_pages > cur_pages) ) > - { > - /* Clip count to maximum 1GB extent. */ > - unsigned long count = nr_pages - cur_pages; > - unsigned long max_pages = SUPERPAGE_1GB_NR_PFNS; > - > - if ( count > max_pages ) > - count = max_pages; > - > - cur_pfn = page_array[cur_pages]; > - > - /* Take care the corner cases of super page tails */ > - if ( ((cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && > - (count > (-cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1))) ) > - count = -cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1); > - else if ( ((count & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && > - (count > SUPERPAGE_1GB_NR_PFNS) ) > - count &= ~(SUPERPAGE_1GB_NR_PFNS - 1); > - > - /* Attemp to allocate 1GB super page. Because in each pass we only > - * allocate at most 1GB, we don''t have to clip super page boundaries. > - */ > - if ( ((count | cur_pfn) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 && > - /* Check if there exists MMIO hole in the 1GB memory range */ > - !check_mmio_hole(cur_pfn << PAGE_SHIFT, > - SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT, > - mmio_start, mmio_size) ) > - { > - long done; > - unsigned long nr_extents = count >> SUPERPAGE_1GB_SHIFT; > - xen_pfn_t sp_extents[nr_extents]; > - > - for ( i = 0; i < nr_extents; i++ ) > - sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_1GB_SHIFT)]; > - > - done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_1GB_SHIFT, > - pod_mode ? XENMEMF_populate_on_demand : 0, > - sp_extents); > - > - if ( done > 0 ) > - { > - stat_1gb_pages += done; > - done <<= SUPERPAGE_1GB_SHIFT; > - cur_pages += done; > - count -= done; > - } > - } > - > - if ( count != 0 ) > - { > - /* Clip count to maximum 8MB extent. */ > - max_pages = SUPERPAGE_2MB_NR_PFNS * 4; > - if ( count > max_pages ) > - count = max_pages; > - > - /* Clip partial superpage extents to superpage boundaries. */ > - if ( ((cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && > - (count > (-cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1))) ) > - count = -cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1); > - else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && > - (count > SUPERPAGE_2MB_NR_PFNS) ) > - count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */ > - > - /* Attempt to allocate superpage extents. */ > - if ( ((count | cur_pfn) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 ) > - { > - long done; > - unsigned long nr_extents = count >> SUPERPAGE_2MB_SHIFT; > - xen_pfn_t sp_extents[nr_extents]; > - > - for ( i = 0; i < nr_extents; i++ ) > - sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_2MB_SHIFT)]; > - > - done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_2MB_SHIFT, > - pod_mode ? XENMEMF_populate_on_demand : 0, > - sp_extents); > - > - if ( done > 0 ) > - { > - stat_2mb_pages += done; > - done <<= SUPERPAGE_2MB_SHIFT; > - cur_pages += done; > - count -= done; > - } > - } > - } > - > - /* Fall back to 4kB extents. */ > - if ( count != 0 ) > - { > - rc = xc_domain_populate_physmap_exact( > - xch, dom, count, 0, 0, &page_array[cur_pages]); > - cur_pages += count; > - stat_normal_pages += count; > - } > - } > - > - /* Subtract 0x20 from target_pages for the VGA "hole". Xen will > - * adjust the PoD cache size so that domain tot_pages will be > - * target_pages - 0x20 after this call. */ > - if ( pod_mode ) > - rc = xc_domain_set_pod_target(xch, dom, target_pages - 0x20, > - NULL, NULL, NULL); > - > - if ( rc != 0 ) > - { > - PERROR("Could not allocate memory for HVM guest."); > - goto error_out; > - } > - > - IPRINTF("PHYSICAL MEMORY ALLOCATION:\n" > - " 4KB PAGES: 0x%016lx\n" > - " 2MB PAGES: 0x%016lx\n" > - " 1GB PAGES: 0x%016lx\n", > - stat_normal_pages, stat_2mb_pages, stat_1gb_pages); > - > - if ( loadelfimage(xch, &elf, dom, page_array) != 0 ) > - goto error_out; > - > - if ( (hvm_info_page = xc_map_foreign_range( > - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, > - HVM_INFO_PFN)) == NULL ) > - goto error_out; > - build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size); > - munmap(hvm_info_page, PAGE_SIZE); > - > - /* Allocate and clear special pages. */ > - for ( i = 0; i < NR_SPECIAL_PAGES; i++ ) > - { > - xen_pfn_t pfn = special_pfn(i); > - rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn); > - if ( rc != 0 ) > - { > - PERROR("Could not allocate %d''th special page.", i); > - goto error_out; > - } > - if ( xc_clear_domain_page(xch, dom, special_pfn(i)) ) > - goto error_out; > - } > - > - xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN, > - special_pfn(SPECIALPAGE_XENSTORE)); > - xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN, > - special_pfn(SPECIALPAGE_BUFIOREQ)); > - xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN, > - special_pfn(SPECIALPAGE_IOREQ)); > - xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN, > - special_pfn(SPECIALPAGE_CONSOLE)); > - > - /* > - * Identity-map page table is required for running with CR0.PG=0 when > - * using Intel EPT. Create a 32-bit non-PAE page directory of superpages. > - */ > - if ( (ident_pt = xc_map_foreign_range( > - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, > - special_pfn(SPECIALPAGE_IDENT_PT))) == NULL ) > - goto error_out; > - for ( i = 0; i < PAGE_SIZE / sizeof(*ident_pt); i++ ) > - ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | > - _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE); > - munmap(ident_pt, PAGE_SIZE); > - xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, > - special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); > - > - /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */ > - entry_eip = elf_uval(&elf, elf.ehdr, e_entry); > - if ( entry_eip != 0 ) > - { > - char *page0 = xc_map_foreign_range( > - xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, 0); > - if ( page0 == NULL ) > - goto error_out; > - page0[0] = 0xe9; > - *(uint32_t *)&page0[1] = entry_eip - 5; > - munmap(page0, PAGE_SIZE); > - } > - > - free(page_array); > - return 0; > - > - error_out: > - free(page_array); > - return -1; > -} > - > -/* xc_hvm_build: > - * Create a domain for a virtualized Linux, using files/filenames. > - */ > -int xc_hvm_build(xc_interface *xch, uint32_t domid, > - const struct xc_hvm_build_args *hvm_args) > -{ > - struct xc_hvm_build_args args = *hvm_args; > - void *image; > - unsigned long image_size; > - int sts; > - > - if ( domid == 0 ) > - return -1; > - if ( args.image_file_name == NULL ) > - return -1; > - > - if ( args.mem_target == 0 ) > - args.mem_target = args.mem_size; > - > - if ( args.mmio_size == 0 ) > - args.mmio_size = HVM_BELOW_4G_MMIO_LENGTH; > - > - /* An HVM guest must be initialised with at least 2MB memory. */ > - if ( args.mem_size < (2ull << 20) || args.mem_target < (2ull << 20) ) > - return -1; > - > - image = xc_read_image(xch, args.image_file_name, &image_size); > - if ( image == NULL ) > - return -1; > - > - sts = setup_guest(xch, domid, &args, image, image_size); > - > - free(image); > - > - return sts; > -} > - > -/* xc_hvm_build_target_mem: > - * Create a domain for a pre-ballooned virtualized Linux, using > - * files/filenames. If target < memsize, domain is created with > - * memsize pages marked populate-on-demand, > - * calculating pod cache size based on target. > - * If target == memsize, pages are populated normally. > - */ > -int xc_hvm_build_target_mem(xc_interface *xch, > - uint32_t domid, > - int memsize, > - int target, > - const char *image_name) > -{ > - struct xc_hvm_build_args args = {}; > - > - args.mem_size = (uint64_t)memsize << 20; > - args.mem_target = (uint64_t)target << 20; > - args.image_file_name = image_name; > - > - return xc_hvm_build(xch, domid, &args); > -} > - > -/* > - * Local variables: > - * mode: C > - * c-set-style: "BSD" > - * c-basic-offset: 4 > - * tab-width: 4 > - * indent-tabs-mode: nil > - * End: > - */ > diff --git a/tools/libxc/xc_hvm_build_arm.c b/tools/libxc/xc_hvm_build_arm.c > new file mode 100644 > index 0000000..010ebdb > --- /dev/null > +++ b/tools/libxc/xc_hvm_build_arm.c > @@ -0,0 +1,61 @@ > +/****************************************************************************** > + * This library 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 of the License. > + * > + * This library 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + * > + * Copyright (c) 2011, Citrix Systems > + */ > + > +#include <inttypes.h> > +#include <errno.h> > +#include <xenctrl.h> > +#include <xenguest.h> > + > +int xc_hvm_build(xc_interface *xch, > + uint32_t domid, > + int memsize, > + const char *image_name) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +int xc_hvm_build_target_mem(xc_interface *xch, > + uint32_t domid, > + int memsize, > + int target, > + const char *image_name) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +int xc_hvm_build_mem(xc_interface *xch, > + uint32_t domid, > + int memsize, > + const char *image_buffer, > + unsigned long image_size) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c > new file mode 100644 > index 0000000..780b23f > --- /dev/null > +++ b/tools/libxc/xc_hvm_build_x86.c > @@ -0,0 +1,463 @@ > +/****************************************************************************** > + * xc_hvm_build.c > + * > + * This library 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 of the License. > + * > + * This library 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#include <stddef.h> > +#include <inttypes.h> > +#include <stdlib.h> > +#include <unistd.h> > +#include <zlib.h> > + > +#include "xg_private.h" > +#include "xc_private.h" > + > +#include <xen/foreign/x86_32.h> > +#include <xen/foreign/x86_64.h> > +#include <xen/hvm/hvm_info_table.h> > +#include <xen/hvm/params.h> > +#include <xen/hvm/e820.h> > + > +#include <xen/libelf/libelf.h> > + > +#define SUPERPAGE_2MB_SHIFT 9 > +#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT) > +#define SUPERPAGE_1GB_SHIFT 18 > +#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT) > + > +#define SPECIALPAGE_BUFIOREQ 0 > +#define SPECIALPAGE_XENSTORE 1 > +#define SPECIALPAGE_IOREQ 2 > +#define SPECIALPAGE_IDENT_PT 3 > +#define SPECIALPAGE_CONSOLE 4 > +#define NR_SPECIAL_PAGES 5 > +#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x)) > + > +static void build_hvm_info(void *hvm_info_page, uint64_t mem_size, > + uint64_t mmio_start, uint64_t mmio_size) > +{ > + struct hvm_info_table *hvm_info = (struct hvm_info_table *) > + (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET); > + uint64_t lowmem_end = mem_size, highmem_end = 0; > + uint8_t sum; > + int i; > + > + if ( lowmem_end > mmio_start ) > + { > + highmem_end = (1ull<<32) + (lowmem_end - mmio_start); > + lowmem_end = mmio_start; > + } > + > + memset(hvm_info_page, 0, PAGE_SIZE); > + > + /* Fill in the header. */ > + strncpy(hvm_info->signature, "HVM INFO", 8); > + hvm_info->length = sizeof(struct hvm_info_table); > + > + /* Sensible defaults: these can be overridden by the caller. */ > + hvm_info->apic_mode = 1; > + hvm_info->nr_vcpus = 1; > + memset(hvm_info->vcpu_online, 0xff, sizeof(hvm_info->vcpu_online)); > + > + /* Memory parameters. */ > + hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT; > + hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT; > + hvm_info->reserved_mem_pgstart = special_pfn(0); > + > + /* Finish with the checksum. */ > + for ( i = 0, sum = 0; i < hvm_info->length; i++ ) > + sum += ((uint8_t *)hvm_info)[i]; > + hvm_info->checksum = -sum; > +} > + > +static int loadelfimage( > + xc_interface *xch, > + struct elf_binary *elf, uint32_t dom, unsigned long *parray) > +{ > + privcmd_mmap_entry_t *entries = NULL; > + unsigned long pfn_start = elf->pstart >> PAGE_SHIFT; > + unsigned long pfn_end = (elf->pend + PAGE_SIZE - 1) >> PAGE_SHIFT; > + size_t pages = pfn_end - pfn_start; > + int i, rc = -1; > + > + /* Map address space for initial elf image. */ > + entries = calloc(pages, sizeof(privcmd_mmap_entry_t)); > + if ( entries == NULL ) > + goto err; > + > + for ( i = 0; i < pages; i++ ) > + entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i]; > + > + elf->dest = xc_map_foreign_ranges( > + xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT, > + entries, pages); > + if ( elf->dest == NULL ) > + goto err; > + > + elf->dest += elf->pstart & (PAGE_SIZE - 1); > + > + /* Load the initial elf image. */ > + rc = elf_load_binary(elf); > + if ( rc < 0 ) > + PERROR("Failed to load elf binary\n"); > + > + munmap(elf->dest, pages << PAGE_SHIFT); > + elf->dest = NULL; > + > + err: > + free(entries); > + > + return rc; > +} > + > +/* > + * Check whether there exists mmio hole in the specified memory range. > + * Returns 1 if exists, else returns 0. > + */ > +static int check_mmio_hole(uint64_t start, uint64_t memsize, > + uint64_t mmio_start, uint64_t mmio_size) > +{ > + if ( start + memsize <= mmio_start || start >= mmio_start + mmio_size ) > + return 0; > + else > + return 1; > +} > + > +static int setup_guest(xc_interface *xch, > + uint32_t dom, const struct xc_hvm_build_args *args, > + char *image, unsigned long image_size) > +{ > + xen_pfn_t *page_array = NULL; > + unsigned long i, nr_pages = args->mem_size >> PAGE_SHIFT; > + unsigned long target_pages = args->mem_target >> PAGE_SHIFT; > + uint64_t mmio_start = (1ull << 32) - args->mmio_size; > + uint64_t mmio_size = args->mmio_size; > + unsigned long entry_eip, cur_pages, cur_pfn; > + void *hvm_info_page; > + uint32_t *ident_pt; > + struct elf_binary elf; > + uint64_t v_start, v_end; > + int rc; > + xen_capabilities_info_t caps; > + unsigned long stat_normal_pages = 0, stat_2mb_pages = 0, > + stat_1gb_pages = 0; > + int pod_mode = 0; > + > + if ( nr_pages > target_pages ) > + pod_mode = 1; > + > + memset(&elf, 0, sizeof(elf)); > + if ( elf_init(&elf, image, image_size) != 0 ) > + goto error_out; > + > + xc_elf_set_logfile(xch, &elf, 1); > + > + elf_parse_binary(&elf); > + v_start = 0; > + v_end = args->mem_size; > + > + if ( xc_version(xch, XENVER_capabilities, &caps) != 0 ) > + { > + PERROR("Could not get Xen capabilities"); > + goto error_out; > + } > + > + IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" > + " Loader: %016"PRIx64"->%016"PRIx64"\n" > + " TOTAL: %016"PRIx64"->%016"PRIx64"\n" > + " ENTRY ADDRESS: %016"PRIx64"\n", > + elf.pstart, elf.pend, > + v_start, v_end, > + elf_uval(&elf, elf.ehdr, e_entry)); > + > + if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) > + { > + PERROR("Could not allocate memory."); > + goto error_out; > + } > + > + for ( i = 0; i < nr_pages; i++ ) > + page_array[i] = i; > + for ( i = mmio_start >> PAGE_SHIFT; i < nr_pages; i++ ) > + page_array[i] += mmio_size >> PAGE_SHIFT; > + > + /* > + * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. > + * > + * We attempt to allocate 1GB pages if possible. It falls back on 2MB > + * pages if 1GB allocation fails. 4KB pages will be used eventually if > + * both fail. > + * > + * Under 2MB mode, we allocate pages in batches of no more than 8MB to > + * ensure that we can be preempted and hence dom0 remains responsive. > + */ > + rc = xc_domain_populate_physmap_exact( > + xch, dom, 0xa0, 0, 0, &page_array[0x00]); > + cur_pages = 0xc0; > + stat_normal_pages = 0xc0; > + while ( (rc == 0) && (nr_pages > cur_pages) ) > + { > + /* Clip count to maximum 1GB extent. */ > + unsigned long count = nr_pages - cur_pages; > + unsigned long max_pages = SUPERPAGE_1GB_NR_PFNS; > + > + if ( count > max_pages ) > + count = max_pages; > + > + cur_pfn = page_array[cur_pages]; > + > + /* Take care the corner cases of super page tails */ > + if ( ((cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && > + (count > (-cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1))) ) > + count = -cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1); > + else if ( ((count & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) && > + (count > SUPERPAGE_1GB_NR_PFNS) ) > + count &= ~(SUPERPAGE_1GB_NR_PFNS - 1); > + > + /* Attemp to allocate 1GB super page. Because in each pass we only > + * allocate at most 1GB, we don''t have to clip super page boundaries. > + */ > + if ( ((count | cur_pfn) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 && > + /* Check if there exists MMIO hole in the 1GB memory range */ > + !check_mmio_hole(cur_pfn << PAGE_SHIFT, > + SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT, > + mmio_start, mmio_size) ) > + { > + long done; > + unsigned long nr_extents = count >> SUPERPAGE_1GB_SHIFT; > + xen_pfn_t sp_extents[nr_extents]; > + > + for ( i = 0; i < nr_extents; i++ ) > + sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_1GB_SHIFT)]; > + > + done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_1GB_SHIFT, > + pod_mode ? XENMEMF_populate_on_demand : 0, > + sp_extents); > + > + if ( done > 0 ) > + { > + stat_1gb_pages += done; > + done <<= SUPERPAGE_1GB_SHIFT; > + cur_pages += done; > + count -= done; > + } > + } > + > + if ( count != 0 ) > + { > + /* Clip count to maximum 8MB extent. */ > + max_pages = SUPERPAGE_2MB_NR_PFNS * 4; > + if ( count > max_pages ) > + count = max_pages; > + > + /* Clip partial superpage extents to superpage boundaries. */ > + if ( ((cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && > + (count > (-cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1))) ) > + count = -cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1); > + else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) && > + (count > SUPERPAGE_2MB_NR_PFNS) ) > + count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */ > + > + /* Attempt to allocate superpage extents. */ > + if ( ((count | cur_pfn) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 ) > + { > + long done; > + unsigned long nr_extents = count >> SUPERPAGE_2MB_SHIFT; > + xen_pfn_t sp_extents[nr_extents]; > + > + for ( i = 0; i < nr_extents; i++ ) > + sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_2MB_SHIFT)]; > + > + done = xc_domain_populate_physmap(xch, dom, nr_extents, SUPERPAGE_2MB_SHIFT, > + pod_mode ? XENMEMF_populate_on_demand : 0, > + sp_extents); > + > + if ( done > 0 ) > + { > + stat_2mb_pages += done; > + done <<= SUPERPAGE_2MB_SHIFT; > + cur_pages += done; > + count -= done; > + } > + } > + } > + > + /* Fall back to 4kB extents. */ > + if ( count != 0 ) > + { > + rc = xc_domain_populate_physmap_exact( > + xch, dom, count, 0, 0, &page_array[cur_pages]); > + cur_pages += count; > + stat_normal_pages += count; > + } > + } > + > + /* Subtract 0x20 from target_pages for the VGA "hole". Xen will > + * adjust the PoD cache size so that domain tot_pages will be > + * target_pages - 0x20 after this call. */ > + if ( pod_mode ) > + rc = xc_domain_set_pod_target(xch, dom, target_pages - 0x20, > + NULL, NULL, NULL); > + > + if ( rc != 0 ) > + { > + PERROR("Could not allocate memory for HVM guest."); > + goto error_out; > + } > + > + IPRINTF("PHYSICAL MEMORY ALLOCATION:\n" > + " 4KB PAGES: 0x%016lx\n" > + " 2MB PAGES: 0x%016lx\n" > + " 1GB PAGES: 0x%016lx\n", > + stat_normal_pages, stat_2mb_pages, stat_1gb_pages); > + > + if ( loadelfimage(xch, &elf, dom, page_array) != 0 ) > + goto error_out; > + > + if ( (hvm_info_page = xc_map_foreign_range( > + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, > + HVM_INFO_PFN)) == NULL ) > + goto error_out; > + build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size); > + munmap(hvm_info_page, PAGE_SIZE); > + > + /* Allocate and clear special pages. */ > + for ( i = 0; i < NR_SPECIAL_PAGES; i++ ) > + { > + xen_pfn_t pfn = special_pfn(i); > + rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn); > + if ( rc != 0 ) > + { > + PERROR("Could not allocate %d''th special page.", i); > + goto error_out; > + } > + if ( xc_clear_domain_page(xch, dom, special_pfn(i)) ) > + goto error_out; > + } > + > + xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN, > + special_pfn(SPECIALPAGE_XENSTORE)); > + xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN, > + special_pfn(SPECIALPAGE_BUFIOREQ)); > + xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN, > + special_pfn(SPECIALPAGE_IOREQ)); > + xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN, > + special_pfn(SPECIALPAGE_CONSOLE)); > + > + /* > + * Identity-map page table is required for running with CR0.PG=0 when > + * using Intel EPT. Create a 32-bit non-PAE page directory of superpages. > + */ > + if ( (ident_pt = xc_map_foreign_range( > + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, > + special_pfn(SPECIALPAGE_IDENT_PT))) == NULL ) > + goto error_out; > + for ( i = 0; i < PAGE_SIZE / sizeof(*ident_pt); i++ ) > + ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | > + _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE); > + munmap(ident_pt, PAGE_SIZE); > + xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, > + special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); > + > + /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */ > + entry_eip = elf_uval(&elf, elf.ehdr, e_entry); > + if ( entry_eip != 0 ) > + { > + char *page0 = xc_map_foreign_range( > + xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, 0); > + if ( page0 == NULL ) > + goto error_out; > + page0[0] = 0xe9; > + *(uint32_t *)&page0[1] = entry_eip - 5; > + munmap(page0, PAGE_SIZE); > + } > + > + free(page_array); > + return 0; > + > + error_out: > + free(page_array); > + return -1; > +} > + > +/* xc_hvm_build: > + * Create a domain for a virtualized Linux, using files/filenames. > + */ > +int xc_hvm_build(xc_interface *xch, uint32_t domid, > + const struct xc_hvm_build_args *hvm_args) > +{ > + struct xc_hvm_build_args args = *hvm_args; > + void *image; > + unsigned long image_size; > + int sts; > + > + if ( domid == 0 ) > + return -1; > + if ( args.image_file_name == NULL ) > + return -1; > + > + if ( args.mem_target == 0 ) > + args.mem_target = args.mem_size; > + > + if ( args.mmio_size == 0 ) > + args.mmio_size = HVM_BELOW_4G_MMIO_LENGTH; > + > + /* An HVM guest must be initialised with at least 2MB memory. */ > + if ( args.mem_size < (2ull << 20) || args.mem_target < (2ull << 20) ) > + return -1; > + > + image = xc_read_image(xch, args.image_file_name, &image_size); > + if ( image == NULL ) > + return -1; > + > + sts = setup_guest(xch, domid, &args, image, image_size); > + > + free(image); > + > + return sts; > +} > + > +/* xc_hvm_build_target_mem: > + * Create a domain for a pre-ballooned virtualized Linux, using > + * files/filenames. If target < memsize, domain is created with > + * memsize pages marked populate-on-demand, > + * calculating pod cache size based on target. > + * If target == memsize, pages are populated normally. > + */ > +int xc_hvm_build_target_mem(xc_interface *xch, > + uint32_t domid, > + int memsize, > + int target, > + const char *image_name) > +{ > + struct xc_hvm_build_args args = {}; > + > + args.mem_size = (uint64_t)memsize << 20; > + args.mem_target = (uint64_t)target << 20; > + args.image_file_name = image_name; > + > + return xc_hvm_build(xch, domid, &args); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/tools/libxc/xc_nomigrate.c b/tools/libxc/xc_nomigrate.c > new file mode 100644 > index 0000000..e734d73 > --- /dev/null > +++ b/tools/libxc/xc_nomigrate.c > @@ -0,0 +1,53 @@ > +/****************************************************************************** > + * This library 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 of the License. > + * > + * This library 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. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + * > + * Copyright (c) 2011, Citrix Systems > + */ > + > +#include <inttypes.h> > +#include <errno.h> > +#include <xenctrl.h> > +#include <xenguest.h> > + > +int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters, > + uint32_t max_factor, uint32_t flags, > + struct save_callbacks* callbacks, int hvm, > + unsigned long vm_generationid_addr) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, > + unsigned int store_evtchn, unsigned long *store_mfn, > + domid_t store_domid, unsigned int console_evtchn, > + unsigned long *console_mfn, domid_t console_domid, > + unsigned int hvm, unsigned int pae, int superpages, > + int no_incr_generationid, > + unsigned long *vm_generationid_addr) > +{ > + errno = ENOSYS; > + return -1; > +} > + > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > -- > 1.7.2.5 >
Ian Campbell
2012-Mar-14 14:05 UTC
Re: [PATCH v6 5/5] libxl: Introduce libxl__arch_domain_create
On Fri, 2012-03-02 at 16:25 +0000, Stefano Stabellini wrote:> Introduce an arch specific internal domain creation function. At the > moment only x86 provides an implementation. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com>I acked v5 of this with the comment: (I thought I acked this last time) and indeed I acked v4 too. Please do collect acks so I don''t have to waste my time figuring out if I''ve seen something before.> --- > tools/libxl/Makefile | 6 +- > tools/libxl/libxl_arch.h | 22 ++++ > tools/libxl/libxl_create.c | 11 +-- > tools/libxl/libxl_internal.h | 2 - > tools/libxl/libxl_noarch.c | 8 ++ > tools/libxl/libxl_pci.c | 242 --------------------------------------- > tools/libxl/libxl_x86.c | 259 ++++++++++++++++++++++++++++++++++++++++++ > 7 files changed, 294 insertions(+), 256 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 8ccc564..5421e16 100644 > --- a/tools/libxl/Makefile > +++ b/tools/libxl/Makefile > @@ -30,9 +30,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 8417661..2a97e95 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> > @@ -690,15 +691,7 @@ static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config, > } > } > > - if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && > - libxl_defbool_val(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_internal.h b/tools/libxl/libxl_internal.h > index e0a1070..0a6b7df 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -1000,8 +1000,6 @@ _hidden int libxl__error_set(libxl__gc *gc, int code); > _hidden int libxl__file_reference_map(libxl_file_reference *f); > _hidden int libxl__file_reference_unmap(libxl_file_reference *f); > > -_hidden int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config); > - > /* parse the string @s as a sequence of 6 colon separated bytes in to @mac */ > _hidden int libxl__parse_mac(const char *s, libxl_mac mac); > /* compare mac address @a and @b. 0 if the same, -ve if a<b and +ve if a>b */ > 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 4175ac3..bc631f4 100644 > --- a/tools/libxl/libxl_pci.c > +++ b/tools/libxl/libxl_pci.c > @@ -1155,248 +1155,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 (!libxl_defbool_val(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..10d5e5f > --- /dev/null > +++ b/tools/libxl/libxl_x86.c > @@ -0,0 +1,259 @@ > +#include "libxl_internal.h" > +#include "libxl_arch.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 (!libxl_defbool_val(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) > +{ > + int rc = 0; > + if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV && > + d_config->b_info.u.pv.e820_host) { > + rc = libxl__e820_alloc(gc, domid, d_config); > + if (rc) > + LIBXL__LOG_ERRNO(libxl__gc_owner(gc), LIBXL__LOG_ERROR, > + "Failed while collecting E820 with: %d (errno:%d)\n", > + rc, errno); > + } > + return rc; > +} > -- > 1.7.2.5 >
On Fri, 2012-03-02 at 16:24 +0000, Stefano Stabellini wrote:> Hi all, > this patch series allows tools/ to compile on ARM, mostly providing an > empty implementation for all the arch specific functions that are needed. > > > Changes in v6: > > - rebase on 33659563f589 (this is a mercurial id).This was quite a while ago -- is there any hope of this series still applying... ... Computer says no -- "git am" failed on the first patch. Can you rebase please? I''m still expecting that IanJ and not me will pick this up, please CC him on the repost. Ian.> > > Changes in v5: > > - libxc: return -1 and set errno on error; > > - add few missing emacs runes in new files. > > > Changes in v4: > > - rebased on 55a36564fb4f85722c67f16fe508f3ecbd204549; > > - minor compile fixes. > > > > Changes in v3: > > - move libxl_cpuid_policy_list_gen_json to libxl_(no)cpuid.c; > > - rename xc_hvm_build.c to xc_hvm_build_x86.c; > > - remove xc_nohvm, introduce xc_hvm_build_arm.c instead; > > - remove "libxl: do not allocate e820 for non x86 guests."; > > - introduce libxl__arch_domain_create. > > > > Changes in v2: > > - rebased on a22587ae517170a7755d3a88611ae0e2d5bb555e; > > - dropped "arm: arch_dump_shared_mem_info as a no-op" that is already in > xen-unstable; > > - define xen_callback_t as uint64_t; > > - define guest_word_t as uint64_t. > > > > > Stefano Stabellini (5): > arm: compile libxenguest > arm: compile memshr > arm: compile xentrace > arm: compile libxl > libxl: Introduce libxl__arch_domain_create > > tools/libxc/Makefile | 12 +- > tools/libxc/xc_dom_arm.c | 50 +++++ > tools/libxc/xc_hvm_build.c | 463 ---------------------------------------- > tools/libxc/xc_hvm_build_arm.c | 61 ++++++ > tools/libxc/xc_hvm_build_x86.c | 463 ++++++++++++++++++++++++++++++++++++++++ > tools/libxc/xc_nomigrate.c | 53 +++++ > tools/libxl/Makefile | 5 +- > tools/libxl/libxl_arch.h | 22 ++ > tools/libxl/libxl_cpuid.c | 60 +++++ > tools/libxl/libxl_create.c | 11 +- > tools/libxl/libxl_internal.h | 2 - > tools/libxl/libxl_json.c | 60 ----- > tools/libxl/libxl_noarch.c | 8 + > tools/libxl/libxl_nocpuid.c | 8 +- > tools/libxl/libxl_pci.c | 242 --------------------- > tools/libxl/libxl_x86.c | 259 ++++++++++++++++++++++ > tools/memshr/bidir-hash.c | 31 +++ > tools/xentrace/xenctx.c | 12 + > 18 files changed, 1040 insertions(+), 782 deletions(-) > > > Cheers, > > Stefano
This patch series was sent out two months ago and all the patches in the series have been acked twice. However it was never applied. What should I do about it? On Fri, 2 Mar 2012, Stefano Stabellini wrote:> Hi all, > this patch series allows tools/ to compile on ARM, mostly providing an > empty implementation for all the arch specific functions that are needed. > > > Changes in v6: > > - rebase on 33659563f589 (this is a mercurial id). > > > Changes in v5: > > - libxc: return -1 and set errno on error; > > - add few missing emacs runes in new files. > > > Changes in v4: > > - rebased on 55a36564fb4f85722c67f16fe508f3ecbd204549; > > - minor compile fixes. > > > > Changes in v3: > > - move libxl_cpuid_policy_list_gen_json to libxl_(no)cpuid.c; > > - rename xc_hvm_build.c to xc_hvm_build_x86.c; > > - remove xc_nohvm, introduce xc_hvm_build_arm.c instead; > > - remove "libxl: do not allocate e820 for non x86 guests."; > > - introduce libxl__arch_domain_create. > > > > Changes in v2: > > - rebased on a22587ae517170a7755d3a88611ae0e2d5bb555e; > > - dropped "arm: arch_dump_shared_mem_info as a no-op" that is already in > xen-unstable; > > - define xen_callback_t as uint64_t; > > - define guest_word_t as uint64_t. > > > > > Stefano Stabellini (5): > arm: compile libxenguest > arm: compile memshr > arm: compile xentrace > arm: compile libxl > libxl: Introduce libxl__arch_domain_create > > tools/libxc/Makefile | 12 +- > tools/libxc/xc_dom_arm.c | 50 +++++ > tools/libxc/xc_hvm_build.c | 463 ---------------------------------------- > tools/libxc/xc_hvm_build_arm.c | 61 ++++++ > tools/libxc/xc_hvm_build_x86.c | 463 ++++++++++++++++++++++++++++++++++++++++ > tools/libxc/xc_nomigrate.c | 53 +++++ > tools/libxl/Makefile | 5 +- > tools/libxl/libxl_arch.h | 22 ++ > tools/libxl/libxl_cpuid.c | 60 +++++ > tools/libxl/libxl_create.c | 11 +- > tools/libxl/libxl_internal.h | 2 - > tools/libxl/libxl_json.c | 60 ----- > tools/libxl/libxl_noarch.c | 8 + > tools/libxl/libxl_nocpuid.c | 8 +- > tools/libxl/libxl_pci.c | 242 --------------------- > tools/libxl/libxl_x86.c | 259 ++++++++++++++++++++++ > tools/memshr/bidir-hash.c | 31 +++ > tools/xentrace/xenctx.c | 12 + > 18 files changed, 1040 insertions(+), 782 deletions(-) > > > Cheers, > > Stefano >
On Fri, 2012-05-25 at 14:30 +0100, Stefano Stabellini wrote:> This patch series was sent out two months ago and all the patches in the > series have been acked twice. > However it was never applied.I think Ian J and I both thought the other was going to do it :-(> What should I do about it?Earlier on in the freeze I think we could have argued for an exception, but at this point I think that is tough hard call to make, especially since this touches non-arm code (even if mostly code motion or whatever). I''ve been wondering generally what to do about ARM patches during the freeze, I''ve been thinking of maintaining a branch to queue stuff up in with the view to send a pull request when 4.3 opens. The other option is to maintain some sort of common dev tree but accept that it will need rebasing and reposting when 4.3 re-opens. (the primary difference is that in the former I get to resolve all the conflicts and in the latter we all get to do it, guess which I''m leaning toward ;-)) Ian.
On Mon, 28 May 2012, Ian Campbell wrote:> On Fri, 2012-05-25 at 14:30 +0100, Stefano Stabellini wrote: > > This patch series was sent out two months ago and all the patches in the > > series have been acked twice. > > However it was never applied. > > I think Ian J and I both thought the other was going to do it :-( > > > What should I do about it? > > Earlier on in the freeze I think we could have argued for an exception, > but at this point I think that is tough hard call to make, especially > since this touches non-arm code (even if mostly code motion or > whatever). > > I''ve been wondering generally what to do about ARM patches during the > freeze, I''ve been thinking of maintaining a branch to queue stuff up in > with the view to send a pull request when 4.3 opens. The other option is > to maintain some sort of common dev tree but accept that it will need > rebasing and reposting when 4.3 re-opens. (the primary difference is > that in the former I get to resolve all the conflicts and in the latter > we all get to do it, guess which I''m leaning toward ;-))I am OK with a common dev tree, but on what changeset should be based on? I am not very motivated in rebasing these patches on a recent changeset because since they involve a lot of code motion they need complete manual re-doing every time...
On Mon, 2012-05-28 at 10:29 +0100, Ian Campbell wrote:> On Fri, 2012-05-25 at 14:30 +0100, Stefano Stabellini wrote: > > This patch series was sent out two months ago and all the patches in the > > series have been acked twice. > > However it was never applied. > > I think Ian J and I both thought the other was going to do it :-( > > > What should I do about it? > > Earlier on in the freeze I think we could have argued for an exception, > but at this point I think that is tough hard call to make, especially > since this touches non-arm code (even if mostly code motion or > whatever).I spoke to Ian J yesterday and he was of the opinion that ARM patches which are purely code motion from the X86 PoV would still be ok. I''m happy to go with this. Likewise I''m happy to continue to take patches to files which are only compiled on ARM. Ian.