diff options
Diffstat (limited to 'tools/libxc/ia64')
-rw-r--r-- | tools/libxc/ia64/Makefile | 45 | ||||
-rw-r--r-- | tools/libxc/ia64/aclinux.h | 111 | ||||
-rw-r--r-- | tools/libxc/ia64/sal.h | 71 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_dom_ia64_util.c | 192 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_dom_ia64_util.h | 19 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_ia64_hvm_build.c | 537 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_ia64_linux_restore.c | 88 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_ia64_linux_save.c | 71 |
8 files changed, 883 insertions, 251 deletions
diff --git a/tools/libxc/ia64/Makefile b/tools/libxc/ia64/Makefile index 974a5c3827..29f7050ad5 100644 --- a/tools/libxc/ia64/Makefile +++ b/tools/libxc/ia64/Makefile @@ -3,3 +3,48 @@ CTRL_SRCS-y += ia64/xc_ia64_stubs.c GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c GUEST_SRCS-y += ia64/xc_ia64_linux_save.c GUEST_SRCS-y += ia64/xc_ia64_linux_restore.c + +GUEST_SRCS-y += ia64/xc_dom_ia64_util.c +DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S +DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE)) +$(DOMFW_SRCS): + ln -sf ../$(XEN_ROOT)/xen/arch/ia64/xen/$(@F) $@ + +# XXX kludge: libxc/Makefile doesn't understand .S. +GUEST_SRCS-y += $(patsubst %.S, %.c, $(DOMFW_SRCS)) +%.o: %.S + $(CC) $(CFLAGS) -c $< -o $@ +%.opic: %.S + $(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $< + + +CFLAGS += -Iia64 + +DOMFW_ASM_HDRS_BASE := bundle.h dom_fw.h dom_fw_common.h dom_fw_domu.h +DOMFW_ASM_HDRS := $(addprefix ia64/asm/, $(DOMFW_ASM_HDRS_BASE)) +$(DOMFW_ASM_HDRS): ia64/asm + ln -sf ../../$(XEN_ROOT)/xen/include/asm-ia64/$(@F) $@ +build: $(DOMFW_ASM_HDR) + +.PHONY: mk-symlinks-acpi mk-symlinks-misc ia64-clean + +IA64_HDR_DIRS := ia64/asm ia64/xen ia64/acpi ia64/acpi/platform +$(IA64_HDR_DIRS): + mkdir -p $@ + +IA64_EMPTY_FILES := ia64/asm/acpi.h ia64/xen/list.h +$(IA64_EMPTY_FILES): $(IA64_HDR_DIRS) + echo "/* automatically created dummy empty header file. */" > $@ + +mk-symlinks-acpi: $(IA64_HDR_DIRS) $(IA64_EMPTY_FILES) $(DOMFW_ASM_HDRS) + ( cd ia64/acpi && ln -sf ../../$(XEN_ROOT)/xen/include/acpi/*.h .) + ( cd ia64/acpi/platform && ln -sf ../../../$(XEN_ROOT)/xen/include/acpi/platform/*.h .) + ( cd ia64/acpi/platform/ && ln -sf ../../aclinux.h .) + ( cd ia64/xen && ln -sf ../../$(XEN_ROOT)/xen/include/xen/acpi.h .) +mk-symlinks-misc: + ( cd ia64/asm && ln -sf ../../$(XEN_ROOT)/xen/include/asm-ia64/linux-xen/asm/kregs.h .) +build: mk-symlinks-acpi mk-symlinks-misc + +clean: ia64-clean +ia64-clean: + rm -rf $(DOMFW_SRCS) $(DOMFW_ASM_HDRS) $(IA64_EMPTY_FILES) $(IA64_HDR_DIRS) diff --git a/tools/libxc/ia64/aclinux.h b/tools/libxc/ia64/aclinux.h new file mode 100644 index 0000000000..4019c7204a --- /dev/null +++ b/tools/libxc/ia64/aclinux.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACLINUX_H__ +#define __ACLINUX_H__ + +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_DO_WHILE_0 + +#if 0 /* def __KERNEL__ */ + +#include <xen/config.h> +#include <xen/string.h> +#include <xen/kernel.h> +#include <xen/ctype.h> +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/div64.h> +#include <asm/acpi.h> + +#define strtoul simple_strtoul + +#define ACPI_MACHINE_WIDTH BITS_PER_LONG + +#else /* !__KERNEL__ */ + +#include <stdarg.h> +#include <string.h> +//#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> + +#if defined(__ia64__) || defined(__x86_64__) +#define ACPI_MACHINE_WIDTH 64 +#define COMPILER_DEPENDENT_INT64 long +#define COMPILER_DEPENDENT_UINT64 unsigned long +#else +#define ACPI_MACHINE_WIDTH 32 +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_USE_NATIVE_DIVIDE +#endif + +typedef int8_t s8; +typedef uint8_t u8; +typedef int16_t s16; +typedef uint16_t u16; +typedef int32_t s32; +typedef uint32_t u32; +typedef int64_t s64; +typedef uint64_t u64; +#define __iomem +#ifdef __ia64__ +#ifdef __cplusplus +#define CPP_ASMLINKAGE extern "C" +#else +#define CPP_ASMLINKAGE +#endif +#define asmlinkage CPP_ASMLINKAGE __attribute__((syscall_linkage)) +#endif +#define CONFIG_ACPI_BOOT 1 + +#define __cdecl +#define ACPI_FLUSH_CPU_CACHE() +#endif /* __KERNEL__ */ + +/* Linux uses GCC */ + +#include "acgcc.h" + +#endif /* __ACLINUX_H__ */ diff --git a/tools/libxc/ia64/sal.h b/tools/libxc/ia64/sal.h new file mode 100644 index 0000000000..741ef6f696 --- /dev/null +++ b/tools/libxc/ia64/sal.h @@ -0,0 +1,71 @@ +#ifndef XC_IA64_SAL_H +#define XC_IA64_SAL_H + +/* + * definitions from + * xen/include/asm-ia64/linux/asm/sal.h + */ + +/* + * The SAL system table is followed by a variable number of variable + * length descriptors. The structure of these descriptors follows + * below. + * The defininition follows SAL specs from July 2000 + */ +struct ia64_sal_systab { + uint8_t signature[4]; /* should be "SST_" */ + uint32_t size; /* size of this table in bytes */ + uint8_t sal_rev_minor; + uint8_t sal_rev_major; + uint16_t entry_count; /* # of entries in variable portion */ + uint8_t checksum; + uint8_t reserved1[7]; + uint8_t sal_a_rev_minor; + uint8_t sal_a_rev_major; + uint8_t sal_b_rev_minor; + uint8_t sal_b_rev_major; + /* oem_id & product_id: terminating NUL is missing if string is exactly 32 bytes long. */ + uint8_t oem_id[32]; + uint8_t product_id[32]; /* ASCII product id */ + uint8_t reserved2[8]; +}; + +enum sal_systab_entry_type { + SAL_DESC_ENTRY_POINT = 0, + SAL_DESC_MEMORY = 1, + SAL_DESC_PLATFORM_FEATURE = 2, + SAL_DESC_TR = 3, + SAL_DESC_PTC = 4, + SAL_DESC_AP_WAKEUP = 5 +}; + +typedef struct ia64_sal_desc_entry_point { + uint8_t type; + uint8_t reserved1[7]; + uint64_t pal_proc; + uint64_t sal_proc; + uint64_t gp; + uint8_t reserved2[16]; +}ia64_sal_desc_entry_point_t; + +#define IA64_SAL_AP_EXTERNAL_INT 0 + +typedef struct ia64_sal_desc_ap_wakeup { + uint8_t type; + uint8_t mechanism; /* 0 == external interrupt */ + uint8_t reserved1[6]; + uint64_t vector; /* interrupt vector in range 0x10-0xff */ +} ia64_sal_desc_ap_wakeup_t ; + +//XXX should move xen_sal_data to arch-ia64.h? +/* These are data in domain memory for SAL emulator. */ +struct xen_sal_data { + /* OS boot rendez vous. */ + unsigned long boot_rdv_ip; + unsigned long boot_rdv_r1; + + /* There are these for EFI_SET_VIRTUAL_ADDRESS_MAP emulation. */ + int efi_virt_mode; /* phys : 0 , virt : 1 */ +}; + +#endif /* XC_IA64_SAL_H */ diff --git a/tools/libxc/ia64/xc_dom_ia64_util.c b/tools/libxc/ia64/xc_dom_ia64_util.c new file mode 100644 index 0000000000..d1d15f405c --- /dev/null +++ b/tools/libxc/ia64/xc_dom_ia64_util.c @@ -0,0 +1,192 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + */ + +#include <assert.h> +#include "xg_private.h" +#include "xc_dom.h" +#include "asm/dom_fw.h" +#include "asm/dom_fw_common.h" +#include "ia64/xc_dom_ia64_util.h" + +uint32_t +xen_ia64_version(struct xc_dom_image *dom) +{ + return xc_version(dom->guest_xc, XENVER_version, NULL); +} + +int +xen_ia64_fpswa_revision(struct xc_dom_image *dom, unsigned int *revision) +{ + int ret; + DECLARE_HYPERCALL; + hypercall.op = __HYPERVISOR_ia64_dom0vp_op; + hypercall.arg[0] = IA64_DOM0VP_fpswa_revision; + hypercall.arg[1] = (unsigned long)revision; + + if (lock_pages(revision, sizeof(*revision)) != 0) { + PERROR("Could not lock memory for xen fpswa hypercall"); + return -1; + } + + ret = do_xen_hypercall(dom->guest_xc, &hypercall); + + unlock_pages(revision, sizeof(*revision)); + + return ret; +} + +int xen_ia64_is_running_on_sim(struct xc_dom_image *dom) +{ + /* + * This is only used by dom_fw_init() as + * "!xen_ia64_is_dom0() || xen_ia64_is_running_on_sim()". + * So this doesn't affect the result. + */ + return 0; +} + +int +xen_ia64_is_dom0(struct xc_dom_image *unused) +{ + /* libxc is for non-dom0 domain builder */ + return 0; +} + +void* +xen_ia64_dom_fw_map(struct xc_dom_image *dom, unsigned long mpaddr) +{ + unsigned long page_size = XC_DOM_PAGE_SIZE(dom); + void* ret; + + ret = xc_map_foreign_range(dom->guest_xc, dom->guest_domid, + page_size, PROT_READ | PROT_WRITE, + mpaddr / page_size); + if (ret != NULL) + ret = (void*)((unsigned long)ret | (mpaddr & (page_size - 1))); + + return ret; +} + +void +xen_ia64_dom_fw_unmap(struct xc_dom_image *dom, void *vaddr) +{ + unsigned long page_size = XC_DOM_PAGE_SIZE(dom); + munmap((void*)((unsigned long)vaddr & ~(page_size - 1)), page_size); +} + +int +xen_ia64_is_vcpu_allocated(struct xc_dom_image *dom, uint32_t vcpu) +{ + // return d->vcpu[vcpu] != NULL; + + int rc; + xc_vcpuinfo_t info; + + rc = xc_vcpu_getinfo(dom->guest_xc, dom->guest_domid, + vcpu, &info); + if (rc == 0) + return 1; + + if (rc != -ESRCH) + PERROR("Could not get vcpu info"); + return 0; +} + +int +xen_ia64_dom_fw_setup(struct xc_dom_image *d, uint64_t brkimm, + unsigned long bp_mpa, unsigned long maxmem) +{ + int rc = 0; + void *imva_hypercall_base = NULL; + struct fw_tables *fw_tables = NULL; + struct fake_acpi_tables *imva = NULL; + struct xen_ia64_boot_param *bp = NULL; + + BUILD_BUG_ON(sizeof(struct fw_tables) > + (FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR)); + + /* Create page for hypercalls. */ + imva_hypercall_base = xen_ia64_dom_fw_map(d, FW_HYPERCALL_BASE_PADDR); + if (imva_hypercall_base == NULL) { + rc = -errno; + goto out; + } + + /* Create page for FW tables. */ + fw_tables = (struct fw_tables*)xen_ia64_dom_fw_map(d, FW_TABLES_BASE_PADDR); + if (fw_tables == NULL) { + rc = -errno; + goto out; + } + memset(fw_tables, 0, FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR); + BUILD_BUG_ON(FW_END_PADDR_MIN != FW_TABLES_END_PADDR_MIN); + fw_tables->fw_tables_size = FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR; + fw_tables->fw_end_paddr = FW_END_PADDR_MIN; + fw_tables->fw_tables_end_paddr = FW_TABLES_END_PADDR_MIN; + fw_tables->num_mds = 0; + + /* Create page for acpi tables. */ + imva = (struct fake_acpi_tables *) + xen_ia64_dom_fw_map(d, FW_ACPI_BASE_PADDR); + if (imva == NULL) { + rc = -errno; + goto out; + } + dom_fw_fake_acpi(d, imva); + + /* Create page for boot_param. */ + bp = xen_ia64_dom_fw_map(d, bp_mpa); + if (bp == NULL) { + rc = -errno; + goto out; + } + rc = dom_fw_init(d, brkimm, bp, fw_tables, + (unsigned long)imva_hypercall_base, maxmem); + BUG_ON(fw_tables->fw_tables_size < sizeof(*fw_tables) + + sizeof(fw_tables->efi_memmap[0]) * fw_tables->num_mds); + + /* clear domain builder internal use member */ + fw_tables->fw_tables_size = 0; + fw_tables->fw_end_paddr = 0; + fw_tables->fw_tables_end_paddr = 0; + fw_tables->num_mds = 0; + + out: + if (imva_hypercall_base != NULL) + xen_ia64_dom_fw_unmap(d, imva_hypercall_base); + if (fw_tables != NULL) + xen_ia64_dom_fw_unmap(d, fw_tables); + if (imva != NULL) + xen_ia64_dom_fw_unmap(d, imva); + if (bp != NULL) + xen_ia64_dom_fw_unmap(d, bp); + + return rc; +} + +/* + * 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/ia64/xc_dom_ia64_util.h b/tools/libxc/ia64/xc_dom_ia64_util.h new file mode 100644 index 0000000000..66dfa41f01 --- /dev/null +++ b/tools/libxc/ia64/xc_dom_ia64_util.h @@ -0,0 +1,19 @@ +#ifndef XC_IA64_DOM_IA64_UTIL_H +#define XC_IA64_DOM_IA64_UTIL_H + +struct xc_dom_image; +uint32_t xen_ia64_version(struct xc_dom_image *dom); +void* xen_ia64_dom_fw_map(struct xc_dom_image *dom, unsigned long mpaddr); +void xen_ia64_dom_fw_unmap(struct xc_dom_image *dom, void *addr); +int xen_ia64_fpswa_revision(struct xc_dom_image *dom, unsigned int *revision); +int xen_ia64_is_vcpu_allocated(struct xc_dom_image *dom, uint32_t vcpu); +int xen_ia64_is_running_on_sim(struct xc_dom_image *dom); +int xen_ia64_is_dom0(struct xc_dom_image *dom); + +int +xen_ia64_dom_fw_setup(struct xc_dom_image *d, uint64_t brkimm, + unsigned long bp_mpa, unsigned long maxmem); +#define efi_systable_init_dom0(tables) assert(0) +#define complete_dom0_memmap(d, tables) ({assert(0);0;}) + +#endif /* XC_IA64_DOM_IA64_UTIL_H */ diff --git a/tools/libxc/ia64/xc_ia64_hvm_build.c b/tools/libxc/ia64/xc_ia64_hvm_build.c index 522ec2d03c..c26055bd5c 100644 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c @@ -1,8 +1,11 @@ +#include <asm/kregs.h> #include "xg_private.h" #include "xenguest.h" #include "xc_private.h" #include "xc_elf.h" +#include "xc_efi.h" #include <stdlib.h> +#include <assert.h> #include <zlib.h> #include "xen/arch-ia64.h" #include <xen/hvm/ioreq.h> @@ -39,11 +42,11 @@ xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value) arg.index = param; arg.value = value; - if (mlock(&arg, sizeof(arg)) != 0) + if (lock_pages(&arg, sizeof(arg)) != 0) return -1; rc = do_xen_hypercall(handle, &hypercall); - safe_munlock(&arg, sizeof(arg)); + unlock_pages(&arg, sizeof(arg)); return rc; } @@ -62,11 +65,11 @@ xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value) arg.domid = dom; arg.index = param; - if (mlock(&arg, sizeof(arg)) != 0) + if (lock_pages(&arg, sizeof(arg)) != 0) return -1; rc = do_xen_hypercall(handle, &hypercall); - safe_munlock(&arg, sizeof(arg)); + unlock_pages(&arg, sizeof(arg)); *value = arg.value; return rc; @@ -122,7 +125,7 @@ typedef enum { HOB_TYPE_PAL_VM_INFO, HOB_TYPE_PAL_VM_PAGE_SIZE, HOB_TYPE_NR_VCPU, - HOB_TYPE_NVRAM, + HOB_TYPE_NVRAM, HOB_TYPE_MAX } hob_type_t; @@ -133,14 +136,14 @@ static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu); static int add_nvram_hob(void* hob_buf, unsigned long nvram_addr); static int build_hob(void* hob_buf, unsigned long hob_buf_size, unsigned long dom_mem_size, unsigned long vcpus, - unsigned long nvram_addr); + unsigned long nvram_addr); static int load_hob(int xc_handle,uint32_t dom, void *hob_buf, unsigned long dom_mem_size); static int xc_ia64_build_hob(int xc_handle, uint32_t dom, unsigned long memsize, unsigned long vcpus, - unsigned long nvram_addr) + unsigned long nvram_addr) { char *hob_buf; @@ -249,7 +252,7 @@ get_hob_size(void* hob_buf) static int build_hob(void* hob_buf, unsigned long hob_buf_size, unsigned long dom_mem_size, unsigned long vcpus, - unsigned long nvram_addr) + unsigned long nvram_addr) { //Init HOB List if (hob_init(hob_buf, hob_buf_size) < 0) { @@ -272,10 +275,10 @@ build_hob(void* hob_buf, unsigned long hob_buf_size, goto err_out; } - if (add_nvram_hob( hob_buf, nvram_addr ) < 0) { - PERROR("Add nvram hob failed, buffer too small"); - goto err_out; - } + if (add_nvram_hob( hob_buf, nvram_addr ) < 0) { + PERROR("Add nvram hob failed, buffer too small"); + goto err_out; + } return 0; @@ -340,7 +343,7 @@ add_vcpus_hob(void* hob_buf, unsigned long vcpus) static int add_nvram_hob(void *hob_buf, unsigned long nvram_addr) { - return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr)); + return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr)); } static const unsigned char config_pal_bus_get_features_data[24] = { @@ -574,49 +577,48 @@ add_pal_hob(void* hob_buf) static uint64_t nvram_init(const char *nvram_path) { - uint64_t fd = 0; - fd = open(nvram_path, O_CREAT|O_RDWR, 0666); + uint64_t fd = 0; + fd = open(nvram_path, O_CREAT|O_RDWR, 0644); - if ( fd < 0 ) - { - PERROR("Nvram open failed at %s. Guest will boot without" - " nvram support!\n", nvram_path); - return -1; - } + if ( fd < 0 ) + { + PERROR("Nvram open failed at %s. Guest will boot without" + " nvram support!\n", nvram_path); + return -1; + } - return VALIDATE_NVRAM_FD(fd); + return VALIDATE_NVRAM_FD(fd); } static int copy_from_nvram_to_GFW(int xc_handle, uint32_t dom, int nvram_fd) { - unsigned int nr_pages = NVRAM_SIZE >> PAGE_SHIFT; - struct stat file_stat; - char buf[NVRAM_SIZE] = {0}; + unsigned int nr_pages = NVRAM_SIZE >> PAGE_SHIFT; + struct stat file_stat; + char buf[NVRAM_SIZE] = {0}; - if ( fstat(nvram_fd, &file_stat) < 0 ) - { - PERROR("Cannot get Nvram file info! Guest will boot without " - "nvram support!\n"); - return -1; - } - - if ( 0 == file_stat.st_size ) - { - DPRINTF("Nvram file create successful!\n"); - return 0; - } - - if ( read(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) - { - PERROR("Load nvram fail. guest will boot without" - " nvram support!\n"); - return -1; - } - - return xc_ia64_copy_to_domain_pages(xc_handle, dom, buf, - NVRAM_START >> PAGE_SHIFT, - nr_pages); + if ( fstat(nvram_fd, &file_stat) < 0 ) + { + PERROR("Cannot get Nvram file info! Guest will boot without " + "nvram support!\n"); + return -1; + } + + if ( 0 == file_stat.st_size ) + { + DPRINTF("Nvram file create successful!\n"); + return 0; + } + + if ( read(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) + { + PERROR("Load nvram fail. guest will boot without" + " nvram support!\n"); + return -1; + } + + return xc_ia64_copy_to_domain_pages(xc_handle, dom, buf, + NVRAM_START >> PAGE_SHIFT, nr_pages); } @@ -628,136 +630,286 @@ copy_from_nvram_to_GFW(int xc_handle, uint32_t dom, int nvram_fd) static int copy_from_GFW_to_nvram(int xc_handle, uint32_t dom, int nvram_fd) { - xen_pfn_t *pfn_list = NULL; - char *tmp_ptr = NULL; - unsigned int nr_pages = 0; - uint64_t addr_from_GFW_4k_align = 0; - uint32_t offset = 0; - uint64_t nvram_base_addr = 0; - char buf[NVRAM_SIZE] = {0}; - int i; + xen_pfn_t *pfn_list = NULL; + char *tmp_ptr = NULL; + unsigned int nr_pages = 0; + uint64_t addr_from_GFW_4k_align = 0; + uint32_t offset = 0; + uint64_t nvram_base_addr = 0; + char buf[NVRAM_SIZE] = {0}; + int i; - - // map one more page - nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT; - pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages); - if ( NULL == pfn_list ) - { - PERROR("Cannot allocate memory for nvram save!\n"); - close(nvram_fd); - return -1; - } - - /* - * GFW allocate memory dynamicly to save nvram data - * and save address of the dynamic memory at NVRAM_START. - * To save nvram data to file, we must get the dynamic - * memory address first. - */ - pfn_list[0] = NVRAM_START >> PAGE_SHIFT; - tmp_ptr = (char *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, - PROT_READ | PROT_WRITE, pfn_list[0]); - - if ( NULL == tmp_ptr ) - { - PERROR("Cannot get nvram data from GFW!\n"); - free(pfn_list); - close(nvram_fd); - return -1; - } - - addr_from_GFW_4k_align = *((uint64_t *)tmp_ptr); - munmap(tmp_ptr, PAGE_SIZE); - - // align address to 16k - offset = addr_from_GFW_4k_align % ( 16 * MEM_K ); - addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset; - for ( i=0; i<nr_pages; i++ ) - pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i; - - tmp_ptr = (char *)xc_map_foreign_batch(xc_handle, dom, - PROT_READ | PROT_WRITE, pfn_list, nr_pages); - if ( NULL == tmp_ptr ) - { - PERROR("Cannot get nvram data from GFW!\n"); - free(pfn_list); - close(nvram_fd); - return -1; - } - - // calculate nvram data base addrees - nvram_base_addr = (uint64_t)(tmp_ptr + offset); - - memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE); - free(pfn_list); - munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE); - - lseek(nvram_fd, 0, SEEK_SET); - if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) - { - PERROR("Save to nvram fail!\n"); - return -1; - } - - close(nvram_fd); - - DPRINTF("Nvram save successful!\n"); - - return 0; + // map one more page + nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT; + pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages); + if ( NULL == pfn_list ) + { + PERROR("Cannot allocate memory for nvram save!\n"); + close(nvram_fd); + return -1; + } + + /* + * GFW allocate memory dynamicly to save nvram data + * and save address of the dynamic memory at NVRAM_START. + * To save nvram data to file, we must get the dynamic + * memory address first. + */ + pfn_list[0] = NVRAM_START >> PAGE_SHIFT; + tmp_ptr = (char *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, pfn_list[0]); + + if ( NULL == tmp_ptr ) + { + PERROR("Cannot get nvram data from GFW!\n"); + free(pfn_list); + close(nvram_fd); + return -1; + } + + addr_from_GFW_4k_align = *((uint64_t *)tmp_ptr); + munmap(tmp_ptr, PAGE_SIZE); + + // align address to 16k + offset = addr_from_GFW_4k_align % ( 16 * MEM_K ); + addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset; + for ( i=0; i<nr_pages; i++ ) + pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i; + + tmp_ptr = (char *)xc_map_foreign_batch(xc_handle, dom, + PROT_READ | PROT_WRITE, pfn_list, nr_pages); + if ( NULL == tmp_ptr ) + { + PERROR("Cannot get nvram data from GFW!\n"); + free(pfn_list); + close(nvram_fd); + return -1; + } + + // calculate nvram data base addrees + nvram_base_addr = (uint64_t)(tmp_ptr + offset); + + memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE); + free(pfn_list); + munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE); + + lseek(nvram_fd, 0, SEEK_SET); + if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) + { + PERROR("Save to nvram fail!\n"); + return -1; + } + + close(nvram_fd); + + DPRINTF("Nvram save successful!\n"); + + return 0; } int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom) { - uint64_t nvram_fd = 0; - xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); + xc_dominfo_t info; + uint64_t nvram_fd = 0; - if ( !IS_VALID_NVRAM_FD(nvram_fd) ) - PERROR("Nvram not be initialized. Nvram save fail!\n"); - else - copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd); + if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 ) + { + PERROR("Could not get info for domain"); + return -1; + } + + if ( !info.hvm ) + return 0; + + xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); + + if ( !IS_VALID_NVRAM_FD(nvram_fd) ) + PERROR("Nvram not initialized. Nvram save failed!\n"); + else + copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd); - // although save to nvram maybe fail, we don't return any error number - // to Xend. This is quite logical because damage of NVRAM on native would - // not block OS's executive path. Return error number will cause an exception - // of Xend and block XenU when it destroy. - return 0; + // although save to nvram maybe fail, we don't return any error number + // to Xend. This is quite logical because damage of NVRAM on native would + // not block OS's executive path. Return error number will cause an + // exception of Xend and block XenU when it destroy. + return 0; } -#define NVRAM_FILE_PATH "/usr/lib/xen/boot/nvram_" +#define NVRAM_DIR "/usr/lib/xen/boot/" +#define NVRAM_FILE_PATH "/usr/lib/xen/boot/nvram_" + int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom) { - int file_path_len = strlen(NVRAM_FILE_PATH); - uint64_t nvram_fd = 0; - char nvram_path[100] = {0}; - - strncpy(nvram_path, NVRAM_FILE_PATH, file_path_len); - if ( file_path_len + strlen(dom_name) + 1 > sizeof(nvram_path) ) - { - PERROR("Nvram file path is too long!\n"); - return -1; - } - strcpy(nvram_path + file_path_len, dom_name); - - nvram_fd = nvram_init(nvram_path); - if ( nvram_fd == (uint64_t)(-1) ) - { - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, 0); - return -1; - } - - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, nvram_fd); - return 0; + int file_path_len = strlen(NVRAM_FILE_PATH); + uint64_t nvram_fd = 0; + char nvram_path[100] = {0}; + struct stat stat_buf; + + if ( stat(NVRAM_DIR, &stat_buf) == -1 ) { + if ( errno != ENOENT ) + { + PERROR("Error stat'ing NVRAM dir %s.", NVRAM_DIR); + return -1; + } + if ( mkdir(NVRAM_DIR, 0755) == -1 ) + { + PERROR("Unable to create NVRAM store directory %s.", NVRAM_DIR); + return -1; + } + } + + if ( !(stat_buf.st_mode & S_IRUSR) || !(stat_buf.st_mode & S_IWUSR) ) + { + errno = EACCES; + PERROR("No R/W permission to NVRAM store directory %s.", NVRAM_DIR); + return -1; + } + + strncpy(nvram_path, NVRAM_FILE_PATH, file_path_len); + if ( file_path_len + strlen(dom_name) + 1 > sizeof(nvram_path) ) + { + PERROR("Nvram file path is too long!\n"); + return -1; + } + strcpy(nvram_path + file_path_len, dom_name); + + nvram_fd = nvram_init(nvram_path); + if ( nvram_fd == (uint64_t)(-1) ) + { + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, 0); + return -1; + } + + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, nvram_fd); + return 0; } #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT) #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT) #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT) + +static void +xc_ia64_setup_md(efi_memory_desc_t *md, + unsigned long start, unsigned long end) +{ + md->type = EFI_CONVENTIONAL_MEMORY; + md->pad = 0; + md->phys_addr = start; + md->virt_addr = 0; + md->num_pages = (end - start) >> EFI_PAGE_SHIFT; + md->attribute = EFI_MEMORY_WB; +} + +static inline unsigned long +min(unsigned long lhs, unsigned long rhs) +{ + return (lhs < rhs)? lhs: rhs; +} + +static int +xc_ia64_setup_memmap_info(int xc_handle, uint32_t dom, + unsigned long dom_memsize, /* in bytes */ + unsigned long *pfns_special_pages, + unsigned long nr_special_pages, + unsigned long memmap_info_pfn, + unsigned long memmap_info_num_pages) +{ + xen_ia64_memmap_info_t* memmap_info; + efi_memory_desc_t *md; + uint64_t nr_mds; + + memmap_info = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE * memmap_info_num_pages, + PROT_READ | PROT_WRITE, + memmap_info_pfn); + if (memmap_info == NULL) { + PERROR("Could not map memmmap_info page.\n"); + return -1; + } + memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages); + + /* + * [0, VGA_IO_START = 0xA0000) + * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB) + * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE) + * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE) + * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE) + * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE) + * [memmap_info_pfn << PAGE_SHIFT, + * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE) + * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB) + * [4GB, ...) + */ + md = (efi_memory_desc_t*)&memmap_info->memdesc; + xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize)); + md++; + if (dom_memsize > (VGA_IO_START + VGA_IO_SIZE)) { + xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE, + min(MMIO_START, dom_memsize)); + md++; + } + xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE); + md++; + xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE); + md++; + xc_ia64_setup_md(md, BUFFER_IO_PAGE_START, + BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE); + md++; + xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START, + BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE); + md++; + xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT, + (memmap_info_pfn << PAGE_SHIFT) + + PAGE_SIZE * memmap_info_num_pages); + md++; + xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE); + md++; + if (dom_memsize > MMIO_START) { + xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + (1 * MEM_G)); + md++; + } + nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc; + + assert(nr_mds <= + (PAGE_SIZE * memmap_info_num_pages - + offsetof(typeof(*memmap_info), memdesc))/sizeof(*md)); + memmap_info->efi_memmap_size = nr_mds * sizeof(*md); + memmap_info->efi_memdesc_size = sizeof(*md); + memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION; + + munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages); + return 0; +} + +/* setup shared_info page */ +static int +xc_ia64_setup_shared_info(int xc_handle, uint32_t dom, + unsigned long shared_info_pfn, + unsigned long memmap_info_pfn, + unsigned long memmap_info_num_pages) +{ + shared_info_t *shared_info; + + shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, + shared_info_pfn); + if (shared_info == NULL) { + PERROR("Could not map shared_info"); + return -1; + } + memset(shared_info, 0, sizeof(*shared_info)); + shared_info->arch.memmap_info_num_pages = memmap_info_num_pages; + shared_info->arch.memmap_info_pfn = memmap_info_pfn; + munmap(shared_info, PAGE_SIZE); + return 0; +} + /* * In this function, we will allocate memory and build P2M/M2P table for VTI * guest. Frist, a pfn list will be initialized discontiguous, normal memory - * begins with 0, GFW memory and other three pages at their place defined in + * begins with 0, GFW memory and other five pages at their place defined in * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called - * three times, to set parameter 'extent_order' to different value, this is + * five times, to set parameter 'extent_order' to different value, this is * convenient to allocate discontiguous memory with different size. */ static int @@ -771,7 +923,10 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, unsigned long dom_memsize = memsize << 20; unsigned long nr_pages = memsize << (20 - PAGE_SHIFT); unsigned long vcpus; - unsigned long nvram_start = NVRAM_START, nvram_fd = 0; + unsigned long nr_special_pages; + unsigned long memmap_info_pfn; + unsigned long memmap_info_num_pages; + unsigned long nvram_start = NVRAM_START, nvram_fd = 0; int rc; long i; DECLARE_DOMCTL; @@ -813,7 +968,7 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, goto error_out; } - // We allocate additional pfn for GFW and other three pages, so + // We allocate additional pfn for GFW and other five pages, so // the pfn_list is not contiguous. Due to this we must support // old interface xc_ia64_get_pfn_list(). for (i = 0; i < GFW_PAGES; i++) @@ -826,12 +981,22 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, goto error_out; } - pfn_list[0] = IO_PAGE_START >> PAGE_SHIFT; - pfn_list[1] = STORE_PAGE_START >> PAGE_SHIFT; - pfn_list[2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; - pfn_list[3] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT; - - rc = xc_domain_memory_populate_physmap(xc_handle, dom, 4, + nr_special_pages = 0; + pfn_list[nr_special_pages] = IO_PAGE_START >> PAGE_SHIFT; + nr_special_pages++; + pfn_list[nr_special_pages] = STORE_PAGE_START >> PAGE_SHIFT; + nr_special_pages++; + pfn_list[nr_special_pages] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; + nr_special_pages++; + pfn_list[nr_special_pages] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT; + + memmap_info_pfn = pfn_list[nr_special_pages] + 1; + memmap_info_num_pages = 1; + nr_special_pages++; + pfn_list[nr_special_pages] = memmap_info_pfn; + nr_special_pages++; + + rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_special_pages, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate IO page or store page or buffer io page.\n"); @@ -861,15 +1026,26 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, goto error_out; } - xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); - if ( !IS_VALID_NVRAM_FD(nvram_fd) ) - nvram_start = 0; - else - if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) - { - nvram_start = 0; - close(nvram_fd); - } + if (xc_ia64_setup_memmap_info(xc_handle, dom, dom_memsize, + pfn_list, nr_special_pages, + memmap_info_pfn, memmap_info_num_pages)) { + PERROR("Could not build memmap info\n"); + goto error_out; + } + if (xc_ia64_setup_shared_info(xc_handle, dom, + domctl.u.getdomaininfo.shared_info_frame, + memmap_info_pfn, memmap_info_num_pages)) { + PERROR("Could not setup shared_info\n"); + goto error_out; + } + + xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); + if ( !IS_VALID_NVRAM_FD(nvram_fd) ) + nvram_start = 0; + else if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) { + nvram_start = 0; + close(nvram_fd); + } vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1; @@ -932,8 +1108,8 @@ xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name) image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK; - if (mlock(&st_ctxt, sizeof(st_ctxt))) { - PERROR("Unable to mlock ctxt"); + if (lock_pages(&st_ctxt, sizeof(st_ctxt))) { + PERROR("Unable to lock_pages ctxt"); return 1; } @@ -948,6 +1124,11 @@ xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name) free(image); ctxt->regs.ip = 0x80000000ffffffb0UL; + ctxt->regs.ar.fpsr = xc_ia64_fpsr_default(); + ctxt->regs.cr.isr = 1UL << 63; + ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN; + ctxt->regs.cr.dcr = 0; + ctxt->regs.cr.pta = 15 << 2; memset(&launch_domctl, 0, sizeof(launch_domctl)); @@ -957,10 +1138,12 @@ xc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name) launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; rc = do_domctl(xc_handle, &launch_domctl); + unlock_pages(&st_ctxt, sizeof(st_ctxt)); return rc; error_out: free(image); + unlock_pages(&st_ctxt, sizeof(st_ctxt)); return -1; } diff --git a/tools/libxc/ia64/xc_ia64_linux_restore.c b/tools/libxc/ia64/xc_ia64_linux_restore.c index de5348baf8..26a39715c0 100644 --- a/tools/libxc/ia64/xc_ia64_linux_restore.c +++ b/tools/libxc/ia64/xc_ia64_linux_restore.c @@ -47,12 +47,13 @@ read_page(int xc_handle, int io_fd, uint32_t dom, unsigned long pfn) mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, pfn); if (mem == NULL) { - ERROR("cannot map page"); - return -1; + ERROR("cannot map page"); + return -1; } if (!read_exact(io_fd, mem, PAGE_SIZE)) { - ERROR("Error when reading from state file (5)"); - return -1; + ERROR("Error when reading from state file (5)"); + munmap(mem, PAGE_SIZE); + return -1; } munmap(mem, PAGE_SIZE); return 0; @@ -98,17 +99,17 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, DPRINTF("xc_linux_restore start: p2m_size = %lx\n", p2m_size); if (!read_exact(io_fd, &ver, sizeof(unsigned long))) { - ERROR("Error when reading version"); - goto out; + ERROR("Error when reading version"); + goto out; } if (ver != 1) { - ERROR("version of save doesn't match"); - goto out; + ERROR("version of save doesn't match"); + goto out; } - if (mlock(&ctxt, sizeof(ctxt))) { + if (lock_pages(&ctxt, sizeof(ctxt))) { /* needed for build domctl, but might as well do early */ - ERROR("Unable to mlock ctxt"); + ERROR("Unable to lock_pages ctxt"); return 1; } @@ -139,9 +140,7 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, /* Build firmware (will be overwritten). */ domctl.domain = (domid_t)dom; domctl.u.arch_setup.flags &= ~XEN_DOMAINSETUP_query; - domctl.u.arch_setup.bp = ((p2m_size - 3) << PAGE_SHIFT) - + sizeof (start_info_t); - domctl.u.arch_setup.maxmem = (p2m_size - 3) << PAGE_SHIFT; + domctl.u.arch_setup.bp = 0; /* indicate domain restore */ domctl.cmd = XEN_DOMCTL_arch_setup; if (xc_domctl(xc_handle, &domctl)) @@ -163,11 +162,11 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, ERROR("Error when reading batch size"); goto out; } - if (gmfn == INVALID_MFN) - break; + if (gmfn == INVALID_MFN) + break; - if (read_page(xc_handle, io_fd, dom, gmfn) < 0) - goto out; + if (read_page(xc_handle, io_fd, dom, gmfn) < 0) + goto out; } DPRINTF("Received all pages\n"); @@ -194,11 +193,11 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, goto out; } - DPRINTF ("Try to free %u pages\n", count); + DPRINTF ("Try to free %u pages\n", count); for (i = 0; i < count; i++) { - volatile unsigned long pfn; + volatile unsigned long pfn; struct xen_memory_reservation reservation = { .nr_extents = 1, @@ -206,9 +205,9 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, .domid = dom }; set_xen_guest_handle(reservation.extent_start, - (unsigned long *)&pfn); + (unsigned long *)&pfn); - pfn = pfntab[i]; + pfn = pfntab[i]; rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation); if (rc != 1) { @@ -217,7 +216,7 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, } } - DPRINTF("Decreased reservation by %d pages\n", count); + DPRINTF("Decreased reservation by %d pages\n", count); } @@ -228,37 +227,27 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt.regs.ip, ctxt.regs.b[0]); - /* First to initialize. */ - domctl.cmd = XEN_DOMCTL_setvcpucontext; - domctl.domain = (domid_t)dom; - domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt); - if (xc_domctl(xc_handle, &domctl) != 0) { - ERROR("Couldn't set vcpu context"); - goto out; - } - - /* Second to set registers... */ + /* Initialize and set registers. */ ctxt.flags = VGCF_EXTRA_REGS; domctl.cmd = XEN_DOMCTL_setvcpucontext; domctl.domain = (domid_t)dom; domctl.u.vcpucontext.vcpu = 0; set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt); if (xc_domctl(xc_handle, &domctl) != 0) { - ERROR("Couldn't set vcpu context"); - goto out; + ERROR("Couldn't set vcpu context"); + goto out; } /* Just a check. */ if (xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, &ctxt)) { ERROR("Could not get vcpu context"); - goto out; + goto out; } /* Then get privreg page. */ if (read_page(xc_handle, io_fd, dom, ctxt.privregs_pfn) < 0) { - ERROR("Could not read vcpu privregs"); - goto out; + ERROR("Could not read vcpu privregs"); + goto out; } /* Read shared info. */ @@ -266,11 +255,12 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, PROT_READ|PROT_WRITE, shared_info_frame); if (shared_info == NULL) { ERROR("cannot map page"); - goto out; + goto out; } if (!read_exact(io_fd, shared_info, PAGE_SIZE)) { ERROR("Error when reading shared_info page"); - goto out; + munmap(shared_info, PAGE_SIZE); + goto out; } /* clear any pending events and the selector */ @@ -286,6 +276,10 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, /* Uncanonicalise the suspend-record frame number and poke resume rec. */ start_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, gmfn); + if (start_info == NULL) { + ERROR("cannot map start_info page"); + goto out; + } start_info->nr_pages = p2m_size; start_info->shared_info = shared_info_frame << PAGE_SHIFT; start_info->flags = 0; @@ -316,9 +310,21 @@ xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, xc_domain_destroy(xc_handle, dom); if (page_array != NULL) - free(page_array); + free(page_array); + + unlock_pages(&ctxt, sizeof(ctxt)); DPRINTF("Restore exit with rc=%d\n", rc); return rc; } + +/* + * 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/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c index eb8dd64bfb..f43f5b86ac 100644 --- a/tools/libxc/ia64/xc_ia64_linux_save.c +++ b/tools/libxc/ia64/xc_ia64_linux_save.c @@ -22,8 +22,8 @@ ** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too. ** */ -#define DEF_MAX_ITERS (4 - 1) /* limit us to 4 times round loop */ -#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */ +#define DEF_MAX_ITERS (4 - 1) /* limit us to 4 times round loop */ +#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */ /* ** During (live) save/migrate, we maintain a number of bitmaps to track @@ -37,24 +37,21 @@ #define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG) -static inline int test_bit (int nr, volatile void * addr) +static inline int test_bit(int nr, volatile void * addr) { return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1; } -static inline void clear_bit (int nr, volatile void * addr) +static inline void clear_bit(int nr, volatile void * addr) { BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr)); } -static inline void set_bit ( int nr, volatile void * addr) +static inline void set_bit(int nr, volatile void * addr) { BITMAP_ENTRY(nr, addr) |= (1UL << BITMAP_SHIFT(nr)); } -/* total number of pages used by the current guest */ -static unsigned long max_pfn; - static int xc_ia64_shadow_control(int xc_handle, uint32_t domid, unsigned int sop, @@ -67,7 +64,7 @@ static int xc_ia64_shadow_control(int xc_handle, unsigned char *bmap = (unsigned char *)dirty_bitmap; unsigned long bmap_bytes = ((pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG - 1)) / 8; - unsigned int bmap_pages = (bmap_bytes + PAGE_SIZE - 1) / PAGE_SIZE; + unsigned int bmap_pages = (bmap_bytes + PAGE_SIZE - 1) / PAGE_SIZE; /* Touch the page so that it is in the TC. FIXME: use a more reliable method. */ @@ -168,6 +165,9 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Number of pages sent (live only). */ unsigned int total_sent; + /* total number of pages used by the current guest */ + unsigned long p2m_size; + /* Size of the shadow bitmap (live only). */ unsigned int bitmap_size = 0; @@ -182,7 +182,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, char *mem; if (debug) - fprintf (stderr, "xc_linux_save (ia64): started dom=%d\n", dom); + fprintf(stderr, "xc_linux_save (ia64): started dom=%d\n", dom); /* If no explicit control parameters given, use defaults */ if (!max_iters) @@ -216,17 +216,17 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - max_pfn = info.max_memkb >> (PAGE_SHIFT - 10); + p2m_size = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom); - page_array = malloc(max_pfn * sizeof(unsigned long)); + page_array = malloc(p2m_size * sizeof(unsigned long)); if (page_array == NULL) { ERROR("Could not allocate memory"); goto out; } /* This is expected by xm restore. */ - if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { - ERROR("write: max_pfn"); + if (!write_exact(io_fd, &p2m_size, sizeof(unsigned long))) { + ERROR("write: p2m_size"); goto out; } @@ -269,7 +269,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, last_iter = 0; - bitmap_size = ((max_pfn + BITS_PER_LONG-1) & ~(BITS_PER_LONG-1)) / 8; + bitmap_size = ((p2m_size + BITS_PER_LONG-1) & ~(BITS_PER_LONG-1)) / 8; to_send = malloc(bitmap_size); to_skip = malloc(bitmap_size); @@ -281,15 +281,15 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Initially all the pages must be sent. */ memset(to_send, 0xff, bitmap_size); - if (mlock(to_send, bitmap_size)) { - ERROR("Unable to mlock to_send"); + if (lock_pages(to_send, bitmap_size)) { + ERROR("Unable to lock_pages to_send"); goto out; } - if (mlock(to_skip, bitmap_size)) { - ERROR("Unable to mlock to_skip"); + if (lock_pages(to_skip, bitmap_size)) { + ERROR("Unable to lock_pages to_skip"); goto out; } - + } else { /* This is a non-live suspend. Issue the call back to get the @@ -304,7 +304,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } - sent_last_iter = max_pfn; + sent_last_iter = p2m_size; total_sent = 0; for (iter = 1; ; iter++) { @@ -316,7 +316,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Get the pfn list, as it may change. */ if (xc_ia64_get_pfn_list(xc_handle, dom, page_array, - 0, max_pfn) != max_pfn) { + 0, p2m_size) != p2m_size) { ERROR("Could not get the page frame list"); goto out; } @@ -327,14 +327,14 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if (!last_iter) { if (xc_ia64_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, - to_skip, max_pfn, NULL) != max_pfn) { + to_skip, p2m_size, NULL) != p2m_size) { ERROR("Error peeking shadow bitmap"); goto out; } } /* Start writing out the saved-domain record. */ - for (N = 0; N < max_pfn; N++) { + for (N = 0; N < p2m_size; N++) { if (page_array[N] == INVALID_MFN) continue; if (!last_iter) { @@ -346,7 +346,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if (debug) fprintf(stderr, "xc_linux_save: page %lx (%lu/%lu)\n", - page_array[N], N, max_pfn); + page_array[N], N, p2m_size); mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, N); @@ -360,12 +360,14 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } if (!write_exact(io_fd, &N, sizeof(N))) { - ERROR("write: max_pfn"); + ERROR("write: p2m_size"); + munmap(mem, PAGE_SIZE); goto out; } if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) { ERROR("Error when writing to state file (5)"); + munmap(mem, PAGE_SIZE); goto out; } munmap(mem, PAGE_SIZE); @@ -382,7 +384,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if (live) { if ( /* ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) || */ (iter >= max_iters) || (sent_this_iter+skip_this_iter < 50) || - (total_sent > max_pfn*max_factor)) { + (total_sent > p2m_size*max_factor)) { DPRINTF("Start last iteration\n"); last_iter = 1; @@ -395,7 +397,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Pages to be sent are pages which were dirty. */ if (xc_ia64_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_CLEAN, - to_send, max_pfn, NULL ) != max_pfn) { + to_send, p2m_size, NULL ) != p2m_size) { ERROR("Error flushing shadow PT"); goto out; } @@ -407,7 +409,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } - fprintf (stderr, "All memory is saved\n"); + fprintf(stderr, "All memory is saved\n"); /* terminate */ { @@ -423,7 +425,7 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned int i,j; unsigned long pfntab[1024]; - for (i = 0, j = 0; i < max_pfn; i++) { + for (i = 0, j = 0; i < p2m_size; i++) { if (page_array[i] == INVALID_MFN) j++; } @@ -433,13 +435,13 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - for (i = 0, j = 0; i < max_pfn; ) { + for (i = 0, j = 0; i < p2m_size; ) { if (page_array[i] == INVALID_MFN) pfntab[j++] = i; i++; - if (j == 1024 || i == max_pfn) { + if (j == 1024 || i == p2m_size) { if (!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) { ERROR("Error when writing to state file (6b)"); goto out; @@ -470,9 +472,10 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) { ERROR("Error when writing privreg to state file (5)"); + munmap(mem, PAGE_SIZE); goto out; } - munmap(mem, PAGE_SIZE); + munmap(mem, PAGE_SIZE); if (!write_exact(io_fd, live_shinfo, PAGE_SIZE)) { ERROR("Error when writing to state file (1)"); @@ -492,7 +495,9 @@ xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } free(page_array); + unlock_pages(to_send, bitmap_size); free(to_send); + unlock_pages(to_skip, bitmap_size); free(to_skip); if (live_shinfo) munmap(live_shinfo, PAGE_SIZE); |