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

[Xen-changelog] [xen-unstable] [TOOLS][POWERPC] Add Prose Domain Builder



# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID f2aaf35c7759252469f01548bd2d93dc8cd65299
# Parent  877361bfe3aeb2ad185e124ca8c82c001ec27c6a
[TOOLS][POWERPC] Add Prose Domain Builder
The following patch addes a Prose domain builder.  For the moment it
is a clone of the linux ppc64 builder but will diverge quickly.
Signed-off-by: Jonathan Appavoo <jappavoo@xxxxxxxxxx>
Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
 tools/libxc/powerpc64/Makefile         |    2 
 tools/libxc/powerpc64/xc_prose_build.c |  478 +++++++++++++++++++++++++++++++++
 tools/libxc/xenguest.h                 |   13 
 tools/python/xen/lowlevel/xc/xc.c      |   53 +++
 tools/python/xen/xend/image.py         |   42 ++
 5 files changed, 587 insertions(+), 1 deletion(-)

diff -r 877361bfe3ae -r f2aaf35c7759 tools/libxc/powerpc64/Makefile
--- a/tools/libxc/powerpc64/Makefile    Wed Oct 18 06:24:57 2006 -0400
+++ b/tools/libxc/powerpc64/Makefile    Wed Oct 18 06:43:33 2006 -0400
@@ -1,4 +1,4 @@ GUEST_SRCS-y += powerpc64/xc_linux_build
 GUEST_SRCS-y += powerpc64/xc_linux_build.c
 GUEST_SRCS-y += powerpc64/flatdevtree.c
-
+GUEST_SRCS-y += powerpc64/xc_prose_build.c
 CTRL_SRCS-y += powerpc64/xc_memory.c
diff -r 877361bfe3ae -r f2aaf35c7759 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Wed Oct 18 06:24:57 2006 -0400
+++ b/tools/libxc/xenguest.h    Wed Oct 18 06:43:33 2006 -0400
@@ -122,4 +122,17 @@ int xc_get_hvm_param(
 int xc_get_hvm_param(
     int handle, domid_t dom, int param, unsigned long *value);
 
+int xc_prose_build(int xc_handle,
+                   uint32_t domid,
+                   const char *image_name,
+                   const char *ramdisk_name,
+                   const char *cmdline,
+                   const char *features,
+                   unsigned long flags,
+                   unsigned int store_evtchn,
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn,
+                   void *arch_args);
+
 #endif /* XENGUEST_H */
diff -r 877361bfe3ae -r f2aaf35c7759 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Wed Oct 18 06:24:57 2006 -0400
+++ b/tools/python/xen/lowlevel/xc/xc.c Wed Oct 18 06:43:33 2006 -0400
@@ -369,6 +369,47 @@ static PyObject *pyxc_linux_build(XcObje
                          "console_mfn", console_mfn);
 }
 
+static PyObject *pyxc_prose_build(XcObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    uint32_t dom;
+    char *image, *ramdisk = NULL, *cmdline = "", *features = NULL;
+    int flags = 0;
+    int store_evtchn, console_evtchn;
+    unsigned long store_mfn = 0;
+    unsigned long console_mfn = 0;
+    void *arch_args = NULL;
+    int unused;
+
+    static char *kwd_list[] = { "dom", "store_evtchn",
+                                "console_evtchn", "image",
+                                /* optional */
+                                "ramdisk", "cmdline", "flags",
+                                "features", "arch_args", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssiss#", kwd_list,
+                                      &dom, &store_evtchn,
+                                      &console_evtchn, &image,
+                                      /* optional */
+                                      &ramdisk, &cmdline, &flags,
+                                      &features, &arch_args, &unused) )
+        return NULL;
+
+    if ( xc_prose_build(self->xc_handle, dom, image,
+                        ramdisk, cmdline, features, flags,
+                        store_evtchn, &store_mfn,
+                        console_evtchn, &console_mfn,
+                        arch_args) != 0 ) {
+        if (!errno)
+             errno = EINVAL;
+        return PyErr_SetFromErrno(xc_error);
+    }
+    return Py_BuildValue("{s:i,s:i}", 
+                         "store_mfn", store_mfn,
+                         "console_mfn", console_mfn);
+}
+
 static PyObject *pyxc_hvm_build(XcObject *self,
                                 PyObject *args,
                                 PyObject *kwds)
@@ -1002,6 +1043,18 @@ static PyMethodDef pyxc_methods[] = {
       " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
       " vcpus   [int, 1]:   Number of Virtual CPUS in domain.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "prose_build", 
+      (PyCFunction)pyxc_prose_build, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Build a new Linux guest OS.\n"
+      " dom     [int]:      Identifier of domain to build into.\n"
+      " image   [str]:      Name of kernel image file. May be gzipped.\n"
+      " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
+      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+      " vcpus   [int, 1]:   Number of Virtual CPUS in domain.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
 
     { "hvm_build", 
       (PyCFunction)pyxc_hvm_build, 
diff -r 877361bfe3ae -r f2aaf35c7759 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Wed Oct 18 06:24:57 2006 -0400
+++ b/tools/python/xen/xend/image.py    Wed Oct 18 06:43:33 2006 -0400
@@ -245,6 +245,47 @@ class PPC_LinuxImageHandler(LinuxImageHa
                               ramdisk        = self.ramdisk,
                               features       = self.vm.getFeatures(),
                               arch_args      = devtree.to_bin())
+
+class PPC_ProseImageHandler(LinuxImageHandler):
+
+    ostype = "prose"
+
+    def configure(self, imageConfig, deviceConfig):
+        LinuxImageHandler.configure(self, imageConfig, deviceConfig)
+        self.imageConfig = imageConfig
+
+    def buildDomain(self):
+        store_evtchn = self.vm.getStorePort()
+        console_evtchn = self.vm.getConsolePort()
+
+        log.debug("dom            = %d", self.vm.getDomid())
+        log.debug("image          = %s", self.kernel)
+        log.debug("store_evtchn   = %d", store_evtchn)
+        log.debug("console_evtchn = %d", console_evtchn)
+        log.debug("cmdline        = %s", self.cmdline)
+        log.debug("ramdisk        = %s", self.ramdisk)
+        log.debug("vcpus          = %d", self.vm.getVCpuCount())
+        log.debug("features       = %s", self.vm.getFeatures())
+
+        devtree = FlatDeviceTree.build(self)
+
+        return xc.prose_build(dom            = self.vm.getDomid(),
+                              image          = self.kernel,
+                              store_evtchn   = store_evtchn,
+                              console_evtchn = console_evtchn,
+                              cmdline        = self.cmdline,
+                              ramdisk        = self.ramdisk,
+                              features       = self.vm.getFeatures(),
+                              arch_args      = devtree.to_bin())
+
+    def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
+        """@param shadow_mem_kb The configured shadow memory, in KiB.
+        @param maxmem_kb The configured maxmem, in KiB.
+        @return The corresponding required amount of shadow memory, also in
+        KiB.
+        PowerPC currently uses "shadow memory" to refer to the hash table."""
+        return max(maxmem_kb / 64, shadow_mem_kb)
+
 
 class HVMImageHandler(ImageHandler):
 
@@ -512,6 +553,7 @@ _handlers = {
 _handlers = {
     "powerpc": {
         "linux": PPC_LinuxImageHandler,
+        "prose": PPC_ProseImageHandler,
     },
     "ia64": {
         "linux": LinuxImageHandler,
diff -r 877361bfe3ae -r f2aaf35c7759 tools/libxc/powerpc64/xc_prose_build.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/powerpc64/xc_prose_build.c    Wed Oct 18 06:43:33 2006 -0400
@@ -0,0 +1,478 @@
+/*
+ * 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 (C) IBM Corporation 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xc_private.h>
+#include <xg_private.h>
+#include <xenctrl.h>
+
+#include "flatdevtree_env.h"
+#include "flatdevtree.h"
+
+#define INITRD_ADDR (24UL << 20)
+#define DEVTREE_ADDR (16UL << 20)
+
+#define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
+
+#define max(x,y) ({ \
+        const typeof(x) _x = (x);       \
+        const typeof(y) _y = (y);       \
+        (void) (&_x == &_y);            \
+        _x > _y ? _x : _y; })
+
+static void *load_file(const char *path, unsigned long *filesize)
+{
+    void *img;
+    ssize_t size;
+    int fd;
+
+    DPRINTF("load_file(%s)\n", path);
+
+    fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        perror(path);
+        return NULL;
+    }
+
+    size = lseek(fd, 0, SEEK_END);
+    if (size < 0) {
+        perror(path);
+        close(fd);
+        return NULL;
+    }
+    lseek(fd, 0, SEEK_SET);
+
+    img = malloc(size);
+    if (img == NULL) {
+        perror(path);
+        close(fd);
+        return NULL;
+    }
+
+    size = read(fd, img, size);
+    if (size <= 0) {
+        perror(path);
+        close(fd);
+        free(img);
+        return NULL;
+    }
+
+    if (filesize)
+        *filesize = size;
+    close(fd);
+    return img;
+}
+
+static int init_boot_vcpu(
+    int xc_handle,
+    int domid,
+    struct domain_setup_info *dsi,
+    unsigned long devtree_addr,
+    unsigned long kern_addr)
+{
+    vcpu_guest_context_t ctxt;
+    int rc;
+
+    memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
+    ctxt.user_regs.pc = dsi->v_kernentry;
+    ctxt.user_regs.msr = 0;
+    ctxt.user_regs.gprs[1] = 0; /* Linux uses its own stack */
+    ctxt.user_regs.gprs[3] = devtree_addr;
+    ctxt.user_regs.gprs[4] = kern_addr;
+    ctxt.user_regs.gprs[5] = 0; /* reserved for specifying OF handler */
+    /* There is a buggy kernel that does not zero the "local_paca", so
+     * we must make sure this register is 0 */
+    ctxt.user_regs.gprs[13] = 0;
+
+    DPRINTF("xc_vcpu_setvcpucontext:\n"
+                 "  pc 0x%016"PRIx64", msr 0x%016"PRIx64"\n"
+                 "  r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
+                 " %016"PRIx64"\n",
+                 ctxt.user_regs.pc, ctxt.user_regs.msr,
+                 ctxt.user_regs.gprs[1],
+                 ctxt.user_regs.gprs[2],
+                 ctxt.user_regs.gprs[3],
+                 ctxt.user_regs.gprs[4],
+                 ctxt.user_regs.gprs[5]);
+    rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
+    if (rc < 0)
+        perror("setdomaininfo");
+
+    return rc;
+}
+
+static int install_image(
+        int xc_handle,
+        int domid,
+        xen_pfn_t *page_array,
+        void *image,
+        unsigned long paddr,
+        unsigned long size)
+{
+    uint8_t *img = image;
+    int i;
+    int rc = 0;
+
+    if (paddr & ~PAGE_MASK) {
+        printf("*** unaligned address\n");
+        return -1;
+    }
+
+    for (i = 0; i < size; i += PAGE_SIZE) {
+        void *page = img + i;
+        xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT;
+        xen_pfn_t mfn = page_array[pfn];
+
+        rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page);
+        if (rc < 0) {
+            perror("xc_copy_to_domain_page");
+            break;
+        }
+    }
+    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 *si,
+    unsigned long si_addr)
+{
+    uint32_t start_info[4] = {0, si_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",
+            start_info, sizeof(start_info));
+    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_kernel(
+    int xc_handle,
+    int domid,
+    const char *kernel_path,
+    struct domain_setup_info *dsi,
+    xen_pfn_t *page_array)
+{
+    struct load_funcs load_funcs;
+    char *kernel_img;
+    unsigned long kernel_size;
+    int rc;
+
+    /* load the kernel ELF file */
+    kernel_img = load_file(kernel_path, &kernel_size);
+    if (kernel_img == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    DPRINTF("probe_elf\n");
+    rc = probe_elf(kernel_img, kernel_size, &load_funcs);
+    if (rc < 0) {
+        rc = -1;
+        printf("%s is not an ELF file\n", kernel_path);
+        goto out;
+    }
+
+    DPRINTF("parseimage\n");
+    rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi);
+    if (rc < 0) {
+        rc = -1;
+        goto out;
+    }
+
+    DPRINTF("loadimage\n");
+    (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid,
+            page_array, dsi);
+
+    DPRINTF("  v_start     %016"PRIx64"\n", dsi->v_start);
+    DPRINTF("  v_end       %016"PRIx64"\n", dsi->v_end);
+    DPRINTF("  v_kernstart %016"PRIx64"\n", dsi->v_kernstart);
+    DPRINTF("  v_kernend   %016"PRIx64"\n", dsi->v_kernend);
+    DPRINTF("  v_kernentry %016"PRIx64"\n", dsi->v_kernentry);
+
+out:
+    free(kernel_img);
+    return rc;
+}
+
+static int load_initrd(
+    int xc_handle,
+    int domid,
+    xen_pfn_t *page_array,
+    const char *initrd_path,
+    unsigned long *base,
+    unsigned long *len)
+{
+    uint8_t *initrd_img;
+    int rc = -1;
+
+    /* load the initrd file */
+    initrd_img = load_file(initrd_path, len);
+    if (initrd_img == NULL)
+        return -1;
+
+    DPRINTF("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len);
+    if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
+                *len))
+        goto out;
+
+    *base = INITRD_ADDR;
+    rc = 0;
+
+out:
+    free(initrd_img);
+    return rc;
+}
+
+static unsigned long create_start_info(void *devtree, start_info_t *si,
+        unsigned int console_evtchn, unsigned int store_evtchn,
+        unsigned long nr_pages, const char *cmdline)
+{
+    void *rma;
+    unsigned long si_addr;
+    uint64_t rma_reg[2];
+    uint64_t rma_top;
+    int rc;
+
+    memset(si, 0, sizeof(*si));
+    snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
+
+    rma = ft_find_node(devtree, "/memory@0");
+    if (rma == NULL) {
+        DPRINTF("couldn't find /memory@0\n");
+        return ~0UL;
+    }
+    rc = ft_get_prop(devtree, rma, "reg", rma_reg, sizeof(rma_reg));
+    if (rc < 0) {
+        DPRINTF("couldn't get /memory@0/reg\n");
+        return ~0UL;
+    }
+    rma_top = rma_reg[0] + rma_reg[1];
+    DPRINTF("RMA top = 0x%"PRIX64"\n", rma_top);
+
+    si->nr_pages = nr_pages;
+    si->shared_info = rma_top - PAGE_SIZE;
+    si->store_mfn = (rma_top >> PAGE_SHIFT) - 2;
+    si->store_evtchn = store_evtchn;
+    si->console.domU.mfn = (rma_top >> PAGE_SHIFT) - 3;
+    si->console.domU.evtchn = console_evtchn;
+    strncpy((char *)si->cmd_line, cmdline, MAX_GUEST_CMDLINE);
+    /* just in case we truncated cmdline with strncpy add 0 at the end */
+    si->cmd_line[MAX_GUEST_CMDLINE]=0;
+    si_addr = rma_top - 4*PAGE_SIZE;
+
+    rc = ft_set_rsvmap(devtree, 0, si_addr, 4*PAGE_SIZE);
+    if (rc < 0) {
+        DPRINTF("couldn't set start_info reservation\n");
+        return ~0UL;
+    }
+
+
+    return si_addr;
+}
+
+static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array,
+                          unsigned long *nr_pages)
+{
+    int rc;
+
+    DPRINTF("xc_get_tot_pages\n");
+    *nr_pages = xc_get_tot_pages(xc_handle, domid);
+    DPRINTF("  0x%lx\n", *nr_pages);
+
+    *page_array = malloc(*nr_pages * sizeof(xen_pfn_t));
+    if (*page_array == NULL) {
+        perror("malloc");
+        return -1;
+    }
+
+    DPRINTF("xc_get_pfn_list\n");
+    rc = xc_get_pfn_list(xc_handle, domid, *page_array, *nr_pages);
+    if (rc != *nr_pages) {
+        perror("Could not get the page frame list");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void free_page_array(xen_pfn_t *page_array)
+{
+    free(page_array);
+}
+
+
+
+int xc_prose_build(int xc_handle,
+                   uint32_t domid,
+                   const char *image_name,
+                   const char *initrd_name,
+                   const char *cmdline,
+                   const char *features,
+                   unsigned long flags,
+                   unsigned int store_evtchn,
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn,
+                   void *devtree)
+{
+    start_info_t si;
+    struct domain_setup_info dsi;
+    xen_pfn_t *page_array = NULL;
+    unsigned long nr_pages;
+    unsigned long devtree_addr = 0;
+    unsigned long kern_addr;
+    unsigned long initrd_base = 0;
+    unsigned long initrd_len = 0;
+    unsigned long si_addr;
+    int rc = 0;
+
+    DPRINTF("%s\n", __func__);
+
+    DPRINTF("cmdline=%s\n", cmdline);
+
+    if (get_page_array(xc_handle, domid, &page_array, &nr_pages)) {
+        rc = -1;
+        goto out;
+    }
+
+    DPRINTF("loading image '%s'\n", image_name);
+    if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
+        rc = -1;
+        goto out;
+    }
+    kern_addr = 0;
+
+    if (initrd_name && initrd_name[0] != '\0') {
+        DPRINTF("loading initrd '%s'\n", initrd_name);
+        if (load_initrd(xc_handle, domid, page_array, initrd_name,
+                &initrd_base, &initrd_len)) {
+            rc = -1;
+            goto out;
+        }
+    }
+
+    /* start_info stuff: about to be removed  */
+    si_addr = create_start_info(devtree, &si, console_evtchn, store_evtchn,
+                                nr_pages,cmdline);
+    *console_mfn = page_array[si.console.domU.mfn];
+    *store_mfn = page_array[si.store_mfn];
+    if (install_image(xc_handle, domid, page_array, &si, si_addr,
+                sizeof(start_info_t))) {
+        rc = -1;
+        goto out;
+    }
+
+    if (devtree) {
+        DPRINTF("loading flattened device tree\n");
+        devtree_addr = DEVTREE_ADDR;
+        if (load_devtree(xc_handle, domid, page_array, devtree, devtree_addr,
+                     initrd_base, initrd_len, &si, si_addr)) {
+            DPRINTF("couldn't load flattened device tree.\n");
+            rc = -1;
+            goto out;
+        }
+    }
+
+    if (init_boot_vcpu(xc_handle, domid, &dsi, devtree_addr, kern_addr)) {
+        rc = -1;
+        goto out;
+    }
+
+out:
+    free_page_array(page_array);
+    return rc;
+}

_______________________________________________
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®.