aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxc/ia64')
-rw-r--r--tools/libxc/ia64/Makefile45
-rw-r--r--tools/libxc/ia64/aclinux.h111
-rw-r--r--tools/libxc/ia64/sal.h71
-rw-r--r--tools/libxc/ia64/xc_dom_ia64_util.c192
-rw-r--r--tools/libxc/ia64/xc_dom_ia64_util.h19
-rw-r--r--tools/libxc/ia64/xc_ia64_hvm_build.c537
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_restore.c88
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c71
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);