diff -urN --exclude=SCCS --exclude=BitKeeper xen-unstable.latest/tools/libxc/Makefile xeno-ft/tools/libxc/Makefile --- xen-unstable.latest/tools/libxc/Makefile 2005-06-06 08:50:14.000000000 -0400 +++ xeno-ft/tools/libxc/Makefile 2005-06-06 09:44:25.000000000 -0400 @@ -22,6 +22,7 @@ SRCS += xc_load_bin.c SRCS += xc_load_elf.c SRCS += xc_linux_build.c +SRCS += xc_linuxtranslate_build.c SRCS += xc_plan9_build.c SRCS += xc_linux_restore.c SRCS += xc_linux_save.c diff -urN --exclude=SCCS --exclude=BitKeeper xen-unstable.latest/tools/libxc/xc.h xeno-ft/tools/libxc/xc.h --- xen-unstable.latest/tools/libxc/xc.h 2005-06-06 08:50:14.000000000 -0400 +++ xeno-ft/tools/libxc/xc.h 2005-06-06 09:44:25.000000000 -0400 @@ -254,6 +254,15 @@ unsigned long flags, unsigned int vcpus); +int xc_linuxtranslate_build(int xc_handle, + u32 domid, + const char *image_name, + const char *ramdisk_name, + const char *cmdline, + unsigned int control_evtchn, + unsigned long flags, + unsigned int vcpus); + int xc_plan9_build (int xc_handle, u32 domid, diff -urN --exclude=SCCS --exclude=BitKeeper xen-unstable.latest/tools/libxc/xc_linuxtranslate_build.c xeno-ft/tools/libxc/xc_linuxtranslate_build.c --- xen-unstable.latest/tools/libxc/xc_linuxtranslate_build.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-ft/tools/libxc/xc_linuxtranslate_build.c 2005-06-06 10:46:28.000000000 -0400 @@ -0,0 +1,519 @@ +/****************************************************************************** + * xc_linuxtranslate_build.c + * Derived from xc_linux_build.c + */ + +#include "xc_private.h" +#define ELFSIZE 32 +#include "xc_elf.h" +#include +#include + +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) + +#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) +#define round_pgdown(_p) ((_p)&PAGE_MASK) + +static int probeimageformat(char *image, + unsigned long image_size, + struct load_funcs *load_funcs) +{ + if ( probe_elf(image, image_size, load_funcs) && + probe_bin(image, image_size, load_funcs) ) + { + ERROR( "Unrecognized image format" ); + return -EINVAL; + } + + return 0; +} + +static int setup_guest(int xc_handle, + u32 dom, + char *image, unsigned long image_size, + gzFile initrd_gfd, unsigned long initrd_len, + unsigned long nr_pages, + unsigned long *pvsi, unsigned long *pvke, + vcpu_guest_context_t *ctxt, + const char *cmdline, + unsigned long shared_info_frame, + unsigned int control_evtchn, + unsigned long flags, + unsigned int vcpus) +{ + l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; + l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; + unsigned long *page_array = NULL; + unsigned long ml2tab, pl2tab; + unsigned long ml1tab, pl1tab; + unsigned long mfn, pfn; + unsigned long count, i; + start_info_t *start_info; + shared_info_t *shared_info; + mmu_t *mmu = NULL; + int rc; + + unsigned long nr_pt_pages; + unsigned long ppt_alloc; + unsigned long *physmap, *physmap_e, physmap_pfn; + + struct load_funcs load_funcs; + struct domain_setup_info dsi; + unsigned long vinitrd_start; + unsigned long vinitrd_end; + unsigned long vphysmap_start; + unsigned long vphysmap_end; + unsigned long vstartinfo_start; + unsigned long vstartinfo_end; + unsigned long vstack_start; + unsigned long vstack_end; + unsigned long vpt_start; + unsigned long vpt_end; + unsigned long v_end; + unsigned long pshared_info; + + rc = probeimageformat(image, image_size, &load_funcs); + if ( rc != 0 ) + goto error_out; + + memset(&dsi, 0, sizeof(struct domain_setup_info)); + + rc = (load_funcs.parseimage)(image, image_size, &dsi); + if ( rc != 0 ) + goto error_out; + + if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) + { + PERROR("Guest OS must load to a page boundary.\n"); + goto error_out; + } + + /* Untranslated guests are given the mfn of the shared_info frame, and + * they are expected to map it. We need to allocate a pfn to map the + * mfn into; so we steal a page from the end. We don't need to put + * it in a page table, we just need to have a p2m and m2p for it... */ + pshared_info = nr_pages; + + /* + * Why do we need this? The number of page-table frames depends on the + * size of the bootstrap address space. But the size of the address space + * depends on the number of page-table frames (since each one is mapped + * read-only). We have a pair of simultaneous equations in two unknowns, + * which we solve by exhaustive search. + */ + vinitrd_start = round_pgup(dsi.v_end); + vinitrd_end = vinitrd_start + initrd_len; + vphysmap_start = round_pgup(vinitrd_end); + vphysmap_end = vphysmap_start + ((nr_pages+1) * sizeof(unsigned long)); + vpt_start = round_pgup(vphysmap_end); + for ( nr_pt_pages = 2; ; nr_pt_pages++ ) + { + vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE); + vstartinfo_start = vpt_end; + vstartinfo_end = vstartinfo_start + PAGE_SIZE; + vstack_start = vstartinfo_end; + vstack_end = vstack_start + PAGE_SIZE; + v_end = (vstack_end + (1<<22)-1) & ~((1<<22)-1); + if ( (v_end - vstack_end) < (512 << 10) ) + v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */ + if ( (((v_end - dsi.v_start + ((1<> + L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) + break; + } + + printf("VIRTUAL MEMORY ARRANGEMENT:\n" + " Loaded kernel: %08lx->%08lx\n" + " Init. ramdisk: %08lx->%08lx\n" + " Phys-Mach map: %08lx->%08lx\n" + " Page tables: %08lx->%08lx\n" + " Start info: %08lx->%08lx\n" + " Boot stack: %08lx->%08lx\n" + " TOTAL: %08lx->%08lx\n", + dsi.v_kernstart, dsi.v_kernend, + vinitrd_start, vinitrd_end, + vphysmap_start, vphysmap_end, + vpt_start, vpt_end, + vstartinfo_start, vstartinfo_end, + vstack_start, vstack_end, + dsi.v_start, v_end); + printf(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry); + + if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) ) + { + printf("Initial guest OS requires too much space\n" + "(%luMB is greater than %luMB limit)\n", + (v_end-dsi.v_start)>>20, (nr_pages<>20); + goto error_out; + } + + if ( (page_array = malloc((nr_pages+1) * sizeof(unsigned long))) == NULL ) + { + PERROR("Could not allocate memory"); + goto error_out; + } + + + if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages ) + { + PERROR("Could not get the page frame list"); + goto error_out; + } + + (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, &dsi); + + /* Load the initial ramdisk image. */ + if ( initrd_len != 0 ) + { + for ( i = (vinitrd_start - dsi.v_start); + i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE ) + { + char page[PAGE_SIZE]; + if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 ) + { + PERROR("Error reading initrd image, could not"); + goto error_out; + } + xc_copy_to_domain_page(xc_handle, dom, + page_array[i>>PAGE_SHIFT], page); + } + } + + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + goto error_out; + + /* First allocate page for page dir. */ + ppt_alloc = (vpt_start - dsi.v_start) >> PAGE_SHIFT; + pl2tab = ppt_alloc++; + ml2tab = page_array[pl2tab]; + ctxt->pt_base = ml2tab << PAGE_SHIFT; + + /* Initialise the page tables. */ + if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + ml2tab)) == NULL ) + goto error_out; + memset(vl2tab, 0, PAGE_SIZE); + vl2e = &vl2tab[l2_table_offset(dsi.v_start)]; + fprintf(stderr, " v_start %lx l2_table_offset %lx\n", + dsi.v_start, + l2_table_offset(dsi.v_start)); + for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ ) + { + if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) + { + pl1tab = ppt_alloc++; + ml1tab = page_array[pl1tab]; + fprintf(stderr, " allocating new l1 page; pfn %lx, mfn %lx\n", + pl1tab, ml1tab); + if ( vl1tab != NULL ) + munmap(vl1tab, PAGE_SIZE); + if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + ml1tab)) == NULL ) + { + munmap(vl2tab, PAGE_SIZE); + goto error_out; + } + memset(vl1tab, 0, PAGE_SIZE); + vl1e = &vl1tab[l1_table_offset(dsi.v_start + (count<machine and machine->phys table entries. */ + physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT; + physmap = physmap_e = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, + page_array[physmap_pfn++]); + for ( count = 0; count < nr_pages; count++ ) + { + pfn = count; + mfn = page_array[count]; + if ( add_mmu_update(xc_handle, mmu, + (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, + pfn) ) + { + munmap(physmap, PAGE_SIZE); + goto error_out; + } + *physmap_e++ = pfn; + if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 ) + { + munmap(physmap, PAGE_SIZE); + physmap = physmap_e = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, + page_array[physmap_pfn++]); + } + } + + if(xc_shadow_control(xc_handle, + dom, + DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE, + NULL, + 0, + NULL)<0) { + PERROR("Could not enable full translate mode!"); + goto error_out; + } + + /* Translate the shared_info page. (we allocated enough for nr_pages+1.) */ + mfn = shared_info_frame; + pfn = pshared_info; + if( add_mmu_update(xc_handle, mmu, + (mfn<>PAGE_SHIFT]); + + memset(start_info, 0, sizeof(*start_info)); + start_info->nr_pages = nr_pages; + start_info->shared_info = pshared_info << PAGE_SHIFT; + start_info->flags = flags; + start_info->pt_base = vpt_start; + start_info->nr_pt_frames = nr_pt_pages; + start_info->mfn_list = vphysmap_start; + start_info->domain_controller_evtchn = control_evtchn; + if ( initrd_len != 0 ) + { + start_info->mod_start = vinitrd_start; + start_info->mod_len = initrd_len; + } + strncpy((char *)start_info->cmd_line, cmdline, MAX_CMDLINE); + start_info->cmd_line[MAX_CMDLINE-1] = '\0'; + munmap(start_info, PAGE_SIZE); + + /* shared_info page starts its life empty. */ + shared_info = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame); + memset(shared_info, 0, sizeof(shared_info_t)); + /* Mask all upcalls... */ + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + shared_info->vcpu_data[i].evtchn_upcall_mask = 1; + + shared_info->n_vcpu = vcpus; + printf(" VCPUS: %d\n", shared_info->n_vcpu); + + munmap(shared_info, PAGE_SIZE); + + fprintf(stderr, "setup_guest: finish_mmu_updates\n"); + /* Send the page update requests down to the hypervisor. */ + if ( finish_mmu_updates(xc_handle, mmu) ) + goto error_out; + + free(mmu); + free(page_array); + + *pvsi = vstartinfo_start; + *pvke = dsi.v_kernentry; + + fprintf(stderr, "setup_guest: done!"); + return 0; + + error_out: + if ( mmu != NULL ) + free(mmu); + if ( page_array != NULL ) + free(page_array); + return -1; +} + +int xc_linuxtranslate_build(int xc_handle, + u32 domid, + const char *image_name, + const char *ramdisk_name, + const char *cmdline, + unsigned int control_evtchn, + unsigned long flags, + unsigned int vcpus) +{ + dom0_op_t launch_op, op; + int initrd_fd = -1; + gzFile initrd_gfd = NULL; + int rc, i; + vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; + unsigned long nr_pages; + char *image = NULL; + unsigned long image_size, initrd_size=0; + unsigned long vstartinfo_start, vkern_entry; + + if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 ) + { + PERROR("Could not find total pages for domain"); + goto error_out; + } + + if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ) + goto error_out; + + if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) ) + { + if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 ) + { + PERROR("Could not open the initial ramdisk image"); + goto error_out; + } + + initrd_size = xc_get_filesz(initrd_fd); + + if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL ) + { + PERROR("Could not allocate decompression state for initrd"); + goto error_out; + } + } + + if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ) + { + PERROR("Unable to mlock ctxt"); + return 1; + } + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = (domid_t)domid; + if ( (do_dom0_op(xc_handle, &op) < 0) || + ((u16)op.u.getdomaininfo.domain != domid) ) + { + PERROR("Could not get info on domain"); + goto error_out; + } + + if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ) + { + PERROR("Could not get vcpu context"); + goto error_out; + } + + if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || + (ctxt->pt_base != 0) ) + { + ERROR("Domain is already constructed"); + goto error_out; + } + + if ( setup_guest(xc_handle, domid, image, image_size, + initrd_gfd, initrd_size, nr_pages, + &vstartinfo_start, &vkern_entry, + ctxt, cmdline, + op.u.getdomaininfo.shared_info_frame, + control_evtchn, flags, vcpus) < 0 ) + { + ERROR("Error constructing guest OS"); + goto error_out; + } + + if ( initrd_fd >= 0 ) + close(initrd_fd); + if ( initrd_gfd ) + gzclose(initrd_gfd); + if ( image != NULL ) + free(image); + + ctxt->flags = 0; + + /* + * Initial register values: + * DS,ES,FS,GS = FLAT_KERNEL_DS + * CS:EIP = FLAT_KERNEL_CS:start_pc + * SS:ESP = FLAT_KERNEL_DS:start_stack + * ESI = start_info + * [EAX,EBX,ECX,EDX,EDI,EBP are zero] + * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) + */ + ctxt->user_regs.ds = FLAT_KERNEL_DS; + ctxt->user_regs.es = FLAT_KERNEL_DS; + ctxt->user_regs.fs = FLAT_KERNEL_DS; + ctxt->user_regs.gs = FLAT_KERNEL_DS; + ctxt->user_regs.ss = FLAT_KERNEL_DS; + ctxt->user_regs.cs = FLAT_KERNEL_CS; + ctxt->user_regs.eip = vkern_entry; + ctxt->user_regs.esp = vstartinfo_start + 2*PAGE_SIZE; + ctxt->user_regs.esi = vstartinfo_start; + ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ + + /* FPU is set up to default initial state. */ + memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); + + /* Virtual IDT is empty at start-of-day. */ + for ( i = 0; i < 256; i++ ) + { + ctxt->trap_ctxt[i].vector = i; + ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS; + } + + /* No LDT. */ + ctxt->ldt_ents = 0; + + /* Use the default Xen-provided GDT. */ + ctxt->gdt_ents = 0; + + /* Ring 1 stack is the initial stack. */ + ctxt->kernel_ss = FLAT_KERNEL_DS; + ctxt->kernel_sp = vstartinfo_start + 2*PAGE_SIZE; + + /* No debugging. */ + memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg)); + + /* No callback handlers. */ +#if defined(__i386__) + ctxt->event_callback_cs = FLAT_KERNEL_CS; + ctxt->event_callback_eip = 0; + ctxt->failsafe_callback_cs = FLAT_KERNEL_CS; + ctxt->failsafe_callback_eip = 0; +#elif defined(__x86_64__) + ctxt->event_callback_eip = 0; + ctxt->failsafe_callback_eip = 0; + ctxt->syscall_callback_eip = 0; +#endif + + memset( &launch_op, 0, sizeof(launch_op) ); + + launch_op.u.setdomaininfo.domain = (domid_t)domid; + launch_op.u.setdomaininfo.vcpu = 0; + launch_op.u.setdomaininfo.ctxt = ctxt; + + launch_op.cmd = DOM0_SETDOMAININFO; + rc = do_dom0_op(xc_handle, &launch_op); + + return rc; + + error_out: + if ( initrd_gfd != NULL ) + gzclose(initrd_gfd); + else if ( initrd_fd >= 0 ) + close(initrd_fd); + if ( image != NULL ) + free(image); + + return -1; +} diff -urN --exclude=SCCS --exclude=BitKeeper xen-unstable.latest/tools/python/xen/lowlevel/xc/xc.c xeno-ft/tools/python/xen/lowlevel/xc/xc.c --- xen-unstable.latest/tools/python/xen/lowlevel/xc/xc.c 2005-06-06 08:50:14.000000000 -0400 +++ xeno-ft/tools/python/xen/lowlevel/xc/xc.c 2005-06-06 09:44:25.000000000 -0400 @@ -280,6 +280,33 @@ return zero; } +static PyObject *pyxc_linuxtranslate_build(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *image, *ramdisk = NULL, *cmdline = ""; + int control_evtchn, flags = 0, vcpus = 1; + + static char *kwd_list[] = { "dom", "control_evtchn", + "image", "ramdisk", "cmdline", "flags", "vcpus", + NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssii", kwd_list, + &dom, &control_evtchn, + &image, &ramdisk, &cmdline, &flags, &vcpus) ) + return NULL; + + if ( xc_linuxtranslate_build(xc->xc_handle, dom, image, + ramdisk, cmdline, control_evtchn, flags, vcpus) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_plan9_build(PyObject *self, PyObject *args, PyObject *kwds) @@ -924,6 +951,17 @@ " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "linuxtranslate_build", + (PyCFunction)pyxc_linuxtranslate_build, + METH_VARARGS | METH_KEYWORDS, "\n" + "Build a new shadow-translated 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" }, + { "plan9_build", (PyCFunction)pyxc_plan9_build, METH_VARARGS | METH_KEYWORDS, "\n" diff -urN --exclude=SCCS --exclude=BitKeeper xen-unstable.latest/tools/python/xen/xend/XendDomainInfo.py xeno-ft/tools/python/xen/xend/XendDomainInfo.py --- xen-unstable.latest/tools/python/xen/xend/XendDomainInfo.py 2005-06-01 14:06:28.000000000 -0400 +++ xeno-ft/tools/python/xen/xend/XendDomainInfo.py 2005-06-04 17:09:24.000000000 -0400 @@ -1114,6 +1114,30 @@ vm.create_domain("linux", kernel, ramdisk, cmdline) return vm +def vm_image_linuxtranslate(vm, image): + """Create a VM for a shaodw translate linux image. + + @param name: vm name + @param memory: vm memory + @param image: image config + @return: vm + """ + kernel = sxp.child_value(image, "kernel") + cmdline = "" + ip = sxp.child_value(image, "ip", None) + if ip: + cmdline += " ip=" + ip + root = sxp.child_value(image, "root") + if root: + cmdline += " root=" + root + args = sxp.child_value(image, "args") + if args: + cmdline += " " + args + ramdisk = sxp.child_value(image, "ramdisk", '') + log.debug("creating translated linux domain with cmdline: %s" %(cmdline,)) + vm.create_domain("linuxtranslate", kernel, ramdisk, cmdline) + return vm + def vm_image_plan9(vm, image): """Create a VM for a Plan 9 image. @@ -1197,6 +1221,7 @@ #============================================================================ # Register image handlers. add_image_handler('linux', vm_image_linux) +add_image_handler('linuxtranslate', vm_image_linuxtranslate) add_image_handler('plan9', vm_image_plan9) add_image_handler('vmx', vm_image_vmx)