# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1179996843 -3600
# Node ID 17f6163ae930c007d13abc1e3dbc06a624fb5a21
# Parent 1e097a48db065457e84647641097b7b55f86d9b1
ia64: nvram setup.
From: "Zhang, Xing Z" <xing.z.zhang@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
tools/libxc/ia64/xc_ia64_hvm_build.c | 214 +++++++++++++++++++++++++++++++-
tools/libxc/xenctrl.h | 9 +
tools/python/xen/lowlevel/xc/xc.c | 48 ++++++-
tools/python/xen/xend/XendDomainInfo.py | 1
tools/python/xen/xend/image.py | 4
xen/include/public/arch-ia64.h | 5
xen/include/public/hvm/params.h | 5
7 files changed, 275 insertions(+), 11 deletions(-)
diff -r 1e097a48db06 -r 17f6163ae930 tools/libxc/ia64/xc_ia64_hvm_build.c
--- a/tools/libxc/ia64/xc_ia64_hvm_build.c Thu May 24 09:15:58 2007 +0100
+++ b/tools/libxc/ia64/xc_ia64_hvm_build.c Thu May 24 09:54:03 2007 +0100
@@ -122,6 +122,7 @@ typedef enum {
HOB_TYPE_PAL_VM_INFO,
HOB_TYPE_PAL_VM_PAGE_SIZE,
HOB_TYPE_NR_VCPU,
+ HOB_TYPE_NVRAM,
HOB_TYPE_MAX
} hob_type_t;
@@ -129,14 +130,17 @@ static int add_pal_hob(void* hob_buf);
static int add_pal_hob(void* hob_buf);
static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
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 dom_mem_size, unsigned long vcpus,
+ 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 memsize, unsigned long vcpus,
+ unsigned long nvram_addr)
{
char *hob_buf;
@@ -146,7 +150,7 @@ xc_ia64_build_hob(int xc_handle, uint32_
return -1;
}
- if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) < 0) {
+ if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) {
free(hob_buf);
PERROR("Could not build hob");
return -1;
@@ -244,7 +248,8 @@ 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 dom_mem_size, unsigned long vcpus,
+ unsigned long nvram_addr)
{
//Init HOB List
if (hob_init(hob_buf, hob_buf_size) < 0) {
@@ -266,6 +271,11 @@ build_hob(void* hob_buf, unsigned long h
PERROR("Add PAL 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;
@@ -325,6 +335,12 @@ add_vcpus_hob(void* hob_buf, unsigned lo
add_vcpus_hob(void* hob_buf, unsigned long vcpus)
{
return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(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));
}
static const unsigned char config_pal_bus_get_features_data[24] = {
@@ -551,6 +567,184 @@ add_pal_hob(void* hob_buf)
return 0;
}
+// The most significant bit of nvram file descriptor:
+// 1: valid; 0: invalid
+#define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x)
+#define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1))
+static uint64_t
+nvram_init(const char *nvram_path)
+{
+ uint64_t fd = 0;
+ fd = open(nvram_path, O_CREAT|O_RDWR, 0666);
+
+ 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);
+}
+
+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};
+
+ 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);
+}
+
+
+/*
+ * GFW use 4k page. when doing foreign map, we should 16k align
+ * the address and map one more page to guarantee all 64k nvram data
+ * can be got.
+ */
+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;
+
+
+ // 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);
+
+ if ( !IS_VALID_NVRAM_FD(nvram_fd) )
+ {
+ PERROR("Nvram not be initialized. Nvram save fail!\n");
+ return -1;
+ }
+ return copy_from_GFW_to_nvram(xc_handle, dom, (int)nvram_fd);
+}
+
+#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;
+}
+
#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)
@@ -573,6 +767,7 @@ setup_guest(int xc_handle, uint32_t dom,
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;
int rc;
long i;
DECLARE_DOMCTL;
@@ -627,7 +822,7 @@ setup_guest(int xc_handle, uint32_t dom,
goto error_out;
}
- pfn_list[0] = IO_PAGE_START >> PAGE_SHIFT;
+ 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;
@@ -662,10 +857,17 @@ setup_guest(int xc_handle, uint32_t dom,
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;
+
vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1;
// Hand-off state passed to guest firmware
- if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus) < 0) {
+ if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus, nvram_start) <
0) {
PERROR("Could not build hob\n");
goto error_out;
}
diff -r 1e097a48db06 -r 17f6163ae930 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu May 24 09:15:58 2007 +0100
+++ b/tools/libxc/xenctrl.h Thu May 24 09:54:03 2007 +0100
@@ -847,4 +847,11 @@ int xc_alloc_real_mode_area(int xc_handl
int xc_alloc_real_mode_area(int xc_handle,
uint32_t domid,
unsigned int log);
-#endif
+
+/* IA64 specific, nvram save */
+int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom);
+
+/* IA64 specific, nvram init */
+int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom);
+
+#endif /* XENCTRL_H */
diff -r 1e097a48db06 -r 17f6163ae930 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 24 09:15:58 2007 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu May 24 09:54:03 2007 +0100
@@ -54,9 +54,9 @@ static PyObject *pyxc_error_to_exception
return PyErr_SetFromErrno(xc_error_obj);
if ( err->message[0] != '\0' )
- pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
+ pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
else
- pyerr = Py_BuildValue("(is)", err->code, desc);
+ pyerr = Py_BuildValue("(is)", err->code, desc);
xc_clear_last_error();
@@ -161,6 +161,16 @@ static PyObject *pyxc_domain_unpause(XcO
static PyObject *pyxc_domain_unpause(XcObject *self, PyObject *args)
{
return dom_op(self, args, xc_domain_unpause);
+}
+
+static PyObject *pyxc_domain_destroy_hook(XcObject *self, PyObject *args)
+{
+#ifdef __ia64__
+ dom_op(self, args, xc_ia64_save_to_nvram);
+#endif
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
@@ -426,7 +436,7 @@ static PyObject *pyxc_linux_build(XcObje
xc_dom_loginit();
if (!(dom = xc_dom_allocate(cmdline, features)))
- return pyxc_error_to_exception();
+ return pyxc_error_to_exception();
if ( xc_dom_linux_build(self->xc_handle, dom, domid, mem_mb, image,
ramdisk, flags, store_evtchn, &store_mfn,
@@ -497,6 +507,23 @@ static PyObject *pyxc_get_hvm_param(XcOb
return Py_BuildValue("i", value);
}
+
+#ifdef __ia64__
+static PyObject *pyxc_nvram_init(XcObject *self,
+ PyObject *args)
+{
+ char *dom_name;
+ uint32_t dom;
+
+ if ( !PyArg_ParseTuple(args, "si", &dom_name, &dom) )
+ return NULL;
+
+ xc_ia64_nvram_init(self->xc_handle, dom_name, dom);
+
+ Py_INCREF(zero);
+ return zero;
+}
+#endif /* __ia64__ */
static PyObject *pyxc_hvm_build(XcObject *self,
PyObject *args,
@@ -1153,6 +1180,13 @@ static PyMethodDef pyxc_methods[] = {
(PyCFunction)pyxc_domain_destroy,
METH_VARARGS, "\n"
"Destroy a domain.\n"
+ " dom [int]: Identifier of domain to be destroyed.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_destroy_hook",
+ (PyCFunction)pyxc_domain_destroy_hook,
+ METH_VARARGS, "\n"
+ "Add a hook for arch stuff before destroy a domain.\n"
" dom [int]: Identifier of domain to be destroyed.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
@@ -1397,7 +1431,13 @@ static PyMethodDef pyxc_methods[] = {
" dom [int]: Identifier of domain.\n"
" mem_kb [long]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
-
+#ifdef __ia64__
+ { "nvram_init",
+ (PyCFunction)pyxc_nvram_init,
+ METH_VARARGS, "\n"
+ "Init nvram in IA64 platform\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+#endif /* __ia64__ */
{ "domain_ioport_permission",
(PyCFunction)pyxc_domain_ioport_permission,
METH_VARARGS | METH_KEYWORDS, "\n"
diff -r 1e097a48db06 -r 17f6163ae930 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu May 24 09:15:58 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu May 24 09:54:03 2007 +0100
@@ -1666,6 +1666,7 @@ class XendDomainInfo:
self._cleanupVm()
if self.dompath is not None:
+ xc.domain_destroy_hook(self.domid)
self.destroyDomain()
self._cleanup_phantom_devs(paths)
diff -r 1e097a48db06 -r 17f6163ae930 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu May 24 09:15:58 2007 +0100
+++ b/tools/python/xen/xend/image.py Thu May 24 09:54:03 2007 +0100
@@ -469,6 +469,10 @@ class HVMImageHandler(ImageHandler):
class IA64_HVM_ImageHandler(HVMImageHandler):
+ def buildDomain(self):
+ xc.nvram_init(self.vm.getName(), self.vm.getDomid())
+ return HVMImageHandler.buildDomain(self)
+
def getRequiredAvailableMemory(self, mem_kb):
page_kb = 16
# ROM size for guest firmware, ioreq page, pio page and xenstore page
diff -r 1e097a48db06 -r 17f6163ae930 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Thu May 24 09:15:58 2007 +0100
+++ b/xen/include/public/arch-ia64.h Thu May 24 09:54:03 2007 +0100
@@ -77,6 +77,7 @@ typedef unsigned long xen_ulong_t;
#define MEM_G (1UL << 30)
#define MEM_M (1UL << 20)
+#define MEM_K (1UL << 10)
#define MMIO_START (3 * MEM_G)
#define MMIO_SIZE (512 * MEM_M)
@@ -107,6 +108,10 @@ typedef unsigned long xen_ulong_t;
#define GFW_START (4*MEM_G -16*MEM_M)
#define GFW_SIZE (16*MEM_M)
+
+/* Nvram belongs to GFW memory space */
+#define NVRAM_SIZE (MEM_K * 64)
+#define NVRAM_START (GFW_START + 10 * MEM_M)
struct pt_fpreg {
union {
diff -r 1e097a48db06 -r 17f6163ae930 xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h Thu May 24 09:15:58 2007 +0100
+++ b/xen/include/public/hvm/params.h Thu May 24 09:54:03 2007 +0100
@@ -50,6 +50,11 @@
#define HVM_PARAM_BUFIOREQ_PFN 6
+#ifdef __ia64__
+#define HVM_PARAM_NVRAM_FD 7
+#define HVM_NR_PARAMS 8
+#else
#define HVM_NR_PARAMS 7
+#endif
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|