# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID f6ce35ef6f1c373785cc3ddb5ebd9dcaf4d499d0
# Parent da91bd66504d63394ebef4cd64ff6d1d8a9ae337
[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>
---
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 | 44 +++
5 files changed, 589 insertions(+), 1 deletion(-)
diff -r da91bd66504d -r f6ce35ef6f1c 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 da91bd66504d -r f6ce35ef6f1c 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
@@ -127,4 +127,17 @@ int xc_hvm_build_mem(int xc_handle,
unsigned int store_evtchn,
unsigned long *store_mfn);
+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 da91bd66504d -r f6ce35ef6f1c 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
@@ -364,6 +364,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)
@@ -989,6 +1030,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 da91bd66504d -r f6ce35ef6f1c 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
@@ -244,6 +244,49 @@ class PPC_LinuxImageHandler(LinuxImageHa
KiB.
PowerPC currently uses "shadow memory" to refer to the hash table."""
return max(maxmem_kb / 64, shadow_mem_kb)
+
+
+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):
@@ -491,6 +534,7 @@ _handlers = {
_handlers = {
"powerpc": {
"linux": PPC_LinuxImageHandler,
+ "prose": PPC_ProseImageHandler,
},
"ia64": {
"linux": LinuxImageHandler,
diff -r da91bd66504d -r f6ce35ef6f1c 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-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|