[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] domain builder for ReactOS


  • To: xen-devel@xxxxxxxxxxxxxxxxxxx
  • From: Ge van Geldorp <gvg@xxxxxxxxxxx>
  • Date: Thu, 2 Jun 2005 23:51:59 +0200
  • Delivery-date: Thu, 02 Jun 2005 21:51:14 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.