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 <[EMAIL PROTECTED]> --- diff -r b5c1397cdc1b tools/libxc/powerpc64/Makefile --- a/tools/libxc/powerpc64/Makefile Sat Oct 07 10:29:00 2006 -0400 +++ b/tools/libxc/powerpc64/Makefile Tue Oct 17 17:31:23 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 b5c1397cdc1b tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Sat Oct 07 10:29:00 2006 -0400 +++ b/tools/libxc/xenguest.h Tue Oct 17 17:31:23 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 b5c1397cdc1b tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Sat Oct 07 10:29:00 2006 -0400 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Oct 17 17:31:23 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 b5c1397cdc1b tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Sat Oct 07 10:29:00 2006 -0400 +++ b/tools/python/xen/xend/image.py Tue Oct 17 17:31:23 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): @@ -478,6 +521,7 @@ _handlers = { _handlers = { "powerpc": { "linux": PPC_LinuxImageHandler, + "prose": PPC_ProseImageHandler, }, "ia64": { "linux": LinuxImageHandler, diff -r b5c1397cdc1b 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 Tue Oct 17 17:31:23 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 <[EMAIL PROTECTED]> + */ + +#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, "/[EMAIL PROTECTED]"); + if (rma == NULL) { + DPRINTF("couldn't find /[EMAIL PROTECTED]"); + return ~0UL; + } + rc = ft_get_prop(devtree, rma, "reg", rma_reg, sizeof(rma_reg)); + if (rc < 0) { + DPRINTF("couldn't get /[EMAIL PROTECTED]/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@lists.xensource.com http://lists.xensource.com/xen-ppc-devel