[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] domain builder for ReactOS
As announced earlier (http://lists.xensource.com/archives/html/xen-devel/2005-03/msg01160.html) I'm working on porting ReactOS to Xen. The first stage, getting our bootloader running, is complete now. Progress report and a screenshot on http://reactos.com/wiki/index.php/Xen_port To start ReactOS in a Xen domain, a ReactOS domain builder is needed. Patches to implement that are included below. I'm not sure about the Signed-Off-By stuff, is just including the line below enough or is some paperwork required? Ge van Geldorp. Signed-Off-By: Ge van Geldorp <gvg@xxxxxxxxxxx> --- orig/tools/libxc/xc.h 2005-06-02 23:26:10.000000000 +0200 +++ reactos/tools/libxc/xc.h 2005-06-02 23:23:10.000000000 +0200 @@ -273,6 +273,15 @@ unsigned int control_evtchn, unsigned long flags); +int xc_reactos_build(int xc_handle, + u32 domid, + const char *image_name, + const char *module_name, + const char *cmdline, + unsigned int control_evtchn, + unsigned long flags, + unsigned int vcpus); + int xc_bvtsched_global_set(int xc_handle, unsigned long ctx_allow); --- orig/tools/python/xen/lowlevel/xc/xc.c 2005-06-02 23:26:10.000000000 +0200 +++ reactos/tools/python/xen/lowlevel/xc/xc.c 2005-06-02 23:23:07.000000000 +0200 @@ -391,6 +391,33 @@ return zero; } +static PyObject *pyxc_reactos_build(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *image, *module = 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, &module, &cmdline, &flags, &vcpus) ) + return NULL; + + if ( xc_reactos_build(xc->xc_handle, dom, image, + module, cmdline, control_evtchn, flags, vcpus) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_bvtsched_global_set(PyObject *self, PyObject *args, PyObject *kwds) @@ -942,6 +969,17 @@ " cmdline [str, n/a]: Kernel parameters, if any.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "reactos_build", + (PyCFunction)pyxc_reactos_build, + METH_VARARGS | METH_KEYWORDS, "\n" + "Build a new ReactOS 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" }, + { "bvtsched_global_set", (PyCFunction)pyxc_bvtsched_global_set, METH_VARARGS | METH_KEYWORDS, "\n" --- orig/tools/python/xen/xend/XendDomainInfo.py 2005-06-02 23:26:10.000000000 +0200 +++ reactos/tools/python/xen/xend/XendDomainInfo.py 2005-06-02 23:23:01.000000000 +0200 @@ -1167,6 +1167,24 @@ vm.create_domain("vmx", kernel, ramdisk, cmdline, memmap) return vm +def vm_image_reactos(vm, image): + """Create a VM for a ReactOS image. + + @param name: vm name + @param memory: vm memory + @param image: image config + @return: vm + """ + kernel = sxp.child_value(image, "kernel") + cmdline = "" + args = sxp.child_value(image, "args") + if args: + cmdline += " " + args + ramdisk = sxp.child_value(image, "ramdisk", '') + log.debug("creating reactos domain with cmdline: %s" %(cmdline,)) + vm.create_domain("reactos", kernel, ramdisk, cmdline) + return vm + def vm_field_ignore(vm, config, val, index): """Dummy config field handler used for fields with built-in handling. @@ -1196,9 +1214,10 @@ #============================================================================ # Register image handlers. -add_image_handler('linux', vm_image_linux) -add_image_handler('plan9', vm_image_plan9) -add_image_handler('vmx', vm_image_vmx) +add_image_handler('linux', vm_image_linux) +add_image_handler('plan9', vm_image_plan9) +add_image_handler('vmx', vm_image_vmx) +add_image_handler('reactos', vm_image_reactos) # Ignore the fields we already handle. add_config_handler('name', vm_field_ignore) --- orig/tools/libxc/Makefile 2005-05-25 00:20:35 +02:00 +++ reactos/tools/libxc/Makefile 2005-06-01 11:51:19 +02:00 @@ -28,6 +28,7 @@ SRCS += xc_private.c SRCS += xc_ptrace.c SRCS += xc_ptrace_core.c +SRCS += xc_reactos_build.c SRCS += xc_vmx_build.c CFLAGS += -Wall --- /dev/null 2005-06-02 12:46:09.470000000 +0200 +++ reactos/tools/libxc/xc_reactos_build.c 2005-06-02 23:23:10.000000000 +0200 @@ -0,0 +1,652 @@ +/****************************************************************************** + * xc_reactos_build.c + * + * Based on xc_linux_build.c + * + * An executable to be loaded by the reactos domain builder is a simple binary + * image. It's like a .COM file in MS-DOS. No headers are present. + * The only requirement is that it must have a xen_reactos table somewhere in + * the first 8192 bytes, starting on a 32-bit aligned address. Those familiar + * with the multiboot specification should recognize this, it's (almost) the + * same as the multiboot header. + * The layout of the xen_reactos table is: + * + * Offset Type Name Note + * 0 u32 magic required + * 4 u32 flags required + * 8 u32 checksum required + * 12 u32 header_addr required + * 16 u32 load_addr required + * 20 u32 load_end_addr required + * 24 u32 bss_end_addr required + * 28 u32 entry_addr required + * + * - magic + * Magic number identifying the table. For images to be loaded by Xen 3, the + * magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set). + * - flags + * bit 0: indicates whether the image needs to be loaded on a page boundary + * bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate + * that memory info should be passed to the image) + * bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate + * that the bootloader should pass video mode info to the image) + * bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate + * that the values in the fields header_addr - entry_addr are + * valid) + * All other bits should be set to 0. + * - checksum + * When added to "magic" and "flags", the resulting value should be 0. + * - header_addr + * Contains the virtual address corresponding to the beginning of the + * table - the memory location at which the magic value is supposed to be + * loaded. This field serves to synchronize the mapping between OS image + * offsets and virtual memory addresses. + * - load_addr + * Contains the virtual address of the beginning of the text segment. The + * offset in the OS image file at which to start loading is defined by the + * offset at which the table was found, minus (header addr - load addr). + * load addr must be less than or equal to header addr. + * - load_end_addr + * Contains the virtual address of the end of the data segment. + * (load_end_addr - load_addr) specifies how much data to load. This implies + * that the text and data segments must be consecutive in the OS image. If + * this field is zero, the domain builder assumes that the text and data + * segments occupy the whole OS image file. + * - bss_end_addr + * Contains the virtual address of the end of the bss segment. The domain + * builder initializes this area to zero, and reserves the memory it occupies + * to avoid placing boot modules and other data relevant to the loaded image + * in that area. If this field is zero, the domain builder assumes that no bss + * segment is present. + * - entry_addr + * The virtual address at which to start execution of the loaded image. + * + * Some of the field descriptions were copied from "The Multiboot + * Specification", Copyright 1995, 96 Bryan Ford <baford@xxxxxxxxxxx>, + * Erich Stefan Boleyn <erich@xxxxxxxx> Copyright 1999, 2000, 2001, 2002 + * Free Software Foundation, Inc. + */ + +#include "xc_private.h" +#include <stdlib.h> + +#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) + +struct xen_reactos_table +{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +}; + +#define XEN_REACTOS_MAGIC3 0x336ec578 + +#define XEN_REACTOS_FLAG_ALIGN4K 0x00000001 +#define XEN_REACTOS_FLAG_NEEDMEMINFO 0x00000002 +#define XEN_REACTOS_FLAG_NEEDVIDINFO 0x00000004 +#define XEN_REACTOS_FLAG_ADDRSVALID 0x00010000 + +/* Flags we test for */ +#define FLAGS_MASK ((~ 0) & (~ XEN_REACTOS_FLAG_ALIGN4K)) +#define FLAGS_REQUIRED XEN_REACTOS_FLAG_ADDRSVALID + +static int +parsereactosimage( + char *base, unsigned long size, struct xen_reactos_table **table); +static int +loadreactosimage( + char *image_base, unsigned long image_size, int xch, u32 dom, + unsigned long *parray, struct xen_reactos_table *image_info); + +static int setup_guest(int xc_handle, + u32 dom, + char *image, unsigned long image_size, + int module_fd, unsigned long module_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 l2tab; + unsigned long l1tab; + 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 xen_reactos_table *image_info; + unsigned long vimage_end; + unsigned long vmodule_start; + unsigned long vmodule_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; + + rc = parsereactosimage(image, image_size, &image_info); + if ( rc != 0 ) + goto error_out; + + if ( (image_info->load_addr & (PAGE_SIZE-1)) != 0 ) + { + PERROR("Guest OS must load to a page boundary.\n"); + goto error_out; + } + + /* + * 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. + */ + if ( 0 != image_info->bss_end_addr ) + { + vimage_end = image_info->bss_end_addr; + } + else if ( 0 != image_info->load_end_addr ) + { + vimage_end = image_info->load_end_addr; + } + else + { + vimage_end = image_info->load_addr + image_size; + } + vmodule_start = round_pgup(vimage_end); + vmodule_end = vmodule_start + module_len; + vphysmap_start = round_pgup(vmodule_end); + vphysmap_end = vphysmap_start + (nr_pages * 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 - image_info->load_addr + ((1<<L2_PAGETABLE_SHIFT)-1)) >> + L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) + break; + } + + printf("VIRTUAL MEMORY ARRANGEMENT:\n" + " Loaded image: %08lx->%08lx\n" + " Module: %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", + image_info->load_addr, vimage_end, + vmodule_start, vmodule_end, + vphysmap_start, vphysmap_end, + vpt_start, vpt_end, + vstartinfo_start, vstartinfo_end, + vstack_start, vstack_end, + image_info->load_addr, v_end); + printf(" ENTRY ADDRESS: %08lx\n", image_info->entry_addr); + + if ( (v_end - image_info->load_addr) > (nr_pages * PAGE_SIZE) ) + { + printf("Initial guest OS requires too much space\n" + "(%luMB is greater than %luMB limit)\n", + (v_end-image_info->load_addr)>>20, (nr_pages<<PAGE_SHIFT)>>20); + goto error_out; + } + + if ( (page_array = malloc(nr_pages * 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; + } + + loadreactosimage(image, image_size, xc_handle, dom, page_array, image_info); + + /* Load the initial ramdisk image. */ + if ( module_len != 0 ) + { + for ( i = (vmodule_start - image_info->load_addr); + i < (vmodule_end - image_info->load_addr); i += PAGE_SIZE ) + { + char page[PAGE_SIZE]; + if ( read(module_fd, page, PAGE_SIZE) == -1 ) + { + PERROR("Error reading module 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 - image_info->load_addr) >> PAGE_SHIFT; + l2tab = page_array[ppt_alloc++] << PAGE_SHIFT; + ctxt->pt_base = l2tab; + + /* Initialise the page tables. */ + if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l2tab >> PAGE_SHIFT)) == NULL ) + goto error_out; + memset(vl2tab, 0, PAGE_SIZE); + vl2e = &vl2tab[l2_table_offset(image_info->load_addr)]; + for ( count = 0; count < ((v_end-image_info->load_addr)>>PAGE_SHIFT); count++ ) + { + if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) + { + l1tab = page_array[ppt_alloc++] << PAGE_SHIFT; + if ( vl1tab != NULL ) + munmap(vl1tab, PAGE_SIZE); + if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l1tab >> PAGE_SHIFT)) == NULL ) + { + munmap(vl2tab, PAGE_SIZE); + goto error_out; + } + memset(vl1tab, 0, PAGE_SIZE); + vl1e = &vl1tab[l1_table_offset(image_info->load_addr + (count<<PAGE_SHIFT))]; + *vl2e++ = l1tab | L2_PROT; + } + + *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT; + if ( (count >= ((vpt_start-image_info->load_addr)>>PAGE_SHIFT)) && + (count < ((vpt_end -image_info->load_addr)>>PAGE_SHIFT)) ) + *vl1e &= ~_PAGE_RW; + vl1e++; + } + munmap(vl1tab, PAGE_SIZE); + munmap(vl2tab, PAGE_SIZE); + + /* Write the phys->machine and machine->phys table entries. */ + physmap_pfn = (vphysmap_start - image_info->load_addr) >> 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++ ) + { + if ( add_mmu_update(xc_handle, mmu, + (page_array[count] << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, count) ) + { + munmap(physmap, PAGE_SIZE); + goto error_out; + } + *physmap_e++ = page_array[count]; + 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++]); + } + } + munmap(physmap, PAGE_SIZE); + + /* + * Pin down l2tab addr as page dir page - causes hypervisor to provide + * correct protection for the page + */ + if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, l2tab>>PAGE_SHIFT, dom) ) + goto error_out; + + start_info = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, + page_array[(vstartinfo_start-image_info->load_addr)>>PAGE_SHIFT]); + memset(start_info, 0, sizeof(*start_info)); + start_info->nr_pages = nr_pages; + start_info->shared_info = shared_info_frame << 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 ( module_len != 0 ) + { + start_info->mod_start = vmodule_start; + start_info->mod_len = module_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); + + /* 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 = image_info->entry_addr; + + return 0; + + error_out: + if ( mmu != NULL ) + free(mmu); + if ( page_array != NULL ) + free(page_array); + return -1; +} + +int xc_reactos_build(int xc_handle, + u32 domid, + const char *image_name, + const char *module_name, + const char *cmdline, + unsigned int control_evtchn, + unsigned long flags, + unsigned int vcpus) +{ + dom0_op_t launch_op, op; + int module_fd = -1; + int rc, i; + vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; + unsigned long nr_pages; + char *image = NULL; + unsigned long image_size, module_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 ( (module_name != NULL) && (strlen(module_name) != 0) ) + { + if ( (module_fd = open(module_name, O_RDONLY)) < 0 ) + { + PERROR("Could not open the module image"); + goto error_out; + } + + module_size = xc_get_filesz(module_fd); + } + + 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, + module_fd, module_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 ( module_fd >= 0 ) + close(module_fd); + 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 ( module_fd >= 0 ) + close(module_fd); + if ( image != NULL ) + free(image); + + return -1; +} + +static int parsereactosimage(char *base, + unsigned long size, + struct xen_reactos_table **table) +{ + unsigned long *probe_ptr; + unsigned probe_index; + unsigned probe_count; + + /* Don't go outside the image */ + if ( size < sizeof(struct xen_reactos_table) ) + { + ERROR("Image does not have a valid xen_reactos table."); + return -EINVAL; + } + probe_count = size; + /* Restrict to first 8k */ + if ( 8192 < probe_count ) + { + probe_count = 8192; + } + probe_count = (probe_count - sizeof(struct xen_reactos_table)) / + sizeof(unsigned long); + + /* Search for the magic header */ + probe_ptr = (unsigned long *) base; + *table = NULL; + for ( probe_index = 0; probe_index < probe_count; probe_index++ ) + { + if ( XEN_REACTOS_MAGIC3 == *probe_ptr ) + { + *table = (struct xen_reactos_table *) probe_ptr; + /* Checksum correct? */ + if ( 0 == (*table)->magic + (*table)->flags + (*table)->checksum ) + { + break; + } + *table = NULL; + } + probe_ptr++; + } + if ( NULL == *table ) + { + ERROR("Image does not have a valid xen_reactos table."); + return -EINVAL; + } + if ( FLAGS_REQUIRED != ((*table)->flags & FLAGS_MASK) ) + { + ERROR("xen_reactos flags required 0x%08x found 0x%08lx", FLAGS_REQUIRED, + (*table)->flags & FLAGS_MASK); + return -EINVAL; + } + + return 0; +} + +static int +loadreactosimage( + char *image_base, unsigned long image_size, int xch, u32 dom, + unsigned long *parray, struct xen_reactos_table *image_info) +{ + unsigned long size; + char *va; + unsigned long done, chunksz; + + /* Determine image size */ + if ( 0 == image_info->load_end_addr ) + { + size = image_size - (((char *) image_info - image_base) - + (image_info->header_addr - + image_info->load_addr)); + } + else + { + size = image_info->load_end_addr - image_info->load_addr; + } + + /* It's possible that we need to skip the first part of the image */ + image_base += ((char *)image_info - image_base) - + (image_info->header_addr - image_info->load_addr); + + for ( done = 0; done < size; done += chunksz ) + { + va = xc_map_foreign_range( + xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]); + chunksz = size - done; + if ( chunksz > PAGE_SIZE ) + chunksz = PAGE_SIZE; + memcpy(va, image_base + done, chunksz); + munmap(va, PAGE_SIZE); + } + + if ( 0 != image_info->bss_end_addr && + image_info->load_addr + size < image_info->bss_end_addr ) + { + size = image_info->bss_end_addr - image_info->load_addr; + } + for ( ; done < size; done += chunksz ) + { + va = xc_map_foreign_range( + xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]); + chunksz = size - done; + if ( chunksz > (PAGE_SIZE - (done & (PAGE_SIZE-1))) ) + chunksz = PAGE_SIZE - (done & (PAGE_SIZE-1)); + memset(va + (done & (PAGE_SIZE-1)), 0, chunksz); + munmap(va, PAGE_SIZE); + } + + return 0; +} _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |