WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC] [PATCH 1 of 4] [PATCH] Move flat device tree construction from

To: xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
Subject: [XenPPC] [PATCH 1 of 4] [PATCH] Move flat device tree construction from python to libxc for xc_linux_build()
From: Ryan Harper <ryanh@xxxxxxxxxx>
Date: Fri, 19 Jan 2007 15:48:23 -0500
Delivery-date: Fri, 19 Jan 2007 13:48:13 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1169243302@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
7 files changed, 699 insertions(+), 113 deletions(-)
tools/libxc/powerpc64/Makefile         |    1 
tools/libxc/powerpc64/mk_flatdevtree.c |  605 ++++++++++++++++++++++++++++++++
tools/libxc/powerpc64/mk_flatdevtree.h |   42 ++
tools/libxc/powerpc64/xc_linux_build.c |  143 ++-----
tools/libxc/xenguest.h                 |    4 
tools/python/xen/lowlevel/xc/xc.c      |   12 
tools/python/xen/xend/image.py         |    5 


# HG changeset patch
# User Ryan Harper <ryanh@xxxxxxxxxx>
# Date 1169241710 21600
# Node ID 5a846b0c810cd24e5390a4dd2bdda8690d48c808
# Parent  c16586000525f9d9dfbbe336d9d458dd08b44a0e
[PATCH] Move flat device tree construction from python to libxc for 
xc_linux_build().

Signed-off-by: Ryan Harper <ryanh@xxxxxxxxxx>

diff -r c16586000525 -r 5a846b0c810c tools/libxc/powerpc64/Makefile
--- a/tools/libxc/powerpc64/Makefile    Wed Jan 17 19:37:20 2007 -0500
+++ b/tools/libxc/powerpc64/Makefile    Fri Jan 19 15:21:50 2007 -0600
@@ -1,4 +1,5 @@ GUEST_SRCS-y += powerpc64/flatdevtree.c
 GUEST_SRCS-y += powerpc64/flatdevtree.c
+GUEST_SRCS-y += powerpc64/mk_flatdevtree.c
 GUEST_SRCS-y += powerpc64/xc_linux_build.c
 GUEST_SRCS-y += powerpc64/xc_prose_build.c
 GUEST_SRCS-y += powerpc64/utils.c
diff -r c16586000525 -r 5a846b0c810c tools/libxc/powerpc64/xc_linux_build.c
--- a/tools/libxc/powerpc64/xc_linux_build.c    Wed Jan 17 19:37:20 2007 -0500
+++ b/tools/libxc/powerpc64/xc_linux_build.c    Fri Jan 19 15:21:50 2007 -0600
@@ -13,9 +13,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * Copyright (C) IBM Corporation 2006
+ * Copyright IBM Corporation 2006, 2007
  *
  * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ *          Ryan Harper <ryanh@xxxxxxxxxx>
  */
 
 #include <stdio.h>
@@ -36,6 +37,7 @@
 #include "flatdevtree_env.h"
 #include "flatdevtree.h"
 #include "utils.h"
+#include "mk_flatdevtree.h"
 
 #define INITRD_ADDR (24UL << 20)
 #define DEVTREE_ADDR (16UL << 20)
@@ -78,85 +80,6 @@ static int init_boot_vcpu(
     return rc;
 }
 
-static int load_devtree(
-    int xc_handle,
-    int domid,
-    xen_pfn_t *page_array,
-    void *devtree,
-    unsigned long devtree_addr,
-    uint64_t initrd_base,
-    unsigned long initrd_len,
-    start_info_t *start_info __attribute__((unused)),
-    unsigned long start_info_addr)
-{
-    uint32_t si[4] = {0, start_info_addr, 0, 0x1000};
-    struct boot_param_header *header;
-    void *chosen;
-    void *xen;
-    uint64_t initrd_end = initrd_base + initrd_len;
-    unsigned int devtree_size;
-    int rc = 0;
-
-    DPRINTF("adding initrd props\n");
-
-    chosen = ft_find_node(devtree, "/chosen");
-    if (chosen == NULL) {
-        DPRINTF("couldn't find /chosen\n");
-        return -1;
-    }
-
-    xen = ft_find_node(devtree, "/xen");
-    if (xen == NULL) {
-        DPRINTF("couldn't find /xen\n");
-        return -1;
-    }
-
-    /* initrd-start */
-    rc = ft_set_prop(&devtree, chosen, "linux,initrd-start",
-            &initrd_base, sizeof(initrd_base));
-    if (rc < 0) {
-        DPRINTF("couldn't set /chosen/linux,initrd-start\n");
-        return rc;
-    }
-
-    /* initrd-end */
-    rc = ft_set_prop(&devtree, chosen, "linux,initrd-end",
-            &initrd_end, sizeof(initrd_end));
-    if (rc < 0) {
-        DPRINTF("couldn't set /chosen/linux,initrd-end\n");
-        return rc;
-    }
-
-    rc = ft_set_rsvmap(devtree, 1, initrd_base, initrd_len);
-    if (rc < 0) {
-        DPRINTF("couldn't set initrd reservation\n");
-        return ~0UL;
-    }
-
-    /* start-info (XXX being removed soon) */
-    rc = ft_set_prop(&devtree, xen, "start-info", si, sizeof(si));
-    if (rc < 0) {
-        DPRINTF("couldn't set /xen/start-info\n");
-        return rc;
-    }
-
-    header = devtree;
-    devtree_size = header->totalsize;
-    {
-        static const char dtb[] = "/tmp/xc_domU.dtb";
-        int dfd = creat(dtb, 0666);
-        if (dfd != -1) {
-            write(dfd, devtree, devtree_size);
-            close(dfd);
-        } else
-            DPRINTF("could not open(\"%s\")\n", dtb);
-    }
-
-    DPRINTF("copying device tree to 0x%lx[0x%x]\n", DEVTREE_ADDR, 
devtree_size);
-    return install_image(xc_handle, domid, page_array, devtree, DEVTREE_ADDR,
-                       devtree_size);
-}
-
 static int load_initrd(
     int xc_handle,
     int domid,
@@ -187,13 +110,14 @@ out:
 }
 
 static unsigned long create_start_info(
-    void *devtree, start_info_t *start_info,
-        unsigned int console_evtchn, unsigned int store_evtchn,
-    unsigned long nr_pages, unsigned long rma_pages)
+        start_info_t *start_info,
+        unsigned int console_evtchn,
+        unsigned int store_evtchn,
+        unsigned long nr_pages,
+        unsigned long rma_pages)
 {
     unsigned long start_info_addr;
     uint64_t rma_top;
-    int rc;
 
     memset(start_info, 0, sizeof(*start_info));
     snprintf(start_info->magic, sizeof(start_info->magic),
@@ -209,13 +133,6 @@ static unsigned long create_start_info(
     start_info->console.domU.mfn = (rma_top >> PAGE_SHIFT) - 3;
     start_info->console.domU.evtchn = console_evtchn;
     start_info_addr = rma_top - 4*PAGE_SIZE;
-
-    rc = ft_set_rsvmap(devtree, 0, start_info_addr, 4*PAGE_SIZE);
-    if (rc < 0) {
-        DPRINTF("couldn't set start_info reservation\n");
-        return ~0UL;
-    }
-
 
     return start_info_addr;
 }
@@ -238,8 +155,7 @@ int xc_linux_build(int xc_handle,
                    unsigned int store_evtchn,
                    unsigned long *store_mfn,
                    unsigned int console_evtchn,
-                   unsigned long *console_mfn,
-                   void *devtree)
+                   unsigned long *console_mfn)
 {
     start_info_t start_info;
     struct domain_setup_info dsi;
@@ -251,14 +167,19 @@ int xc_linux_build(int xc_handle,
     unsigned long initrd_len = 0;
     unsigned long start_info_addr;
     unsigned long rma_pages;
+    unsigned long shadow_mb;
+    int rma_log = 26;  /* 64MB RMA */
     int rc = 0;
+    int op;
+    struct ft_cxt root;
+    void *devtree;
 
     DPRINTF("%s\n", __func__);
 
     nr_pages = mem_mb << (20 - PAGE_SHIFT);
     DPRINTF("nr_pages 0x%lx\n", nr_pages);
 
-    rma_pages = get_rma_pages(devtree);
+    rma_pages = (1 << rma_log) >> PAGE_SHIFT;
     if (rma_pages == 0) {
         rc = -1;
         goto out;
@@ -285,8 +206,27 @@ int xc_linux_build(int xc_handle,
         }
     }
 
+    /* fetch the current shadow_memory value for this domain */
+    op = XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION;
+    if (xc_shadow_control(xc_handle, domid, op, NULL, 0, &shadow_mb, 0, NULL) 
< 0 ) {
+        rc = -1;
+        goto out;
+    }
+
+    /* build the devtree here */
+    DPRINTF("constructing devtree\n");
+    if (make_devtree(&root, domid, mem_mb, (rma_pages * PAGE_SIZE), shadow_mb, 
+                     initrd_base, initrd_len, cmdline) < 0) {
+        DPRINTF("failed to create flattened device tree\n");
+        rc = -1;
+        goto out;
+    }
+    
+    /* point devtree at bph blob */
+    devtree = root.bph;
+
     /* start_info stuff: about to be removed  */
-    start_info_addr = create_start_info(devtree, &start_info, console_evtchn,
+    start_info_addr = create_start_info(&start_info, console_evtchn,
                                         store_evtchn, nr_pages, rma_pages);
     *console_mfn = page_array[start_info.console.domU.mfn];
     *store_mfn = page_array[start_info.store_mfn];
@@ -297,11 +237,15 @@ int xc_linux_build(int xc_handle,
     }
 
     if (devtree) {
-        DPRINTF("loading flattened device tree\n");
+        struct boot_param_header *header = root.bph;
+        unsigned int devtree_size = header->totalsize;
+
         devtree_addr = DEVTREE_ADDR;
-        if (load_devtree(xc_handle, domid, page_array, devtree, devtree_addr,
-                         initrd_base, initrd_len, &start_info,
-                         start_info_addr)) {
+        DPRINTF("loading flattened device tree to 0x%lx[0x%x]\n",
+                devtree_addr, devtree_size);
+
+        if (install_image(xc_handle, domid, page_array, devtree, devtree_addr,
+                       devtree_size)) {
             DPRINTF("couldn't load flattened device tree.\n");
             rc = -1;
             goto out;
@@ -314,6 +258,7 @@ int xc_linux_build(int xc_handle,
     }
 
 out:
+    free_devtree(&root);
     free_page_array(page_array);
     return rc;
 }
diff -r c16586000525 -r 5a846b0c810c tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Wed Jan 17 19:37:20 2007 -0500
+++ b/tools/libxc/xenguest.h    Fri Jan 19 15:21:50 2007 -0600
@@ -57,7 +57,6 @@ int xc_linux_restore(int xc_handle, int 
  * @parm store_mfn returned with the mfn of the store page
  * @parm console_evtchn the console event channel for this domain to use
  * @parm console_mfn returned with the mfn of the console page
- * @parm arch_args architecture-specific data
  * @return 0 on success, -1 on failure
  */
 int xc_linux_build(int xc_handle,
@@ -71,8 +70,7 @@ int xc_linux_build(int xc_handle,
                    unsigned int store_evtchn,
                    unsigned long *store_mfn,
                    unsigned int console_evtchn,
-                   unsigned long *console_mfn,
-                   void *arch_args);
+                   unsigned long *console_mfn);
 
 /**
  * This function will create a domain for a paravirtualized Linux
diff -r c16586000525 -r 5a846b0c810c tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Wed Jan 17 19:37:20 2007 -0500
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Jan 19 15:21:50 2007 -0600
@@ -360,28 +360,26 @@ static PyObject *pyxc_linux_build(XcObje
     unsigned int mem_mb;
     unsigned long store_mfn = 0;
     unsigned long console_mfn = 0;
-    void *arch_args = NULL;
     int unused;
 
     static char *kwd_list[] = { "domid", "store_evtchn", "memsize",
                                 "console_evtchn", "image",
                                 /* optional */
                                 "ramdisk", "cmdline", "flags",
-                                "features", "arch_args", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssiss#", kwd_list,
+                                "features", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssis#", kwd_list,
                                       &dom, &store_evtchn, &mem_mb,
                                       &console_evtchn, &image,
                                       /* optional */
                                       &ramdisk, &cmdline, &flags,
-                                      &features, &arch_args, &unused) )
+                                      &features, &unused) )
         return NULL;
 
     if ( xc_linux_build(self->xc_handle, dom, mem_mb, image,
                         ramdisk, cmdline, features, flags,
                         store_evtchn, &store_mfn,
-                        console_evtchn, &console_mfn,
-                        arch_args) != 0 ) {
+                        console_evtchn, &console_mfn) != 0 ) {
         return pyxc_error_to_exception();
     }
     return Py_BuildValue("{s:i,s:i}", 
diff -r c16586000525 -r 5a846b0c810c tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Wed Jan 17 19:37:20 2007 -0500
+++ b/tools/python/xen/xend/image.py    Fri Jan 19 15:21:50 2007 -0600
@@ -239,8 +239,6 @@ class PPC_LinuxImageHandler(LinuxImageHa
         log.debug("vcpus          = %d", self.vm.getVCpuCount())
         log.debug("features       = %s", self.vm.getFeatures())
 
-        devtree = FlatDeviceTree.build(self)
-
         return xc.linux_build(domid          = self.vm.getDomid(),
                               memsize        = mem_mb,
                               image          = self.kernel,
@@ -248,8 +246,7 @@ class PPC_LinuxImageHandler(LinuxImageHa
                               console_evtchn = console_evtchn,
                               cmdline        = self.cmdline,
                               ramdisk        = self.ramdisk,
-                              features       = self.vm.getFeatures(),
-                              arch_args      = devtree.to_bin())
+                              features       = self.vm.getFeatures())
 
     def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
         """@param shadow_mem_kb The configured shadow memory, in KiB.
diff -r c16586000525 -r 5a846b0c810c tools/libxc/powerpc64/mk_flatdevtree.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/powerpc64/mk_flatdevtree.c    Fri Jan 19 15:21:50 2007 -0600
@@ -0,0 +1,605 @@
+/*
+ * 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation 2007
+ *
+ * Authors: Ryan Harper <ryanh@xxxxxxxxxx>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <libgen.h>    
+#include <inttypes.h>
+#include <math.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <xc_private.h> /* for PERROR() */
+
+#include "mk_flatdevtree.h"
+
+static uint32_t current_phandle = 0;
+
+static uint32_t get_phandle(void)
+{
+   return current_phandle++;
+}
+
+static int readfile(const char *fullpath, void *data, int len)
+{
+    struct stat st;
+    int saved_errno;
+    int rc = -1;
+    int fd;
+   
+    if ((fd = open(fullpath, O_RDONLY)) == -1) {
+        PERROR("%s: failed to open file %s", __func__, fullpath);
+        return -1;
+    }
+
+    if ((rc = fstat(fd, &st)) == -1) {
+        PERROR("%s: failed to stat fd %d", __func__, fd);
+        goto error;
+    }
+
+    if (S_ISREG(st.st_mode))
+        rc = read(fd, data, len); 
+
+    close(fd);
+    return rc;
+
+error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+/* 
+ * @property - string to check against the filter list
+ * @filter   - NULL terminated list of strings 
+ *
+ * compare @property string to each string in @filter
+ *
+ * return 1 if @property matches any filter, otherwise 0
+ *
+ */
+static int match(const char *property, const char **filter)
+{
+    int i;
+    
+    for (i=0; filter[i] != NULL; i++) {
+        /* compare the filter to property */
+        if (strncmp(property, filter[i], strlen(filter[i])) == 0)
+            return 1;
+    }
+
+    return 0;
+}
+
+/*
+ * copy the node at @dirpath filtering out any properties that match in 
@propfilter
+ */
+static int copynode(struct ft_cxt *cxt, const char *dirpath, const char 
**propfilter)
+{   
+    struct dirent *tree;
+    struct stat st;
+    DIR *dir;
+    char fullpath[MAX_PATH];
+    char *bname = NULL;
+    char *basec = NULL;
+    int saved_errno;
+
+    if ((dir = opendir(dirpath)) == NULL) {
+        PERROR("%s: failed to open dir %s", __func__, dirpath);
+        return -1;
+    }
+
+    while (1) {
+        if ((tree = readdir(dir)) == NULL)
+            break;  /* reached end of directory entries */
+
+        /* ignore . and .. */
+        if (strcmp(tree->d_name,"." ) == 0 || strcmp(tree->d_name,"..") == 0)
+            continue;
+
+        /* build full path name of the file, for stat() */
+        if (snprintf(fullpath, sizeof(fullpath), "%s/%s", dirpath,
+                     tree->d_name) >= sizeof(fullpath)) {
+            PERROR("%s: failed to build full path", __func__);
+            goto error;
+        }
+
+        /* stat the entry */
+        if (stat(fullpath, &st) < 0) {
+            PERROR("%s: failed to stat file %s", __func__, fullpath);
+            goto error;
+        }
+
+        if (S_ISDIR(st.st_mode)) {
+            /* start a new node for a dir */
+            ft_begin_node(cxt, tree->d_name);
+
+            /* copy everything in this dir */
+            if (copynode(cxt, fullpath, propfilter) < 0) {
+                PERROR("%s: failed to copy node @ %s", __func__, fullpath);
+                goto error;
+            }
+
+            /* end the node */
+            ft_end_node(cxt);
+        }
+        /* add files in dir as properties */
+        else if (S_ISREG(st.st_mode)) {
+
+            if ((basec = strdup(fullpath)) == NULL) {
+                PERROR("%s: failed to dupe string", __func__);
+                goto error;
+            }
+
+            if ((bname = basename(basec)) == NULL) {
+                PERROR("%s: basename() failed", __func__);
+                goto error;
+            }
+
+            /* only add files that don't match the property filter string */
+            if (!match(bname, propfilter)) {
+                char data[BUFSIZE];
+                int len;
+
+                /* snarf the data and push into the property */
+                if ((len = readfile(fullpath, data, sizeof(data))) < 0) {
+                    PERROR("%s: failed to read data from file %s", __func__,
+                                                                   fullpath);
+                    goto error;
+                }
+                ft_prop(cxt, tree->d_name, data, len);
+
+            }
+
+            /* strdup mallocs memory */
+            if (basec != NULL ) {
+                free(basec);
+                basec = NULL;
+            }
+
+        }
+    }
+
+    closedir(dir);
+    return 0;
+
+error:
+    saved_errno = errno;
+
+    /* strdup mallocs memory */
+    if (basec != NULL ) {
+        free(basec);
+        basec = NULL;
+    }
+
+    closedir(dir);
+
+    errno = saved_errno;
+    return -1;
+}
+
+static int find_cpu0(char *cpupath, int len)
+{   
+    const char path[] = "/proc/device-tree/cpus";
+    const char device[] = "device_type";
+    const char dev_cpu[] = "cpu";
+    const char reg[] = "reg";
+    char data[sizeof(dev_cpu)];
+    char prop[MAX_PATH];
+    char node[MAX_PATH];
+    struct dirent *tree;
+    struct stat st;
+    DIR* dir;
+    int saved_errno;
+    int found = 0;
+
+    if ((dir = opendir(path)) == NULL) {
+        PERROR("%s: failed to open directory %s", __func__, path);
+        return -1;
+    }    
+
+    while (!found) {
+
+        if ((tree = readdir(dir)) == NULL)
+            break;  /* reached end of directory entries */
+
+        /* ignore ., .. */
+        if (strcmp(tree->d_name,"." ) == 0 || strcmp(tree->d_name,"..") == 0)
+            continue;
+
+        /* build full path name of the file, for stat() */
+        if (snprintf(node, sizeof(node), "%s/%s", path,
+                     tree->d_name) >= sizeof(node)) {
+            PERROR("%s: failed to concat strings", __func__);
+            goto error;
+        }
+
+        /* stat the entry */
+        if (stat(node, &st) < 0) {
+            PERROR("%s: failed to stat file %s", __func__, node);
+            /* something funny happen in /proc/device-tree, but march onward */
+            continue;
+        }
+
+        /* for each dir, check the device_type property until we find 'cpu'*/
+        if (S_ISDIR(st.st_mode)) {
+
+            /* construct path to device_type */
+            if (snprintf(prop, sizeof(prop), "%s/%s", node,
+                         device) >= sizeof(prop)) {
+                PERROR("%s: failed to concat strings", __func__);
+                goto error;
+            }
+
+            /* read device_type into buffer */
+            if ((readfile(prop, data, sizeof(data))) < 0) {
+                PERROR("%s: failed to read data from file %s", __func__, prop);
+                goto error;
+            }
+
+            /* if the device_type is 'cpu',  and reg is 0 
+             * return the path where we found it */
+            if (strcmp(data, "cpu") == 0) {
+
+                /* construct path to reg */
+                if (snprintf(prop, sizeof(prop), "%s/%s", node,
+                             reg) >= sizeof(prop)) {
+                    PERROR("%s: failed to concat strings", __func__);
+                    goto error;
+                }
+
+                /* using data buffer since reg and device_type values have 
same size */
+                if ((readfile(prop, data, sizeof(data))) < 0) {
+                    PERROR("%s: failed to read data from file %s", __func__, 
prop);
+                    goto error;
+                }
+
+                /* now check property "reg" for value 0 */
+                if ((u32)*data == 0) {
+                    if (snprintf(cpupath, len, "%s", node) >= len) {
+                        PERROR("%s: failed to copy cpupath", __func__);
+                        goto error;
+                    }
+                    found = 1;
+                }
+            }
+        }
+    }
+
+    closedir(dir);
+    return found;
+
+error:
+    saved_errno = errno;
+    closedir(dir);
+    errno = saved_errno;
+    return -1;
+}
+
+void free_devtree(struct ft_cxt *root)
+{
+    if ((root != NULL) && root->bph != NULL) {
+        free(root->bph);
+        root->bph = NULL;
+    }
+}
+
+int make_devtree(struct ft_cxt *root,
+                 uint32_t domid, 
+                 uint32_t mem_mb,
+                 unsigned long rma_bytes,
+                 unsigned long shadow_mb,
+                 unsigned long initrd_base,
+                 unsigned long initrd_len,
+                 const char *bootargs)
+{
+    struct boot_param_header *bph = NULL;
+    uint64_t val[2];
+    uint32_t val32[2];
+    unsigned long remaining;
+    unsigned long rma_reserve = 4 * PAGE_SIZE;
+    unsigned long initrd_end = initrd_base + initrd_len;
+    int64_t shadow_mb_log;
+    uint64_t pft_size;
+    char cpupath[MAX_PATH];
+    const char *propfilter[] = { "ibm", "linux,", NULL };
+    char *cpupath_copy = NULL;
+    char *cpuname = NULL;
+    int saved_errno;
+    int dtb_fd = -1;
+    uint32_t cpu0_phandle = get_phandle();
+    uint32_t xen_phandle = get_phandle();
+    uint32_t rma_phandle = get_phandle();
+
+    /* initialize bph to prevent double free on error path */
+    root->bph = NULL;
+
+    /* carve out space for bph */
+    if ((bph = (struct boot_param_header *)malloc(BPH_SIZE)) == NULL) {
+        PERROR("%s: Failed to malloc bph buffer size", __func__);
+        goto error;
+    }
+
+    /* NB: struct ft_cxt root defined at top of file */
+    /* root = Tree() */
+    ft_begin(root, bph, BPH_SIZE);
+
+    /* you MUST set reservations BEFORE _starting_the_tree_ */
+
+    /* reserve some pages at the end of RMA */
+    val[0] = cpu_to_be64((u64) (rma_bytes - rma_reserve));
+    val[1] = cpu_to_be64((u64) rma_reserve);
+    ft_add_rsvmap(root, val[0], val[1]);
+
+    /* reserve space for initrd if needed */
+    if ( initrd_len > 0 )  {
+        val[0] = cpu_to_be64((u64) initrd_base);
+        val[1] = cpu_to_be64((u64) initrd_len);
+        ft_add_rsvmap(root, val[0], val[1]);
+    }
+
+    /* NB: ft_add_rsvmap() already terminates with a NULL reservation for us */
+
+    /* done with reservations, _starting_the_tree_ */
+    ft_begin_tree(root);
+
+    /* make root node */
+    ft_begin_node(root, "");
+
+    /* root.addprop('device_type', 'chrp-but-not-really\0') */
+    ft_prop_str(root, "device_type", "chrp-but-not-really");
+
+    /* root.addprop('#size-cells', 2) */
+    ft_prop_int(root, "#size-cells", 2);
+
+    /* root.addprop('#address-cells', 2) */
+    ft_prop_int(root, "#address-cells", 2);
+
+    /* root.addprop('model', 'Momentum,Maple-D\0') */
+    ft_prop_str(root, "model", "Momentum,Maple-D");
+
+    /* root.addprop('compatible', 'Momentum,Maple\0') */
+    ft_prop_str(root, "compatible", "Momentum,Maple");
+
+    /* start chosen node */
+    ft_begin_node(root, "chosen");
+
+    /* chosen.addprop('cpu', cpu0.get_phandle()) */
+    ft_prop_int(root, "cpu", cpu0_phandle);
+
+    /* chosen.addprop('rma', rma.get_phandle()) */
+    ft_prop_int(root, "memory", rma_phandle);
+
+    /* chosen.addprop('linux,stdout-path', '/xen/console\0') */
+    ft_prop_str(root, "linux,stdout-path", "/xen/console");
+
+    /* chosen.addprop('interrupt-controller, xen.get_phandle()) */
+    ft_prop_int(root, "interrupt-controller", xen_phandle);
+
+    /* chosen.addprop('bootargs', imghandler.cmdline + '\0') */
+    if ( bootargs != NULL )
+        ft_prop_str(root, "bootargs", bootargs);
+
+    /* mark where the initrd is, if present */
+    if ( initrd_len > 0 ) {
+        val[0] = cpu_to_be64((u64) initrd_base);
+        val[1] = cpu_to_be64((u64) initrd_end);
+        ft_prop(root, "linux,initrd-start", &(val[0]), sizeof(val[0]));
+        ft_prop(root, "linux,initrd-end", &(val[1]), sizeof(val[1]));
+    }
+
+    /* end chosen node */
+    ft_end_node(root);
+
+    /* xen = root.addnode('xen') */
+    ft_begin_node(root, "xen");
+
+    /* start-info is the first page in the RMA reserved area */
+    val[0] = cpu_to_be64((u64) (rma_bytes - rma_reserve));
+    val[1] = cpu_to_be64((u64) PAGE_SIZE);
+    ft_prop(root, "start-info", val, sizeof(val));
+
+    /*  xen.addprop('version', 'Xen-3.0-unstable\0') */
+    ft_prop_str(root, "version", "Xen-3.0-unstable");
+
+    /* xen.addprop('reg', long(imghandler.vm.domid), long(0)) */
+    val[0] = cpu_to_be64((u64) domid);
+    val[1] = cpu_to_be64((u64) 0);
+    ft_prop(root, "reg", val, sizeof(val));
+
+    /* xen.addprop('domain-name', imghandler.vm.getName() + '\0') */
+    /* libxc doesn't know the domain name, that is purely a xend thing */
+    /* ft_prop_str(root, "domain-name", domain_name); */
+
+    /* add xen/linux,phandle for chosen/interrupt-controller */
+    ft_prop_int(root, "linux,phandle", xen_phandle);
+
+    /* xencons = xen.addnode('console') */
+    ft_begin_node(root, "console");
+
+    /* xencons.addprop('interrupts', 1, 0) */
+    val32[0] = cpu_to_be32((u32) 1);
+    val32[1] = cpu_to_be32((u32) 0);
+    ft_prop(root, "interrupts", val32, sizeof(val32));
+
+    /* end of console */
+    ft_end_node(root);
+
+    /* end of xen node */
+    ft_end_node(root);
+
+    /* rma = root.addnode('memory@0') */
+    ft_begin_node(root, "memory@0");
+
+    /* rma.addprop('reg', long(0), long(rma_bytes)) */
+    val[0] = cpu_to_be64((u64) 0);
+    val[1] = cpu_to_be64((u64) rma_bytes);
+    ft_prop(root, "reg", val, sizeof(val));
+
+    /* rma.addprop('device_type', 'memory\0') */
+    ft_prop_str(root, "device_type", "memory");
+
+    /* add linux,phandle for chosen/rma node */
+    ft_prop_int(root, "linux,phandle", rma_phandle);
+
+    /* end of memory@0 */
+    ft_end_node(root);
+
+    /* calculate remaining bytes from total - rma size */
+    remaining = (mem_mb * 1024 * 1024) - rma_bytes;
+
+    /* memory@<rma_bytes> is all remaining memory after RMA */
+    if (remaining > 0)
+    {
+        char mem[MAX_PATH];
+        
+        if (snprintf(mem, sizeof(mem), "memory@%lx",
+                     rma_bytes) >= sizeof(mem)) {
+            PERROR("%s: failed to build memory string", __func__);
+            goto error;
+        }
+
+        /* memory@<rma_bytes> is all remaining memory after RMA */
+        ft_begin_node(root, mem);
+
+        /* mem.addprop('reg', long(rma_bytes), long(remaining)) */
+        val[0] = cpu_to_be64((u64) rma_bytes);
+        val[1] = cpu_to_be64((u64) remaining);
+        ft_prop(root, "reg", val, sizeof(val));
+
+        /* mem.addprop('device_type', 'memory\0') */
+        ft_prop_str(root, "device_type", "memory");
+
+        /* end memory@<rma_bytes> node */
+        ft_end_node(root);
+    }
+
+    /* add CPU nodes */
+    /* cpus = root.addnode('cpus') */
+    ft_begin_node(root, "cpus");
+
+    /* cpus.addprop('smp-enabled') */
+    ft_prop(root, "smp-enabled", NULL, 0);
+
+    /* cpus.addprop('#size-cells', 0) */
+    ft_prop_int(root, "#size-cells", 0);
+
+    /* cpus.addprop('#address-cells', 1) */
+    ft_prop_int(root, "#address-cells", 1);
+
+    /*
+     * Copy all properties the system firmware gave us from a 
+     * CPU node in the device tree.
+     */
+    if (find_cpu0(cpupath, sizeof(cpupath)) <= 0) {
+        PERROR("%s: failed find cpu0 node in host devtree", __func__);
+        goto error;
+    }
+
+    /* get the basename from path to cpu device */
+    if ((cpupath_copy = strdup(cpupath)) == NULL) {
+        PERROR("%s: failed to dupe string", __func__);
+        goto error;
+    }
+    if ((cpuname = basename(cpupath_copy)) == NULL) {
+        PERROR("%s: basename() failed", __func__);
+        goto error;
+    }
+     
+    /* start node for the cpu */
+    ft_begin_node(root, cpuname);
+
+    /* strdup() mallocs memory */
+    if ( cpupath_copy != NULL ) {
+        free(cpupath_copy);
+        cpupath_copy = NULL;
+    }
+
+    /* copy over most properties from host tree for cpu */
+    if (copynode(root, cpupath, propfilter) < 0) {
+        PERROR("%s: failed to copy node", __func__);
+            goto error;
+    }
+
+    /* calculate the pft-size */
+    shadow_mb_log = (int)log2((double)shadow_mb);
+    pft_size = shadow_mb_log + 20;
+
+    val32[0] = cpu_to_be32((u32) 0);
+    val32[1] = cpu_to_be32((u32) pft_size);
+    ft_prop(root, "ibm,pft-size", val32, sizeof(val32));
+
+    /* make phandle for cpu0 */
+    ft_prop_int(root, "linux,phandle", cpu0_phandle);
+
+    /* end <cpuname> node */
+    ft_end_node(root);
+
+    /* end cpus node */
+    ft_end_node(root);
+
+    /* end root node */
+    ft_end_node(root);
+
+    /* end of the tree */
+    if (ft_end_tree(root) != 0) {
+        PERROR("%s: failed to end tree", __func__);
+        goto error;
+    }
+
+    /* write a copy of the tree to a file */
+    if ((dtb_fd = open(DTB_FILE , O_RDWR)) == -1) {
+        PERROR("%s: failed to open file %s", __func__, DTB_FILE);
+        goto error;
+    }
+
+    if (write(dtb_fd, (const void *)bph, bph->totalsize) != bph->totalsize) {
+        PERROR("%s: failed to write blob to file", __func__);
+        goto error; 
+    }
+
+    return 0;
+ 
+error:
+    saved_errno = errno;
+
+    /* strdup() mallocs memory */
+    if ( cpupath_copy != NULL ) {
+        free(cpupath_copy);
+        cpupath_copy = NULL;
+    }
+
+    /* free bph buffer */
+    free_devtree(root);
+
+    if (dtb_fd)
+        close(dtb_fd);
+
+    errno = saved_errno;
+    return -1;
+}
diff -r c16586000525 -r 5a846b0c810c tools/libxc/powerpc64/mk_flatdevtree.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/powerpc64/mk_flatdevtree.h    Fri Jan 19 15:21:50 2007 -0600
@@ -0,0 +1,42 @@
+/*
+ * 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation 2007
+ *
+ * Authors: Ryan Harper <ryanh@xxxxxxxxxx>
+ */
+
+#ifndef MK_FLATDEVTREE_H
+#define MK_FLATDEVTREE_H
+
+#include "flatdevtree_env.h"
+#include "flatdevtree.h"
+
+extern void free_devtree(struct ft_cxt *root);
+extern int make_devtree(struct ft_cxt *root,
+                        uint32_t domid, 
+                        uint32_t mem_mb,
+                        unsigned long rma_bytes,
+                        unsigned long shadow_mb,
+                        unsigned long initrd_base,
+                        unsigned long initrd_len,
+                        const char *bootargs);
+
+#define MAX_PATH 200
+#define BUFSIZE 1024
+#define BPH_SIZE 16*1024
+#define DTB_FILE "/tmp/domU.dtb"
+
+#endif /* MK_FLATDEVTREE_H */

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel