[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] ia64: nvram setup.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.