WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] domain builder for ReactOS
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
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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