[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge with xen-ia64-unstable.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 9fc1979e9b00216b82d32a875088b28778cbf5d4 # Parent fc6c3d866477a2a7454ba032281744b534d78bf8 # Parent b60ea69932b1a4d10c3aae945a1ce1aa160c689b Merge with xen-ia64-unstable. --- tools/libxc/xc_ppc_linux_build.c | 414 --------------------------------- .hgignore | 8 tools/libxc/Makefile | 2 tools/libxc/powerpc64/Makefile | 1 tools/libxc/powerpc64/xc_linux_build.c | 408 ++++++++++++++++++++++++++++++++ xen/arch/powerpc/Makefile | 3 xen/arch/powerpc/boot_of.c | 8 xen/arch/powerpc/dom0_ops.c | 43 ++- xen/arch/powerpc/domain.c | 29 +- xen/arch/powerpc/of_handler/devtree.c | 2 xen/arch/powerpc/powerpc64/ppc970.c | 7 xen/arch/powerpc/usercopy.c | 4 xen/include/asm-powerpc/processor.h | 1 13 files changed, 486 insertions(+), 444 deletions(-) diff -r fc6c3d866477 -r 9fc1979e9b00 .hgignore --- a/.hgignore Wed Aug 09 10:32:23 2006 -0600 +++ b/.hgignore Wed Aug 09 18:15:27 2006 +0100 @@ -197,7 +197,7 @@ ^xen/xen$ ^xen/xen-syms$ ^xen/xen\..*$ -^xen/arch/ppc/dom0\.bin$ -^xen/arch/ppc/asm-offsets\.s$ -^xen/arch/ppc/firmware -^xen/arch/ppc/firmware_image +^xen/arch/powerpc/dom0\.bin$ +^xen/arch/powerpc/asm-offsets\.s$ +^xen/arch/powerpc/firmware +^xen/arch/powerpc/firmware_image diff -r fc6c3d866477 -r 9fc1979e9b00 tools/libxc/Makefile --- a/tools/libxc/Makefile Wed Aug 09 10:32:23 2006 -0600 +++ b/tools/libxc/Makefile Wed Aug 09 18:15:27 2006 +0100 @@ -29,7 +29,6 @@ GUEST_SRCS-y += xc_load_bin.c GUEST_SRCS-y += xc_load_bin.c GUEST_SRCS-y += xc_load_elf.c GUEST_SRCS-y += xg_private.c -GUEST_SRCS-$(CONFIG_POWERPC) += xc_ppc_linux_build.c GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c @@ -140,3 +139,4 @@ libxenguest.so.$(MAJOR).$(MINOR): $(GUES $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenguest.so.$(MAJOR) -shared -o $@ $^ -lz -lxenctrl -include $(DEPS) + diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/Makefile --- a/xen/arch/powerpc/Makefile Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/Makefile Wed Aug 09 18:15:27 2006 +0100 @@ -83,6 +83,9 @@ physdev.o: ../x86/physdev.c HDRS += $(wildcard *.h) +CMDLINE = "xen" +boot_of.o: CFLAGS += -DCMDLINE="\"$(CMDLINE)\"" + start.o: boot/start.S $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@ diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/boot_of.c --- a/xen/arch/powerpc/boot_of.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/boot_of.c Wed Aug 09 18:15:27 2006 +0100 @@ -36,6 +36,10 @@ static int of_out; static int of_out; static ofdn_t boot_cpu; static char bootargs[256]; + +#define COMMAND_LINE_SIZE 512 +static char builtin_cmdline[COMMAND_LINE_SIZE] + __attribute__((section("__builtin_cmdline"))) = CMDLINE; extern struct ns16550_defaults ns16550; @@ -449,8 +453,8 @@ static void boot_of_bootargs(multiboot_i int rc; rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs)); - if (rc == OF_FAILURE) { - strcpy(bootargs, "xen"); + if (rc == OF_FAILURE || bootargs[0] == '\0') { + strlcpy(bootargs, builtin_cmdline, sizeof(bootargs)); } mbi->flags |= MBI_CMDLINE; diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/dom0_ops.c --- a/xen/arch/powerpc/dom0_ops.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/dom0_ops.c Wed Aug 09 18:15:27 2006 +0100 @@ -40,23 +40,40 @@ long arch_do_dom0_op(struct dom0_op *op, long ret = 0; switch (op->cmd) { - case DOM0_GETMEMLIST: { - /* XXX 64M hackage */ - const int memsize = (64UL<<20); - int domain_pfns = memsize>>12; - int max_pfns = op->u.getmemlist.max_pfns; - int domid = op->u.getmemlist.domain; + case DOM0_GETMEMLIST: + { int i; + struct domain *d = find_domain_by_id(op->u.getmemlist.domain); + unsigned long max_pfns = op->u.getmemlist.max_pfns; + xen_pfn_t mfn; + struct list_head *list_ent; - for (i = 0; (i < max_pfns) && (i < domain_pfns); i++) { - xen_pfn_t mfn = (((domid + 1) * memsize) >> 12) + i; - if (copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1)) { - ret = -EFAULT; - break; + ret = -EINVAL; + if ( d != NULL ) + { + ret = 0; + + spin_lock(&d->page_alloc_lock); + list_ent = d->page_list.next; + for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ ) + { + mfn = page_to_mfn(list_entry( + list_ent, struct page_info, list)); + if ( copy_to_guest_offset(op->u.getmemlist.buffer, + i, &mfn, 1) ) + { + ret = -EFAULT; + break; + } + list_ent = mfn_to_page(mfn)->list.next; } + spin_unlock(&d->page_alloc_lock); + + op->u.getmemlist.num_pfns = i; + copy_to_guest(u_dom0_op, op, 1); + + put_domain(d); } - op->u.getmemlist.num_pfns = i; - copy_to_guest(u_dom0_op, op, 1); } break; diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/domain.c --- a/xen/arch/powerpc/domain.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/domain.c Wed Aug 09 18:15:27 2006 +0100 @@ -73,6 +73,10 @@ unsigned long hypercall_create_continuat int arch_domain_create(struct domain *d) { + struct page_info *rma; + unsigned long rma_base; + unsigned long rma_size; + unsigned int rma_order; if (d->domain_id == IDLE_DOMAIN_ID) { d->shared_info = (void *)alloc_xenheap_page(); @@ -81,17 +85,28 @@ int arch_domain_create(struct domain *d) return 0; } - /* XXX the hackage... hardcode 64M domains */ - d->arch.rma_base = (64<<20) * (d->domain_id + 1); - d->arch.rma_size = (64<<20); - - printk("clearing RMO: 0x%lx[0x%lx]\n", d->arch.rma_base, d->arch.rma_size); - memset((void*)d->arch.rma_base, 0, d->arch.rma_size); + rma_order = cpu_rma_order(); + rma_size = 1UL << rma_order << PAGE_SHIFT; + + /* allocate the real mode area */ + d->max_pages = 1UL << rma_order; + rma = alloc_domheap_pages(d, rma_order, 0); + if (NULL == rma) + return 1; + rma_base = page_to_maddr(rma); + + BUG_ON(rma_base & (rma_size-1)); /* check alignment */ + + d->arch.rma_base = rma_base; + d->arch.rma_size = rma_size; + + printk("clearing RMO: 0x%lx[0x%lx]\n", rma_base, rma_size); + memset((void *)rma_base, 0, rma_size); htab_alloc(d, LOG_DEFAULT_HTAB_BYTES); d->shared_info = (shared_info_t *) - (rma_addr(&d->arch, RMA_SHARED_INFO) + d->arch.rma_base); + (rma_addr(&d->arch, RMA_SHARED_INFO) + rma_base); d->arch.large_page_sizes = 1; d->arch.large_page_shift[0] = 24; /* 16 M for 970s */ diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/of_handler/devtree.c --- a/xen/arch/powerpc/of_handler/devtree.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/of_handler/devtree.c Wed Aug 09 18:15:27 2006 +0100 @@ -203,12 +203,14 @@ ofh_finddevice(u32 nargs, u32 nrets, s32 /* good enuff */ if (devspec[0] == '\0') { if (*ap == -1) { + *ph = -1; return OF_FAILURE; } *ph = *ap; } else { *ph = ofd_node_find(mem, devspec); if (*ph <= 0) { + *ph = -1; return OF_FAILURE; } } diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/powerpc64/ppc970.c --- a/xen/arch/powerpc/powerpc64/ppc970.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/powerpc64/ppc970.c Wed Aug 09 18:15:27 2006 +0100 @@ -30,6 +30,12 @@ #include <asm/powerpc64/ppc970-hid.h> #undef SERIALIZE + +unsigned int cpu_rma_order(void) +{ + /* XXX what about non-HV mode? */ + return 14; /* 1<<14<<PAGE_SIZE = 64M */ +} void cpu_initialize(void) { @@ -102,7 +108,6 @@ void cpu_initialize(void) mthid5(hid5.word); __asm__ __volatile__("isync; slbia; isync" : : : "memory"); - } void cpu_init_vcpu(struct vcpu *v) diff -r fc6c3d866477 -r 9fc1979e9b00 xen/arch/powerpc/usercopy.c --- a/xen/arch/powerpc/usercopy.c Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/arch/powerpc/usercopy.c Wed Aug 09 18:15:27 2006 +0100 @@ -238,5 +238,5 @@ int xencomm_handle_is_null(void *ptr) desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)ptr); - return (desc->address[0] == XENCOMM_INVALID); -} + return (desc->nr_addrs == 0); +} diff -r fc6c3d866477 -r 9fc1979e9b00 xen/include/asm-powerpc/processor.h --- a/xen/include/asm-powerpc/processor.h Wed Aug 09 10:32:23 2006 -0600 +++ b/xen/include/asm-powerpc/processor.h Wed Aug 09 18:15:27 2006 +0100 @@ -39,6 +39,7 @@ struct cpu_user_regs; struct cpu_user_regs; extern void show_registers(struct cpu_user_regs *); extern void show_execution_state(struct cpu_user_regs *); +extern unsigned int cpu_rma_order(void); extern void cpu_initialize(void); extern void cpu_init_vcpu(struct vcpu *); extern void save_cpu_sprs(struct vcpu *); diff -r fc6c3d866477 -r 9fc1979e9b00 tools/libxc/powerpc64/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/powerpc64/Makefile Wed Aug 09 18:15:27 2006 +0100 @@ -0,0 +1,1 @@ +GUEST_SRCS-y += powerpc64/xc_linux_build.c diff -r fc6c3d866477 -r 9fc1979e9b00 tools/libxc/powerpc64/xc_linux_build.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/powerpc64/xc_linux_build.c Wed Aug 09 18:15:27 2006 +0100 @@ -0,0 +1,408 @@ +/* + * 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/dom0_ops.h> +#include <xen/memory.h> +#include <xc_private.h> +#include <xg_private.h> +#include <xenctrl.h> + +/* XXX 64M hack */ +#define MEMSIZE (64UL << 20) +#define INITRD_ADDR (24UL << 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 dtb, + unsigned long kaddr) +{ + 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] = dtb; + ctxt.user_regs.gprs[4] = kaddr; + ctxt.user_regs.gprs[5] = 0; + /* 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%"PRIx64", msr 0x016%"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; +} + +/* XXX be more flexible about placement in memory */ +static int load_dtb( + int xc_handle, + int domid, + const char *dtb_path, + unsigned long dtb_addr, + struct domain_setup_info *dsi, + xen_pfn_t *page_array) +{ + uint8_t *img; + unsigned long dtb_size; + int rc = 0; + + img = load_file(dtb_path, &dtb_size); + if (img == NULL) { + rc = -1; + goto out; + } + + DPRINTF("copying device tree to 0x%lx[0x%lx]\n", dtb_addr, dtb_size); + rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size); + +out: + free(img); + return rc; +} + +unsigned long spin_list[] = { +#if 0 + 0x100, + 0x200, + 0x300, + 0x380, + 0x400, + 0x480, + 0x500, + 0x700, + 0x900, + 0xc00, +#endif + 0 +}; + +/* XXX yes, this is a hack */ +static void hack_kernel_img(char *img) +{ + const off_t file_offset = 0x10000; + unsigned long *addr = spin_list; + + while (*addr) { + uint32_t *instruction = (uint32_t *)(img + *addr + file_offset); + printf("installing spin loop at %lx (%x)\n", *addr, *instruction); + *instruction = 0x48000000; + addr++; + } +} + +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; + } + + hack_kernel_img(kernel_img); + + 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(start_info_t *si, + unsigned int console_evtchn, unsigned int store_evtchn) +{ + unsigned long eomem; + unsigned long si_addr; + + memset(si, 0, sizeof(*si)); + snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0); + + eomem = MEMSIZE; + si->nr_pages = eomem >> PAGE_SHIFT; + si->shared_info = eomem - (PAGE_SIZE * 1); + si->store_mfn = si->nr_pages - 2; + si->store_evtchn = store_evtchn; + si->console_mfn = si->nr_pages - 3; + si->console_evtchn = console_evtchn; + si_addr = eomem - (PAGE_SIZE * 4); + + return si_addr; +} + +static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array) +{ + int nr_pages; + int rc; + + DPRINTF("xc_get_tot_pages\n"); + nr_pages = xc_get_tot_pages(xc_handle, domid); + DPRINTF(" 0x%x\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; +} + + + +int xc_linux_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) +{ + struct domain_setup_info dsi; + xen_pfn_t *page_array = NULL; + unsigned long kern_addr; + unsigned long dtb_addr; + unsigned long si_addr; + unsigned long initrd_base = 0; + unsigned long initrd_len = 0; + start_info_t si; + int rc = 0; + + if (get_page_array(xc_handle, domid, &page_array)) { + rc = -1; + goto out; + } + + 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' && + load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base, + &initrd_len)) { + rc = -1; + goto out; + } + /* XXX install initrd addr/len into device tree */ + + dtb_addr = (16 << 20); + if (load_dtb(xc_handle, domid, "/root/DomU.dtb", dtb_addr, &dsi, page_array)) { + dtb_addr = 0; + } + + si_addr = create_start_info(&si, console_evtchn, store_evtchn); + *console_mfn = page_array[si.console_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 (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) { + rc = -1; + goto out; + } + +out: + return rc; +} diff -r fc6c3d866477 -r 9fc1979e9b00 tools/libxc/xc_ppc_linux_build.c --- a/tools/libxc/xc_ppc_linux_build.c Wed Aug 09 10:32:23 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* - * 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/dom0_ops.h> -#include <xen/memory.h> -#include <xc_private.h> -#include <xg_private.h> -#include <xenctrl.h> - -/* XXX 64M hack */ -#define MEMSIZE (64UL << 20) -#define INITRD_ADDR (24UL << 20) - -int verbose; -#define VERBOSE(stuff, ...) \ - if (verbose) \ - stuff __VA_ARGS__; - -#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; - - VERBOSE(printf("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 dtb, - unsigned long kaddr) -{ - 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] = dtb; - ctxt.user_regs.gprs[4] = kaddr; - ctxt.user_regs.gprs[5] = 0; - /* 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; - - VERBOSE(printf("xc_vcpu_setvcpucontext:\n" - " pc 0x%"PRIx64", msr 0x016%"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; -} - -/* XXX be more flexible about placement in memory */ -static int load_dtb( - int xc_handle, - int domid, - const char *dtb_path, - unsigned long dtb_addr, - struct domain_setup_info *dsi, - xen_pfn_t *page_array) -{ - uint8_t *img; - unsigned long dtb_size; - int rc = 0; - - img = load_file(dtb_path, &dtb_size); - if (img == NULL) { - rc = -1; - goto out; - } - - VERBOSE(printf("copying device tree to 0x%lx[0x%lx]\n", - dtb_addr, dtb_size)); - rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size); - -out: - free(img); - return rc; -} - -unsigned long spin_list[] = { -#if 0 - 0x100, - 0x200, - 0x300, - 0x380, - 0x400, - 0x480, - 0x500, - 0x700, - 0x900, - 0xc00, -#endif - 0 -}; - -/* XXX yes, this is a hack */ -static void hack_kernel_img(char *img) -{ - const off_t file_offset = 0x10000; - unsigned long *addr = spin_list; - - while (*addr) { - uint32_t *instruction = (uint32_t *)(img + *addr + file_offset); - printf("installing spin loop at %lx (%x)\n", *addr, *instruction); - *instruction = 0x48000000; - addr++; - } -} - -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; - } - - hack_kernel_img(kernel_img); - - VERBOSE(printf("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; - } - - VERBOSE(printf("parseimage\n")); - rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi); - if (rc < 0) { - rc = -1; - goto out; - } - - VERBOSE(printf("loadimage\n")); - (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid, - page_array, dsi); - - VERBOSE(printf(" v_start %016"PRIx64"\n", dsi->v_start)); - VERBOSE(printf(" v_end %016"PRIx64"\n", dsi->v_end)); - VERBOSE(printf(" v_kernstart %016"PRIx64"\n", dsi->v_kernstart)); - VERBOSE(printf(" v_kernend %016"PRIx64"\n", dsi->v_kernend)); - VERBOSE(printf(" 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; - - VERBOSE(printf("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(start_info_t *si, - unsigned int console_evtchn, unsigned int store_evtchn) -{ - unsigned long eomem; - unsigned long si_addr; - - memset(si, 0, sizeof(*si)); - snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0); - - eomem = MEMSIZE; - si->nr_pages = eomem >> PAGE_SHIFT; - si->shared_info = eomem - (PAGE_SIZE * 1); - si->store_mfn = si->nr_pages - 2; - si->store_evtchn = store_evtchn; - si->console_mfn = si->nr_pages - 3; - si->console_evtchn = console_evtchn; - si_addr = eomem - (PAGE_SIZE * 4); - - return si_addr; -} - -static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array) -{ - int nr_pages; - int rc; - - VERBOSE(printf("xc_get_tot_pages\n")); - nr_pages = xc_get_tot_pages(xc_handle, domid); - VERBOSE(printf(" 0x%x\n", nr_pages)); - - *page_array = malloc(nr_pages * sizeof(xen_pfn_t)); - if (*page_array == NULL) { - perror("malloc"); - return -1; - } - - VERBOSE(printf("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; -} - - - -int xc_linux_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) -{ - struct domain_setup_info dsi; - xen_pfn_t *page_array = NULL; - unsigned long kern_addr; - unsigned long dtb_addr; - unsigned long si_addr; - unsigned long initrd_base = 0; - unsigned long initrd_len = 0; - start_info_t si; - int rc = 0; - - if (get_page_array(xc_handle, domid, &page_array)) { - rc = -1; - goto out; - } - - 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' && - load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base, - &initrd_len)) { - rc = -1; - goto out; - } - /* XXX install initrd addr/len into device tree */ - - dtb_addr = (16 << 20); - if (load_dtb(xc_handle, domid, "/root/DomU.dtb", dtb_addr, &dsi, page_array)) { - dtb_addr = 0; - } - - si_addr = create_start_info(&si, store_evtchn, console_evtchn); - *console_mfn = page_array[si.console_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 (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) { - rc = -1; - goto out; - } - -out: - return rc; -} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |