ia64/xen-unstable

changeset 975:0cac9d16969a

bitkeeper revision 1.627.1.1 (3fbf4befPIgRjU40eyhadjRuioWcwA)

Many files:
Lib renames and fixes. Only build shared version of libxc, as the static archive version caused too many problems.
xc_vif.c:
Rename: tools/xc/lib/libxc_vif.c -> tools/xc/lib/xc_vif.c
xc_vbd.c:
Rename: tools/xc/lib/libxc_vbd.c -> tools/xc/lib/xc_vbd.c
xc_private.h:
Rename: tools/xc/lib/libxc_private.h -> tools/xc/lib/xc_private.h
xc_private.c:
Rename: tools/xc/lib/libxc_private.c -> tools/xc/lib/xc_private.c
xc_misc.c:
Rename: tools/xc/lib/libxc_misc.c -> tools/xc/lib/xc_misc.c
xc_linux_restore.c:
Rename: tools/xc/lib/libxc_linux_restore.c -> tools/xc/lib/xc_linux_restore.c
xc_linux_save.c:
Rename: tools/xc/lib/libxc_linux_save.c -> tools/xc/lib/xc_linux_save.c
xc_linux_build.c:
Rename: tools/xc/lib/libxc_linux_build.c -> tools/xc/lib/xc_linux_build.c
xc_domain.c:
Rename: tools/xc/lib/libxc_domain.c -> tools/xc/lib/xc_domain.c
xc_bvtsched.c:
Rename: tools/xc/lib/libxc_bvtsched.c -> tools/xc/lib/xc_bvtsched.c
author kaf24@scramble.cl.cam.ac.uk
date Sat Nov 22 11:43:43 2003 +0000 (2003-11-22)
parents 9c7b2b238a29
children 2b1d395d801a
files .rootkeys tools/xc/lib/Makefile tools/xc/lib/libxc_bvtsched.c tools/xc/lib/libxc_domain.c tools/xc/lib/libxc_linux_build.c tools/xc/lib/libxc_linux_restore.c tools/xc/lib/libxc_linux_save.c tools/xc/lib/libxc_misc.c tools/xc/lib/libxc_private.c tools/xc/lib/libxc_private.h tools/xc/lib/libxc_vbd.c tools/xc/lib/libxc_vif.c tools/xc/lib/xc_bvtsched.c tools/xc/lib/xc_domain.c tools/xc/lib/xc_linux_build.c tools/xc/lib/xc_linux_restore.c tools/xc/lib/xc_linux_save.c tools/xc/lib/xc_misc.c tools/xc/lib/xc_private.c tools/xc/lib/xc_private.h tools/xc/lib/xc_vbd.c tools/xc/lib/xc_vif.c tools/xc/py/Makefile tools/xc/py/setup.py
line diff
     1.1 --- a/.rootkeys	Fri Nov 21 16:46:39 2003 +0000
     1.2 +++ b/.rootkeys	Sat Nov 22 11:43:43 2003 +0000
     1.3 @@ -59,18 +59,18 @@ 3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/mis
     1.4  3f87ba90EUVPQLVOlFG0sW89BCwouQ tools/misc/xen_refresh_dev.c
     1.5  3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
     1.6  3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/xc/lib/Makefile
     1.7 -3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/libxc_bvtsched.c
     1.8 -3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/libxc_domain.c
     1.9 -3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/libxc_linux_build.c
    1.10 -3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/libxc_linux_restore.c
    1.11 -3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/libxc_linux_save.c
    1.12 -3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/libxc_misc.c
    1.13 -3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/libxc_private.c
    1.14 -3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/libxc_private.h
    1.15 -3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/libxc_vbd.c
    1.16 -3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/xc/lib/libxc_vif.c
    1.17  3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/lib/rpm.spec
    1.18  3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/xc/lib/xc.h
    1.19 +3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/xc_bvtsched.c
    1.20 +3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/xc_domain.c
    1.21 +3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/xc_linux_build.c
    1.22 +3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/xc_linux_restore.c
    1.23 +3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
    1.24 +3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/xc_misc.c
    1.25 +3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/xc_private.c
    1.26 +3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/xc_private.h
    1.27 +3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/xc_vbd.c
    1.28 +3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/xc/lib/xc_vif.c
    1.29  3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile
    1.30  3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c
    1.31  3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xc/py/XenoUtil.py
     2.1 --- a/tools/xc/lib/Makefile	Fri Nov 21 16:46:39 2003 +0000
     2.2 +++ b/tools/xc/lib/Makefile	Sat Nov 22 11:43:43 2003 +0000
     2.3 @@ -4,12 +4,11 @@ CFLAGS   = -c -Wall -O3
     2.4  CFLAGS  += -I../../../xen/include -I../../../xenolinux-sparse/include
     2.5  
     2.6  HDRS     = $(wildcard *.h)
     2.7 -OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
     2.8 +OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
     2.9  
    2.10 -LIBS     = libxc.a libxc.so
    2.11 +LIB      = libxc.so
    2.12  
    2.13 -all: check-for-zlib $(LIBS)
    2.14 -	ranlib libxc.a
    2.15 +all: check-for-zlib $(LIB)
    2.16  
    2.17  check-for-zlib:
    2.18  	@if [ ! -e /usr/include/zlib.h ]; then \
    2.19 @@ -22,21 +21,21 @@ check-for-zlib:
    2.20  install: all
    2.21  	mkdir -p /usr/lib
    2.22  	mkdir -p /usr/include
    2.23 -	cp -a $(LIBS) /usr/lib
    2.24 -	for i in $(LIBS); do chmod 755 /usr/bin/$i ; done
    2.25 +	cp -a $(LIB) /usr/lib
    2.26 +	for i in $(LIB); do chmod 755 /usr/bin/$i ; done
    2.27  	cp -a xc.h /usr/include
    2.28  	chmod 644 /usr/include/xc.h
    2.29  
    2.30  dist: all
    2.31  	mkdir -p ../../../../install/lib
    2.32  	mkdir -p ../../../../install/include
    2.33 -	cp -a $(LIBS) ../../../../install/lib
    2.34 -	for i in $(LIBS); do chmod 755 ../../../../install/bin/$i ; done
    2.35 +	cp -a $(LIB) ../../../../install/lib
    2.36 +	for i in $(LIB); do chmod 755 ../../../../install/bin/$i ; done
    2.37  	cp -a xc.h ../../../../install/include
    2.38  	chmod 644 ../../../../install/include/xc.h
    2.39  
    2.40  clean:
    2.41 -	$(RM) *.a *.so *.o *.rpm $(LIBS)
    2.42 +	$(RM) *.a *.so *.o *.rpm $(LIB)
    2.43  
    2.44  rpm: all
    2.45  	rm -rf staging
    2.46 @@ -50,7 +49,5 @@ rpm: all
    2.47  libxc.so: $(OBJS)
    2.48  	$(LD) -shared -o $@ $^ -lz
    2.49  
    2.50 -libxc.a: libxc.a($(OBJS))
    2.51 -
    2.52  %.o: %.c $(HDRS) Makefile
    2.53  	$(CC) $(CFLAGS) -o $@ $<
     3.1 --- a/tools/xc/lib/libxc_bvtsched.c	Fri Nov 21 16:46:39 2003 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,35 +0,0 @@
     3.4 -/******************************************************************************
     3.5 - * libxc_bvtsched.c
     3.6 - * 
     3.7 - * API for manipulating parameters of the Borrowed Virtual Time scheduler.
     3.8 - * 
     3.9 - * Copyright (c) 2003, K A Fraser.
    3.10 - */
    3.11 -
    3.12 -#include "libxc_private.h"
    3.13 -
    3.14 -int xc_bvtsched_global_set(int xc_handle,
    3.15 -                           unsigned long ctx_allow)
    3.16 -{
    3.17 -    dom0_op_t op;
    3.18 -    op.cmd = DOM0_BVTCTL;
    3.19 -    op.u.bvtctl.ctx_allow = ctx_allow;
    3.20 -    return do_dom0_op(xc_handle, &op);
    3.21 -}
    3.22 -
    3.23 -int xc_bvtsched_domain_set(int xc_handle,
    3.24 -                           unsigned int domid,
    3.25 -                           unsigned long mcuadv,
    3.26 -                           unsigned long warp,
    3.27 -                           unsigned long warpl,
    3.28 -                           unsigned long warpu)
    3.29 -{
    3.30 -    dom0_op_t op;
    3.31 -    op.cmd = DOM0_ADJUSTDOM;
    3.32 -    op.u.adjustdom.domain  = domid;
    3.33 -    op.u.adjustdom.mcu_adv = mcuadv;
    3.34 -    op.u.adjustdom.warp    = warp;
    3.35 -    op.u.adjustdom.warpl   = warpl;
    3.36 -    op.u.adjustdom.warpu   = warpu;
    3.37 -    return do_dom0_op(xc_handle, &op);
    3.38 -}
     4.1 --- a/tools/xc/lib/libxc_domain.c	Fri Nov 21 16:46:39 2003 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,88 +0,0 @@
     4.4 -/******************************************************************************
     4.5 - * libxc_domain.c
     4.6 - * 
     4.7 - * API for manipulating and obtaining information on domains.
     4.8 - * 
     4.9 - * Copyright (c) 2003, K A Fraser.
    4.10 - */
    4.11 -
    4.12 -#include "libxc_private.h"
    4.13 -
    4.14 -int xc_domain_create(int xc_handle,
    4.15 -                     unsigned int mem_kb, 
    4.16 -                     const char *name)
    4.17 -{
    4.18 -    int err;
    4.19 -    dom0_op_t op;
    4.20 -
    4.21 -    op.cmd = DOM0_CREATEDOMAIN;
    4.22 -    op.u.createdomain.memory_kb = mem_kb;
    4.23 -    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
    4.24 -    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
    4.25 -
    4.26 -    err = do_dom0_op(xc_handle, &op);
    4.27 -
    4.28 -    return (err < 0) ? err : op.u.createdomain.domain;
    4.29 -}    
    4.30 -
    4.31 -
    4.32 -int xc_domain_start(int xc_handle,
    4.33 -                    unsigned int domid)
    4.34 -{
    4.35 -    dom0_op_t op;
    4.36 -    op.cmd = DOM0_STARTDOMAIN;
    4.37 -    op.u.startdomain.domain = domid;
    4.38 -    return do_dom0_op(xc_handle, &op);
    4.39 -}    
    4.40 -
    4.41 -
    4.42 -int xc_domain_stop(int xc_handle, 
    4.43 -                   unsigned int domid)
    4.44 -{
    4.45 -    dom0_op_t op;
    4.46 -    op.cmd = DOM0_STOPDOMAIN;
    4.47 -    op.u.stopdomain.domain = domid;
    4.48 -    return do_dom0_op(xc_handle, &op);
    4.49 -}    
    4.50 -
    4.51 -
    4.52 -int xc_domain_destroy(int xc_handle,
    4.53 -                      unsigned int domid, 
    4.54 -                      int force)
    4.55 -{
    4.56 -    dom0_op_t op;
    4.57 -    op.cmd = DOM0_DESTROYDOMAIN;
    4.58 -    op.u.destroydomain.domain = domid;
    4.59 -    op.u.destroydomain.force  = !!force;
    4.60 -    return do_dom0_op(xc_handle, &op);
    4.61 -}
    4.62 -
    4.63 -int xc_domain_getinfo(int xc_handle,
    4.64 -                      unsigned int first_domid,
    4.65 -                      unsigned int max_doms,
    4.66 -                      xc_dominfo_t *info)
    4.67 -{
    4.68 -    unsigned int nr_doms, next_domid = first_domid;
    4.69 -    dom0_op_t op;
    4.70 -
    4.71 -    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
    4.72 -    {
    4.73 -        op.cmd = DOM0_GETDOMAININFO;
    4.74 -        op.u.getdomaininfo.domain = next_domid;
    4.75 -        if ( do_dom0_op(xc_handle, &op) < 0 )
    4.76 -            break;
    4.77 -        info->domid   = op.u.getdomaininfo.domain;
    4.78 -        info->cpu     = op.u.getdomaininfo.processor;
    4.79 -        info->has_cpu = op.u.getdomaininfo.has_cpu;
    4.80 -        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
    4.81 -        info->nr_pages = op.u.getdomaininfo.tot_pages;
    4.82 -        info->cpu_time = op.u.getdomaininfo.cpu_time;
    4.83 -        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
    4.84 -        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
    4.85 -
    4.86 -        next_domid = op.u.getdomaininfo.domain + 1;
    4.87 -        info++;
    4.88 -    }
    4.89 -
    4.90 -    return nr_doms;
    4.91 -}
     5.1 --- a/tools/xc/lib/libxc_linux_build.c	Fri Nov 21 16:46:39 2003 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,478 +0,0 @@
     5.4 -/******************************************************************************
     5.5 - * libxc_linux_build.c
     5.6 - */
     5.7 -
     5.8 -#include "libxc_private.h"
     5.9 -#include <zlib.h>
    5.10 -
    5.11 -/* This string is written to the head of every guest kernel image. */
    5.12 -#define GUEST_SIG   "XenoGues"
    5.13 -#define SIG_LEN    8
    5.14 -
    5.15 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    5.16 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    5.17 -
    5.18 -static long get_tot_pages(int xc_handle, int domid)
    5.19 -{
    5.20 -    dom0_op_t op;
    5.21 -    op.cmd = DOM0_GETDOMAININFO;
    5.22 -    op.u.getdomaininfo.domain = domid;
    5.23 -    return (do_dom0_op(xc_handle, &op) < 0) ? 
    5.24 -        -1 : op.u.getdomaininfo.tot_pages;
    5.25 -}
    5.26 -
    5.27 -static int get_pfn_list(int xc_handle,
    5.28 -                        int domid, 
    5.29 -                        unsigned long *pfn_buf, 
    5.30 -                        unsigned long max_pfns)
    5.31 -{
    5.32 -    dom0_op_t op;
    5.33 -    int ret;
    5.34 -    op.cmd = DOM0_GETMEMLIST;
    5.35 -    op.u.getmemlist.domain   = domid;
    5.36 -    op.u.getmemlist.max_pfns = max_pfns;
    5.37 -    op.u.getmemlist.buffer   = pfn_buf;
    5.38 -
    5.39 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    5.40 -        return -1;
    5.41 -
    5.42 -    ret = do_dom0_op(xc_handle, &op);
    5.43 -
    5.44 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    5.45 -
    5.46 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    5.47 -}
    5.48 -
    5.49 -static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates)
    5.50 -{
    5.51 -    int ret = -1;
    5.52 -    privcmd_hypercall_t hypercall;
    5.53 -
    5.54 -    hypercall.op     = __HYPERVISOR_mmu_update;
    5.55 -    hypercall.arg[0] = (unsigned long)updates;
    5.56 -    hypercall.arg[1] = (unsigned long)nr_updates;
    5.57 -
    5.58 -    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
    5.59 -        goto out1;
    5.60 -
    5.61 -    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
    5.62 -        goto out2;
    5.63 -
    5.64 -    ret = 0;
    5.65 -
    5.66 - out2: (void)munlock(updates, nr_updates * sizeof(*updates));
    5.67 - out1: return ret;
    5.68 -}
    5.69 -
    5.70 -/* Read the kernel header, extracting the image size and load address. */
    5.71 -static int read_kernel_header(gzFile gfd, long dom_size, 
    5.72 -                              unsigned long *load_addr)
    5.73 -{
    5.74 -    char signature[SIG_LEN];
    5.75 -
    5.76 -    gzread(gfd, signature, SIG_LEN);
    5.77 -    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
    5.78 -    {
    5.79 -        ERROR("Kernel image does not contain required signature");
    5.80 -        return -1;
    5.81 -    }
    5.82 -
    5.83 -    /* Read the load address which immediately follows the Xeno signature. */
    5.84 -    gzread(gfd, load_addr, sizeof(unsigned long));
    5.85 -
    5.86 -    return 0;
    5.87 -}
    5.88 -
    5.89 -static int copy_to_domain_page(int pm_handle,
    5.90 -                               unsigned long dst_pfn, 
    5.91 -                               void *src_page)
    5.92 -{
    5.93 -    void *vaddr = map_pfn(pm_handle, dst_pfn);
    5.94 -    if ( vaddr == NULL )
    5.95 -        return -1;
    5.96 -    memcpy(vaddr, src_page, PAGE_SIZE);
    5.97 -    unmap_pfn(pm_handle, vaddr);
    5.98 -    return 0;
    5.99 -}
   5.100 -
   5.101 -static int setup_guestos(int xc_handle,
   5.102 -                         int dom, 
   5.103 -                         gzFile kernel_gfd, 
   5.104 -                         int initrd_fd, 
   5.105 -                         unsigned long tot_pages,
   5.106 -                         unsigned long *virt_startinfo_addr, 
   5.107 -                         unsigned long virt_load_addr, 
   5.108 -                         dom0_builddomain_t *builddomain, 
   5.109 -                         const char *cmdline,
   5.110 -                         unsigned long shared_info_frame)
   5.111 -{
   5.112 -    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
   5.113 -    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
   5.114 -    unsigned long *page_array = NULL;
   5.115 -    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
   5.116 -    int alloc_index, num_pt_pages;
   5.117 -    unsigned long l2tab;
   5.118 -    unsigned long l1tab = 0;
   5.119 -    unsigned long num_pgt_updates = 0;
   5.120 -    unsigned long count, pt_start, i, j;
   5.121 -    unsigned long initrd_addr = 0, initrd_len = 0;
   5.122 -    start_info_t *start_info;
   5.123 -    shared_info_t *shared_info;
   5.124 -    unsigned long ksize;
   5.125 -    int pm_handle;
   5.126 -
   5.127 -    memset(builddomain, 0, sizeof(*builddomain));
   5.128 -
   5.129 -    if ( (pm_handle = init_pfn_mapper()) < 0 )
   5.130 -        goto error_out;
   5.131 -
   5.132 -    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
   5.133 -    page_array = malloc(tot_pages * sizeof(unsigned long));
   5.134 -    pgt_update_arr = pgt_updates;
   5.135 -    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
   5.136 -    {
   5.137 -        PERROR("Could not allocate memory");
   5.138 -        goto error_out;
   5.139 -    }
   5.140 -
   5.141 -    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
   5.142 -    {
   5.143 -        PERROR("Could not get the page frame list");
   5.144 -        goto error_out;
   5.145 -    }
   5.146 -
   5.147 -    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
   5.148 -    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
   5.149 -    {
   5.150 -        char page[PAGE_SIZE];
   5.151 -        int size;
   5.152 -        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
   5.153 -        {
   5.154 -            PERROR("Error reading kernel image, could not"
   5.155 -                   " read the whole image.");
   5.156 -            goto error_out;
   5.157 -        }
   5.158 -        if ( size == 0 )
   5.159 -            goto kernel_copied;
   5.160 -        copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
   5.161 -    }
   5.162 -    ERROR("Kernel too big to safely fit in domain memory");
   5.163 -    goto error_out;
   5.164 -
   5.165 - kernel_copied:
   5.166 -    /* ksize is kernel-image size rounded up to a page boundary. */
   5.167 -    ksize = i;
   5.168 -
   5.169 -    /* Load the initial ramdisk image. */
   5.170 -    if ( initrd_fd >= 0 )
   5.171 -    {
   5.172 -        struct stat stat;
   5.173 -        unsigned long isize;
   5.174 -
   5.175 -        if ( fstat(initrd_fd, &stat) < 0 )
   5.176 -        {
   5.177 -            PERROR("Could not stat the initrd image");
   5.178 -            goto error_out;
   5.179 -        }
   5.180 -        isize = stat.st_size;
   5.181 -        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
   5.182 -        {
   5.183 -            ERROR("Kernel/initrd too big to safely fit in domain memory");
   5.184 -            goto error_out;
   5.185 -        }
   5.186 -
   5.187 -        initrd_addr = virt_load_addr + ksize;
   5.188 -        initrd_len  = isize;
   5.189 -
   5.190 -        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
   5.191 -        {
   5.192 -            char page[PAGE_SIZE];
   5.193 -            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
   5.194 -            if ( read(initrd_fd, page, size) != size )
   5.195 -            {
   5.196 -                PERROR("Error reading initrd image, could not"
   5.197 -                       " read the whole image.");
   5.198 -                goto error_out;
   5.199 -            } 
   5.200 -            copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
   5.201 -        }
   5.202 -    }
   5.203 -
   5.204 -    alloc_index = tot_pages - 1;
   5.205 -
   5.206 -    /* Count bottom-level PTs, rounding up. */
   5.207 -    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
   5.208 -
   5.209 -    /* We must also count the page directory. */
   5.210 -    num_pt_pages++;
   5.211 -
   5.212 -    /* Index of first PT page. */
   5.213 -    pt_start = tot_pages - num_pt_pages;
   5.214 -
   5.215 -    /*
   5.216 -     * First allocate page for page dir. Allocation goes backwards from the end
   5.217 -     * of the allocated physical address space.
   5.218 -     */
   5.219 -    l2tab = page_array[alloc_index] << PAGE_SHIFT;
   5.220 -    alloc_index--;
   5.221 -    builddomain->ctxt.pt_base = l2tab;
   5.222 -
   5.223 -    /*
   5.224 -     * Pin down l2tab addr as page dir page - causes hypervisor to provide
   5.225 -     * correct protection for the page
   5.226 -     */ 
   5.227 -    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
   5.228 -    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
   5.229 -    pgt_updates++;
   5.230 -    num_pgt_updates++;
   5.231 -
   5.232 -    /* Initialise the page tables. */
   5.233 -    if ( (vl2tab = map_pfn(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
   5.234 -        goto error_out;
   5.235 -    memset(vl2tab, 0, PAGE_SIZE);
   5.236 -    vl2e = vl2tab + l2_table_offset(virt_load_addr);
   5.237 -    for ( count = 0; count < tot_pages; count++ )
   5.238 -    {    
   5.239 -        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
   5.240 -        {
   5.241 -            l1tab = page_array[alloc_index] << PAGE_SHIFT;
   5.242 -            if ( (vl1tab = map_pfn(pm_handle, l1tab >> PAGE_SHIFT)) == NULL )
   5.243 -                goto error_out;
   5.244 -            memset(vl1tab, 0, PAGE_SIZE);
   5.245 -            alloc_index--;
   5.246 -		
   5.247 -            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
   5.248 -                                            (count << PAGE_SHIFT));
   5.249 -
   5.250 -            /* make apropriate entry in the page directory */
   5.251 -            pgt_updates->ptr = (unsigned long)vl2e;
   5.252 -            pgt_updates->val = l1tab | L2_PROT;
   5.253 -            pgt_updates++;
   5.254 -            num_pgt_updates++;
   5.255 -            vl2e++;
   5.256 -        }
   5.257 -
   5.258 -        if ( count < pt_start )
   5.259 -        {
   5.260 -            pgt_updates->ptr = (unsigned long)vl1e;
   5.261 -            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
   5.262 -            pgt_updates++;
   5.263 -            num_pgt_updates++;
   5.264 -            vl1e++;
   5.265 -        }
   5.266 -        else
   5.267 -        {
   5.268 -            pgt_updates->ptr = (unsigned long)vl1e;
   5.269 -            pgt_updates->val = 
   5.270 -                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
   5.271 -            pgt_updates++;
   5.272 -            num_pgt_updates++;
   5.273 -            vl1e++;
   5.274 -        }
   5.275 -
   5.276 -        pgt_updates->ptr = 
   5.277 -            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   5.278 -        pgt_updates->val = count;
   5.279 -        pgt_updates++;
   5.280 -        num_pgt_updates++;
   5.281 -    }
   5.282 -
   5.283 -    *virt_startinfo_addr =
   5.284 -        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
   5.285 -
   5.286 -    start_info = map_pfn(pm_handle, page_array[alloc_index-1]);
   5.287 -    memset(start_info, 0, sizeof(*start_info));
   5.288 -    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
   5.289 -    start_info->mod_start   = initrd_addr;
   5.290 -    start_info->mod_len     = initrd_len;
   5.291 -    start_info->nr_pages    = tot_pages;
   5.292 -    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
   5.293 -    start_info->dom_id      = dom;
   5.294 -    start_info->flags       = 0;
   5.295 -    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
   5.296 -    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
   5.297 -
   5.298 -    unmap_pfn(pm_handle, start_info);
   5.299 -
   5.300 -    /* shared_info page starts its life empty. */
   5.301 -    shared_info = map_pfn(pm_handle, shared_info_frame);
   5.302 -    memset(shared_info, 0, PAGE_SIZE);
   5.303 -    unmap_pfn(pm_handle, shared_info);
   5.304 -
   5.305 -    /* Send the page update requests down to the hypervisor. */
   5.306 -    if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 )
   5.307 -        goto error_out;
   5.308 -
   5.309 -    free(page_array);
   5.310 -    free(pgt_update_arr);
   5.311 -    return 0;
   5.312 -
   5.313 - error_out:
   5.314 -    if ( pm_handle >= 0 )
   5.315 -        (void)close_pfn_mapper(pm_handle);
   5.316 -    if ( page_array == NULL )
   5.317 -        free(page_array);
   5.318 -    if ( pgt_update_arr == NULL )
   5.319 -        free(pgt_update_arr);
   5.320 -    return -1;
   5.321 -}
   5.322 -
   5.323 -int xc_linux_build(int xc_handle,
   5.324 -                   unsigned int domid,
   5.325 -                   const char *image_name,
   5.326 -                   const char *ramdisk_name,
   5.327 -                   const char *cmdline)
   5.328 -{
   5.329 -    dom0_op_t launch_op, op;
   5.330 -    unsigned long load_addr;
   5.331 -    long tot_pages;
   5.332 -    int kernel_fd, initrd_fd = -1;
   5.333 -    gzFile kernel_gfd;
   5.334 -    int rc, i;
   5.335 -    full_execution_context_t *ctxt;
   5.336 -    unsigned long virt_startinfo_addr;
   5.337 -
   5.338 -    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
   5.339 -    {
   5.340 -        PERROR("Could not find total pages for domain");
   5.341 -        return 1;
   5.342 -    }
   5.343 -
   5.344 -    kernel_fd = open(image_name, O_RDONLY);
   5.345 -    if ( kernel_fd < 0 )
   5.346 -    {
   5.347 -        PERROR("Could not open kernel image");
   5.348 -        return 1;
   5.349 -    }
   5.350 -
   5.351 -    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
   5.352 -    {
   5.353 -        PERROR("Could not allocate decompression state for state file");
   5.354 -        close(kernel_fd);
   5.355 -        return 1;
   5.356 -    }
   5.357 -
   5.358 -    rc = read_kernel_header(kernel_gfd,
   5.359 -                            tot_pages << (PAGE_SHIFT - 10), 
   5.360 -                            &load_addr);
   5.361 -    if ( rc < 0 )
   5.362 -        goto error_out;
   5.363 -    
   5.364 -    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
   5.365 -    {
   5.366 -        ERROR("We can only deal with page-aligned load addresses");
   5.367 -        goto error_out;
   5.368 -    }
   5.369 -
   5.370 -    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
   5.371 -    {
   5.372 -        ERROR("Cannot map all domain memory without hitting Xen space");
   5.373 -        goto error_out;
   5.374 -    }
   5.375 -
   5.376 -    if ( ramdisk_name != NULL )
   5.377 -    {
   5.378 -        initrd_fd = open(ramdisk_name, O_RDONLY);
   5.379 -        if ( initrd_fd < 0 )
   5.380 -        {
   5.381 -            PERROR("Could not open the initial ramdisk image");
   5.382 -            goto error_out;
   5.383 -        }
   5.384 -    }
   5.385 -
   5.386 -    op.cmd = DOM0_GETDOMAININFO;
   5.387 -    op.u.getdomaininfo.domain = domid;
   5.388 -    if ( (do_dom0_op(xc_handle, &op) < 0) || 
   5.389 -         (op.u.getdomaininfo.domain != domid) )
   5.390 -    {
   5.391 -        PERROR("Could not get info on domain");
   5.392 -        goto error_out;
   5.393 -    }
   5.394 -    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
   5.395 -         (op.u.getdomaininfo.ctxt.pt_base != 0) )
   5.396 -    {
   5.397 -        ERROR("Domain is already constructed");
   5.398 -        goto error_out;
   5.399 -    }
   5.400 -
   5.401 -    if ( setup_guestos(xc_handle, domid, kernel_gfd, initrd_fd, tot_pages,
   5.402 -                       &virt_startinfo_addr,
   5.403 -                       load_addr, &launch_op.u.builddomain, cmdline,
   5.404 -                       op.u.getdomaininfo.shared_info_frame) < 0 )
   5.405 -    {
   5.406 -        ERROR("Error constructing guest OS");
   5.407 -        goto error_out;
   5.408 -    }
   5.409 -
   5.410 -    if ( initrd_fd >= 0 )
   5.411 -        close(initrd_fd);
   5.412 -    gzclose(kernel_gfd);
   5.413 -
   5.414 -    ctxt = &launch_op.u.builddomain.ctxt;
   5.415 -
   5.416 -    ctxt->flags = 0;
   5.417 -
   5.418 -    /*
   5.419 -     * Initial register values:
   5.420 -     *  DS,ES,FS,GS = FLAT_RING1_DS
   5.421 -     *       CS:EIP = FLAT_RING1_CS:start_pc
   5.422 -     *       SS:ESP = FLAT_RING1_DS:start_stack
   5.423 -     *          ESI = start_info
   5.424 -     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
   5.425 -     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
   5.426 -     */
   5.427 -    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
   5.428 -    ctxt->i386_ctxt.es = FLAT_RING1_DS;
   5.429 -    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
   5.430 -    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
   5.431 -    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
   5.432 -    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
   5.433 -    ctxt->i386_ctxt.eip = load_addr;
   5.434 -    ctxt->i386_ctxt.esp = virt_startinfo_addr;
   5.435 -    ctxt->i386_ctxt.esi = virt_startinfo_addr;
   5.436 -    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
   5.437 -
   5.438 -    /* FPU is set up to default initial state. */
   5.439 -    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
   5.440 -
   5.441 -    /* Virtual IDT is empty at start-of-day. */
   5.442 -    for ( i = 0; i < 256; i++ )
   5.443 -    {
   5.444 -        ctxt->trap_ctxt[i].vector = i;
   5.445 -        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
   5.446 -    }
   5.447 -    ctxt->fast_trap_idx = 0;
   5.448 -
   5.449 -    /* No LDT. */
   5.450 -    ctxt->ldt_ents = 0;
   5.451 -    
   5.452 -    /* Use the default Xen-provided GDT. */
   5.453 -    ctxt->gdt_ents = 0;
   5.454 -
   5.455 -    /* Ring 1 stack is the initial stack. */
   5.456 -    ctxt->ring1_ss  = FLAT_RING1_DS;
   5.457 -    ctxt->ring1_esp = virt_startinfo_addr;
   5.458 -
   5.459 -    /* No debugging. */
   5.460 -    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
   5.461 -
   5.462 -    /* No callback handlers. */
   5.463 -    ctxt->event_callback_cs     = FLAT_RING1_CS;
   5.464 -    ctxt->event_callback_eip    = 0;
   5.465 -    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
   5.466 -    ctxt->failsafe_callback_eip = 0;
   5.467 -
   5.468 -    launch_op.u.builddomain.domain   = domid;
   5.469 -    launch_op.u.builddomain.num_vifs = 1;
   5.470 -
   5.471 -    launch_op.cmd = DOM0_BUILDDOMAIN;
   5.472 -    rc = do_dom0_op(xc_handle, &launch_op);
   5.473 -    
   5.474 -    return rc;
   5.475 -
   5.476 - error_out:
   5.477 -    if ( initrd_fd >= 0 )
   5.478 -        close(initrd_fd);
   5.479 -    gzclose(kernel_gfd);
   5.480 -    return -1;
   5.481 -}
     6.1 --- a/tools/xc/lib/libxc_linux_restore.c	Fri Nov 21 16:46:39 2003 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,488 +0,0 @@
     6.4 -/******************************************************************************
     6.5 - * libxc_linux_restore.c
     6.6 - * 
     6.7 - * Restore the state of a Xenolinux session.
     6.8 - * 
     6.9 - * Copyright (c) 2003, K A Fraser.
    6.10 - */
    6.11 -
    6.12 -#include "libxc_private.h"
    6.13 -#include <asm-xeno/suspend.h>
    6.14 -#include <zlib.h>
    6.15 -
    6.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
    6.17 -#define verbose_printf(_f, _a...) \
    6.18 -    do {                          \
    6.19 -        if ( !verbose ) break;    \
    6.20 -        printf( _f , ## _a );     \
    6.21 -        fflush(stdout);           \
    6.22 -    } while ( 0 )
    6.23 -
    6.24 -static int get_pfn_list(int xc_handle,
    6.25 -                        int domain_id, 
    6.26 -                        unsigned long *pfn_buf, 
    6.27 -                        unsigned long max_pfns)
    6.28 -{
    6.29 -    dom0_op_t op;
    6.30 -    int ret;
    6.31 -    op.cmd = DOM0_GETMEMLIST;
    6.32 -    op.u.getmemlist.domain   = domain_id;
    6.33 -    op.u.getmemlist.max_pfns = max_pfns;
    6.34 -    op.u.getmemlist.buffer   = pfn_buf;
    6.35 -
    6.36 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    6.37 -    {
    6.38 -        PERROR("Could not lock pfn list buffer");
    6.39 -        return -1;
    6.40 -    }    
    6.41 -
    6.42 -    ret = do_dom0_op(xc_handle, &op);
    6.43 -
    6.44 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    6.45 -
    6.46 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    6.47 -}
    6.48 -
    6.49 -#define MAX_MMU_UPDATES 1024
    6.50 -
    6.51 -static int flush_mmu_updates(int xc_handle,
    6.52 -                             mmu_update_t *mmu_updates,
    6.53 -                             int *mmu_update_idx)
    6.54 -{
    6.55 -    int err = 0;
    6.56 -    privcmd_hypercall_t hypercall;
    6.57 -
    6.58 -    if ( *mmu_update_idx == 0 )
    6.59 -        return 0;
    6.60 -
    6.61 -    hypercall.op     = __HYPERVISOR_mmu_update;
    6.62 -    hypercall.arg[0] = (unsigned long)mmu_updates;
    6.63 -    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
    6.64 -
    6.65 -    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
    6.66 -    {
    6.67 -        PERROR("Could not lock pagetable update array");
    6.68 -        err = 1;
    6.69 -        goto out;
    6.70 -    }
    6.71 -
    6.72 -    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
    6.73 -    {
    6.74 -        ERROR("Failure when submitting mmu updates");
    6.75 -        err = 1;
    6.76 -    }
    6.77 -
    6.78 -    *mmu_update_idx = 0;
    6.79 -    
    6.80 -    (void)munlock(mmu_updates, sizeof(mmu_updates));
    6.81 -
    6.82 - out:
    6.83 -    return err;
    6.84 -}
    6.85 -
    6.86 -static int add_mmu_update(int xc_handle,
    6.87 -                          mmu_update_t *mmu_updates,
    6.88 -                          int *mmu_update_idx,
    6.89 -                          unsigned long ptr, 
    6.90 -                          unsigned long val)
    6.91 -{
    6.92 -    mmu_updates[*mmu_update_idx].ptr = ptr;
    6.93 -    mmu_updates[*mmu_update_idx].val = val;
    6.94 -    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
    6.95 -        return flush_mmu_updates(xc_handle, mmu_updates, mmu_update_idx);
    6.96 -    return 0;
    6.97 -}
    6.98 -
    6.99 -static int checked_read(gzFile fd, void *buf, size_t count)
   6.100 -{
   6.101 -    int rc;
   6.102 -    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
   6.103 -        continue;
   6.104 -    return rc == count;
   6.105 -}
   6.106 -
   6.107 -int xc_linux_restore(int xc_handle,
   6.108 -                     const char *state_file,
   6.109 -                     int verbose)
   6.110 -{
   6.111 -    dom0_op_t op;
   6.112 -    int rc = 1, i, j;
   6.113 -    unsigned long mfn, pfn, dom = 0;
   6.114 -    unsigned int prev_pc, this_pc;
   6.115 -    
   6.116 -    /* Number of page frames in use by this XenoLinux session. */
   6.117 -    unsigned long nr_pfns;
   6.118 -
   6.119 -    /* The new domain's shared-info frame number. */
   6.120 -    unsigned long shared_info_frame;
   6.121 -    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
   6.122 -    
   6.123 -    /* A copy of the CPU context of the guest. */
   6.124 -    full_execution_context_t ctxt;
   6.125 -
   6.126 -    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
   6.127 -    char signature[16];
   6.128 -    
   6.129 -    /* A copy of the domain's name. */
   6.130 -    char name[MAX_DOMAIN_NAME];
   6.131 -
   6.132 -    /* A table containg the type of each PFN (/not/ MFN!). */
   6.133 -    unsigned long *pfn_type = NULL;
   6.134 -
   6.135 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
   6.136 -    unsigned long *ppage, page[1024];
   6.137 -
   6.138 -    /* A copy of the pfn-to-mfn table frame list. */
   6.139 -    unsigned long pfn_to_mfn_frame_list[1024];
   6.140 -
   6.141 -    /* A table mapping each PFN to its new MFN. */
   6.142 -    unsigned long *pfn_to_mfn_table = NULL;
   6.143 -
   6.144 -    /* A temporary mapping of the guest's suspend record. */
   6.145 -    suspend_record_t *p_srec;
   6.146 -
   6.147 -    /* The name and descriptor of the file that we are reading from. */
   6.148 -    int    fd;
   6.149 -    gzFile gfd;
   6.150 -
   6.151 -    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
   6.152 -    int mmu_update_idx = 0;
   6.153 -
   6.154 -    int pm_handle = -1;
   6.155 -
   6.156 -    if ( (fd = open(state_file, O_RDONLY)) == -1 )
   6.157 -    {
   6.158 -        PERROR("Could not open state file for reading");
   6.159 -        return 1;
   6.160 -    }
   6.161 -
   6.162 -    if ( (gfd = gzdopen(fd, "rb")) == NULL )
   6.163 -    {
   6.164 -        ERROR("Could not allocate decompression state for state file");
   6.165 -        close(fd);
   6.166 -        return 1;
   6.167 -    }
   6.168 -
   6.169 -    /* Start writing out the saved-domain record. */
   6.170 -    if ( !checked_read(gfd, signature, 16) ||
   6.171 -         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
   6.172 -    {
   6.173 -        ERROR("Unrecognised state format -- no signature found");
   6.174 -        goto out;
   6.175 -    }
   6.176 -
   6.177 -    if ( !checked_read(gfd, name,                  sizeof(name)) ||
   6.178 -         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
   6.179 -         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
   6.180 -         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
   6.181 -         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
   6.182 -    {
   6.183 -        ERROR("Error when reading from state file");
   6.184 -        goto out;
   6.185 -    }
   6.186 -
   6.187 -    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
   6.188 -    {
   6.189 -        if ( name[i] == '\0' ) break;
   6.190 -        if ( name[i] & 0x80 )
   6.191 -        {
   6.192 -            ERROR("Random characters in domain name");
   6.193 -            goto out;
   6.194 -        }
   6.195 -    }
   6.196 -    name[MAX_DOMAIN_NAME-1] = '\0';
   6.197 -
   6.198 -    if ( nr_pfns > 1024*1024 )
   6.199 -    {
   6.200 -        ERROR("Invalid state file -- pfn count out of range");
   6.201 -        goto out;
   6.202 -    }
   6.203 -
   6.204 -    /* We want zeroed memory so use calloc rather than malloc. */
   6.205 -    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
   6.206 -    pfn_type         = calloc(1, 4 * nr_pfns);    
   6.207 -
   6.208 -    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
   6.209 -    {
   6.210 -        errno = ENOMEM;
   6.211 -        goto out;
   6.212 -    }
   6.213 -
   6.214 -    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
   6.215 -    {
   6.216 -        ERROR("Error when reading from state file");
   6.217 -        goto out;
   6.218 -    }
   6.219 -
   6.220 -    /* Create a new domain of the appropriate size, and find it's dom_id. */
   6.221 -    op.cmd = DOM0_CREATEDOMAIN;
   6.222 -    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
   6.223 -    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   6.224 -    if ( do_dom0_op(xc_handle, &op) < 0 )
   6.225 -    {
   6.226 -        ERROR("Could not create new domain");
   6.227 -        goto out;
   6.228 -    }
   6.229 -    dom = op.u.createdomain.domain;
   6.230 -
   6.231 -    /* Get the domain's shared-info frame. */
   6.232 -    op.cmd = DOM0_GETDOMAININFO;
   6.233 -    op.u.getdomaininfo.domain = dom;
   6.234 -    if ( do_dom0_op(xc_handle, &op) < 0 )
   6.235 -    {
   6.236 -        ERROR("Could not get information on new domain");
   6.237 -        goto out;
   6.238 -    }
   6.239 -    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   6.240 -
   6.241 -    if ( (pm_handle = init_pfn_mapper()) < 0 )
   6.242 -        goto out;
   6.243 -
   6.244 -    /* Copy saved contents of shared-info page. No checking needed. */
   6.245 -    ppage = map_pfn(pm_handle, shared_info_frame);
   6.246 -    memcpy(ppage, shared_info, PAGE_SIZE);
   6.247 -    unmap_pfn(pm_handle, ppage);
   6.248 -
   6.249 -    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
   6.250 -    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
   6.251 -    {
   6.252 -        ERROR("Did not read correct number of frame numbers for new dom");
   6.253 -        goto out;
   6.254 -    }
   6.255 -
   6.256 -    verbose_printf("Reloading memory pages:   0%%");
   6.257 -
   6.258 -    /*
   6.259 -     * Now simply read each saved frame into its new machine frame.
   6.260 -     * We uncanonicalise page tables as we go.
   6.261 -     */
   6.262 -    prev_pc = 0;
   6.263 -    for ( i = 0; i < nr_pfns; i++ )
   6.264 -    {
   6.265 -        this_pc = (i * 100) / nr_pfns;
   6.266 -        if ( (this_pc - prev_pc) >= 5 )
   6.267 -        {
   6.268 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
   6.269 -            prev_pc = this_pc;
   6.270 -        }
   6.271 -
   6.272 -        mfn = pfn_to_mfn_table[i];
   6.273 -
   6.274 -        if ( !checked_read(gfd, page, PAGE_SIZE) )
   6.275 -        {
   6.276 -            ERROR("Error when reading from state file");
   6.277 -            goto out;
   6.278 -        }
   6.279 -
   6.280 -        ppage = map_pfn(pm_handle, mfn);
   6.281 -        switch ( pfn_type[i] )
   6.282 -        {
   6.283 -        case L1TAB:
   6.284 -            memset(ppage, 0, PAGE_SIZE);
   6.285 -            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
   6.286 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   6.287 -                                MMUEXT_PIN_L1_TABLE) )
   6.288 -                goto out;
   6.289 -            for ( j = 0; j < 1024; j++ )
   6.290 -            {
   6.291 -                if ( page[j] & _PAGE_PRESENT )
   6.292 -                {
   6.293 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   6.294 -                    {
   6.295 -                        ERROR("Frame number in page table is out of range");
   6.296 -                        goto out;
   6.297 -                    }
   6.298 -                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
   6.299 -                    {
   6.300 -                        ERROR("Write access requested for a restricted frame");
   6.301 -                        goto out;
   6.302 -                    }
   6.303 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
   6.304 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.305 -                }
   6.306 -                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
   6.307 -                                    (unsigned long)&ppage[j], page[j]) )
   6.308 -                    goto out;
   6.309 -            }
   6.310 -            break;
   6.311 -        case L2TAB:
   6.312 -            memset(ppage, 0, PAGE_SIZE);
   6.313 -            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
   6.314 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   6.315 -                                MMUEXT_PIN_L2_TABLE) )
   6.316 -                goto out;
   6.317 -            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
   6.318 -            {
   6.319 -                if ( page[j] & _PAGE_PRESENT )
   6.320 -                {
   6.321 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   6.322 -                    {
   6.323 -                        ERROR("Frame number in page table is out of range");
   6.324 -                        goto out;
   6.325 -                    }
   6.326 -                    if ( pfn_type[pfn] != L1TAB )
   6.327 -                    {
   6.328 -                        ERROR("Page table mistyping");
   6.329 -                        goto out;
   6.330 -                    }
   6.331 -                    /* Haven't reached the L1 table yet. Ensure it is safe! */
   6.332 -                    if ( pfn > i )
   6.333 -                    {
   6.334 -                        unsigned long **l1 = map_pfn(pm_handle, 
   6.335 -                                                     pfn_to_mfn_table[pfn]);
   6.336 -                        memset(l1, 0, PAGE_SIZE);
   6.337 -                        unmap_pfn(pm_handle, l1);
   6.338 -                    }
   6.339 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
   6.340 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.341 -                }
   6.342 -                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
   6.343 -                                    (unsigned long)&ppage[j], page[j]) )
   6.344 -                    goto out;
   6.345 -            }
   6.346 -            break;
   6.347 -        default:
   6.348 -            memcpy(ppage, page, PAGE_SIZE);
   6.349 -            break;
   6.350 -        }
   6.351 -        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
   6.352 -        if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
   6.353 -            goto out;
   6.354 -        unmap_pfn(pm_handle, ppage);
   6.355 -
   6.356 -        if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
   6.357 -                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
   6.358 -            goto out;
   6.359 -    }
   6.360 -
   6.361 -    if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
   6.362 -        goto out;
   6.363 -
   6.364 -    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
   6.365 -
   6.366 -    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
   6.367 -    pfn = ctxt.i386_ctxt.esi;
   6.368 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.369 -    {
   6.370 -        ERROR("Suspend record frame number is bad");
   6.371 -        goto out;
   6.372 -    }
   6.373 -    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
   6.374 -    p_srec = map_pfn(pm_handle, mfn);
   6.375 -    p_srec->resume_info.nr_pages    = nr_pfns;
   6.376 -    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
   6.377 -    p_srec->resume_info.dom_id      = dom;
   6.378 -    p_srec->resume_info.flags       = 0;
   6.379 -    unmap_pfn(pm_handle, p_srec);
   6.380 -
   6.381 -    /* Uncanonicalise each GDT frame number. */
   6.382 -    if ( ctxt.gdt_ents > 8192 )
   6.383 -    {
   6.384 -        ERROR("GDT entry count out of range");
   6.385 -        goto out;
   6.386 -    }
   6.387 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   6.388 -    {
   6.389 -        pfn = ctxt.gdt_frames[i];
   6.390 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.391 -        {
   6.392 -            ERROR("GDT frame number is bad");
   6.393 -            goto out;
   6.394 -        }
   6.395 -        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
   6.396 -    }
   6.397 -
   6.398 -    /* Uncanonicalise the page table base pointer. */
   6.399 -    pfn = ctxt.pt_base >> PAGE_SHIFT;
   6.400 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
   6.401 -    {
   6.402 -        ERROR("PT base is bad");
   6.403 -        goto out;
   6.404 -    }
   6.405 -    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.406 -
   6.407 -    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
   6.408 -    for ( i = 0; i < nr_pfns; i += 1024 )
   6.409 -    {
   6.410 -        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
   6.411 -        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
   6.412 -        pfn = pfn_to_mfn_frame_list[i/1024];
   6.413 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.414 -        {
   6.415 -            ERROR("PFN-to-MFN frame number is bad");
   6.416 -            goto out;
   6.417 -        }
   6.418 -        ppage = map_pfn(pm_handle, pfn_to_mfn_table[pfn]);
   6.419 -        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
   6.420 -        unmap_pfn(pm_handle, ppage);
   6.421 -    }
   6.422 -
   6.423 -    /*
   6.424 -     * Safety checking of saved context:
   6.425 -     *  1. i386_ctxt is fine, as Xen checks that on context switch.
   6.426 -     *  2. i387_ctxt is fine, as it can't hurt Xen.
   6.427 -     *  3. trap_ctxt needs the code selectors checked.
   6.428 -     *  4. fast_trap_idx is checked by Xen.
   6.429 -     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
   6.430 -     *  6. gdt already done, and further checking is done by Xen.
   6.431 -     *  7. check that ring1_ss is safe.
   6.432 -     *  8. pt_base is already done.
   6.433 -     *  9. debugregs are checked by Xen.
   6.434 -     *  10. callback code selectors need checking.
   6.435 -     */
   6.436 -    for ( i = 0; i < 256; i++ )
   6.437 -    {
   6.438 -        ctxt.trap_ctxt[i].vector = i;
   6.439 -        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
   6.440 -            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
   6.441 -    }
   6.442 -    if ( (ctxt.ring1_ss & 3) == 0 )
   6.443 -        ctxt.ring1_ss = FLAT_RING1_DS;
   6.444 -    if ( (ctxt.event_callback_cs & 3) == 0 )
   6.445 -        ctxt.event_callback_cs = FLAT_RING1_CS;
   6.446 -    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
   6.447 -        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
   6.448 -    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
   6.449 -         (ctxt.ldt_ents > 8192) ||
   6.450 -         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
   6.451 -         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
   6.452 -    {
   6.453 -        ERROR("Bad LDT base or size");
   6.454 -        goto out;
   6.455 -    }
   6.456 -
   6.457 -    op.cmd = DOM0_BUILDDOMAIN;
   6.458 -    op.u.builddomain.domain   = dom;
   6.459 -    op.u.builddomain.num_vifs = 1;
   6.460 -    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
   6.461 -    rc = do_dom0_op(xc_handle, &op);
   6.462 -
   6.463 - out:
   6.464 -    if ( rc != 0 )
   6.465 -    {
   6.466 -        if ( dom != 0 )
   6.467 -        {
   6.468 -            op.cmd = DOM0_DESTROYDOMAIN;
   6.469 -            op.u.destroydomain.domain = dom;
   6.470 -            op.u.destroydomain.force  = 1;
   6.471 -            (void)do_dom0_op(xc_handle, &op);
   6.472 -        }
   6.473 -    }
   6.474 -    else
   6.475 -    {
   6.476 -        /* Success: print the domain id. */
   6.477 -        verbose_printf("DOM=%ld\n", dom);
   6.478 -    }
   6.479 -
   6.480 -    if ( pm_handle >= 0 )
   6.481 -        (void)close_pfn_mapper(pm_handle);
   6.482 -
   6.483 -    if ( pfn_to_mfn_table != NULL )
   6.484 -        free(pfn_to_mfn_table);
   6.485 -    if ( pfn_type != NULL )
   6.486 -        free(pfn_type);
   6.487 -
   6.488 -    gzclose(gfd);
   6.489 -
   6.490 -    return (rc == 0) ? dom : rc;
   6.491 -}
     7.1 --- a/tools/xc/lib/libxc_linux_save.c	Fri Nov 21 16:46:39 2003 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,392 +0,0 @@
     7.4 -/******************************************************************************
     7.5 - * libxc_linux_save.c
     7.6 - * 
     7.7 - * Save the state of a running Xenolinux session.
     7.8 - * 
     7.9 - * Copyright (c) 2003, K A Fraser.
    7.10 - */
    7.11 -
    7.12 -#include "libxc_private.h"
    7.13 -#include <asm-xeno/suspend.h>
    7.14 -#include <zlib.h>
    7.15 -
    7.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
    7.17 -#define verbose_printf(_f, _a...) \
    7.18 -    do {                          \
    7.19 -        if ( !verbose ) break;    \
    7.20 -        printf( _f , ## _a );     \
    7.21 -        fflush(stdout);           \
    7.22 -    } while ( 0 )
    7.23 -
    7.24 -/*
    7.25 - * Returns TRUE if the given machine frame number has a unique mapping
    7.26 - * in the guest's pseudophysical map.
    7.27 - */
    7.28 -#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
    7.29 -    (((_mfn) < (1024*1024)) &&          \
    7.30 -     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
    7.31 -
    7.32 -/* Returns TRUE if MFN is successfully converted to a PFN. */
    7.33 -#define translate_mfn_to_pfn(_pmfn)         \
    7.34 -({                                          \
    7.35 -    unsigned long mfn = *(_pmfn);           \
    7.36 -    int _res = 1;                           \
    7.37 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
    7.38 -        _res = 0;                           \
    7.39 -    else                                    \
    7.40 -        *(_pmfn) = mfn_to_pfn_table[mfn];   \
    7.41 -    _res;                                   \
    7.42 -})
    7.43 -
    7.44 -static int check_pfn_ownership(int xc_handle, 
    7.45 -                               unsigned long mfn, 
    7.46 -                               unsigned int dom)
    7.47 -{
    7.48 -    dom0_op_t op;
    7.49 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
    7.50 -    op.u.getpageframeinfo.pfn = mfn;
    7.51 -    if ( (do_dom0_op(xc_handle, &op) < 0) || 
    7.52 -         (op.u.getpageframeinfo.domain != dom) )
    7.53 -        return 0;
    7.54 -    return 1;
    7.55 -}
    7.56 -
    7.57 -#define GETPFN_ERR (~0U)
    7.58 -static unsigned int get_pfn_type(int xc_handle, unsigned long mfn)
    7.59 -{
    7.60 -    dom0_op_t op;
    7.61 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
    7.62 -    op.u.getpageframeinfo.pfn = mfn;
    7.63 -    if ( do_dom0_op(xc_handle, &op) < 0 )
    7.64 -    {
    7.65 -        PERROR("Unexpected failure when getting page frame info!");
    7.66 -        return GETPFN_ERR;
    7.67 -    }
    7.68 -    return op.u.getpageframeinfo.type;
    7.69 -}
    7.70 -
    7.71 -static int checked_write(gzFile fd, void *buf, size_t count)
    7.72 -{
    7.73 -    int rc;
    7.74 -    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
    7.75 -        continue;
    7.76 -    return rc == count;
    7.77 -}
    7.78 -
    7.79 -int xc_linux_save(int xc_handle,
    7.80 -                  unsigned int domid, 
    7.81 -                  const char *state_file, 
    7.82 -                  int verbose)
    7.83 -{
    7.84 -    dom0_op_t op;
    7.85 -    int rc = 1, i, j;
    7.86 -    unsigned long mfn;
    7.87 -    unsigned int prev_pc, this_pc;
    7.88 -
    7.89 -    /* Remember if we stopped the guest, so we can restart it on exit. */
    7.90 -    int we_stopped_it = 0;
    7.91 -
    7.92 -    /* The new domain's shared-info frame number. */
    7.93 -    unsigned long shared_info_frame;
    7.94 -    
    7.95 -    /* A copy of the CPU context of the guest. */
    7.96 -    full_execution_context_t ctxt;
    7.97 -
    7.98 -    /* A copy of the domain's name. */
    7.99 -    char name[MAX_DOMAIN_NAME];
   7.100 -
   7.101 -    /* A table containg the type of each PFN (/not/ MFN!). */
   7.102 -    unsigned long *pfn_type = NULL;
   7.103 -
   7.104 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
   7.105 -    unsigned long *ppage, page[1024];
   7.106 -
   7.107 -    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
   7.108 -    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
   7.109 -    /* A temporary mapping of one frame in the above list. */
   7.110 -    unsigned long *pfn_to_mfn_frame;
   7.111 -
   7.112 -    /* A table mapping each PFN to its current MFN. */
   7.113 -    unsigned long *pfn_to_mfn_table = NULL;
   7.114 -    /* A table mapping each current MFN to its canonical PFN. */
   7.115 -    unsigned long *mfn_to_pfn_table = NULL;
   7.116 -    
   7.117 -    /* A temporary mapping, and a copy, of the guest's suspend record. */
   7.118 -    suspend_record_t *p_srec, srec;
   7.119 -
   7.120 -    /* The name and descriptor of the file that we are writing to. */
   7.121 -    int    fd;
   7.122 -    gzFile gfd;
   7.123 -
   7.124 -    int pm_handle = -1;
   7.125 -
   7.126 -    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
   7.127 -    {
   7.128 -        PERROR("Could not open file for writing");
   7.129 -        return 1;
   7.130 -    }
   7.131 -
   7.132 -    /*
   7.133 -     * Compression rate 1: we want speed over compression. We're mainly going
   7.134 -     * for those zero pages, after all.
   7.135 -     */
   7.136 -    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
   7.137 -    {
   7.138 -        ERROR("Could not allocate compression state for state file");
   7.139 -        close(fd);
   7.140 -        return 1;
   7.141 -    }
   7.142 -
   7.143 -    /* Ensure that the domain exists, and that it is stopped. */
   7.144 -    for ( ; ; )
   7.145 -    {
   7.146 -        op.cmd = DOM0_GETDOMAININFO;
   7.147 -        op.u.getdomaininfo.domain = domid;
   7.148 -        if ( (do_dom0_op(xc_handle, &op) < 0) || 
   7.149 -             (op.u.getdomaininfo.domain != domid) )
   7.150 -        {
   7.151 -            PERROR("Could not get info on domain");
   7.152 -            goto out;
   7.153 -        }
   7.154 -
   7.155 -        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
   7.156 -        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
   7.157 -        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   7.158 -
   7.159 -        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
   7.160 -            break;
   7.161 -
   7.162 -        we_stopped_it = 1;
   7.163 -
   7.164 -        op.cmd = DOM0_STOPDOMAIN;
   7.165 -        op.u.stopdomain.domain = domid;
   7.166 -        (void)do_dom0_op(xc_handle, &op);
   7.167 -
   7.168 -        sleep(1);
   7.169 -    }
   7.170 -
   7.171 -    /* A cheesy test to see whether the domain contains valid state. */
   7.172 -    if ( ctxt.pt_base == 0 )
   7.173 -    {
   7.174 -        ERROR("Domain is not in a valid Xenolinux state");
   7.175 -        goto out;
   7.176 -    }
   7.177 -
   7.178 -    if ( (pm_handle = init_pfn_mapper()) < 0 )
   7.179 -        goto out;
   7.180 -
   7.181 -    /* Is the suspend-record MFN actually valid for this domain? */
   7.182 -    if ( !check_pfn_ownership(xc_handle, ctxt.i386_ctxt.esi, domid) )
   7.183 -    {
   7.184 -        ERROR("Invalid state record pointer");
   7.185 -        goto out;
   7.186 -    }
   7.187 -
   7.188 -    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
   7.189 -    p_srec = map_pfn(pm_handle, ctxt.i386_ctxt.esi);
   7.190 -    memcpy(&srec, p_srec, sizeof(srec));
   7.191 -    unmap_pfn(pm_handle, p_srec);
   7.192 -
   7.193 -    if ( srec.nr_pfns > 1024*1024 )
   7.194 -    {
   7.195 -        ERROR("Invalid state record -- pfn count out of range");
   7.196 -        goto out;
   7.197 -    }
   7.198 -
   7.199 -    if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) )
   7.200 -    {
   7.201 -        ERROR("Invalid pfn-to-mfn frame list pointer");
   7.202 -        goto out;
   7.203 -    }
   7.204 -
   7.205 -    /* Grab a copy of the pfn-to-mfn table frame list. */
   7.206 -    p_pfn_to_mfn_frame_list = map_pfn(pm_handle, srec.pfn_to_mfn_frame_list);
   7.207 -    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
   7.208 -    unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list);
   7.209 -
   7.210 -    /* We want zeroed memory so use calloc rather than malloc. */
   7.211 -    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
   7.212 -    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
   7.213 -    pfn_type         = calloc(1, 4 * srec.nr_pfns);
   7.214 -
   7.215 -    if ( (mfn_to_pfn_table == NULL) ||
   7.216 -         (pfn_to_mfn_table == NULL) ||
   7.217 -         (pfn_type == NULL) )
   7.218 -    {
   7.219 -        errno = ENOMEM;
   7.220 -        goto out;
   7.221 -    }
   7.222 -
   7.223 -
   7.224 -    /*
   7.225 -     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
   7.226 -     * loop we have each MFN mapped at most once. Note that there may be MFNs
   7.227 -     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
   7.228 -     */
   7.229 -    pfn_to_mfn_frame = NULL;
   7.230 -    for ( i = 0; i < srec.nr_pfns; i++ )
   7.231 -    {
   7.232 -        /* Each frameful of table frames must be checked & mapped on demand. */
   7.233 -        if ( (i & 1023) == 0 )
   7.234 -        {
   7.235 -            mfn = pfn_to_mfn_frame_list[i/1024];
   7.236 -            if ( !check_pfn_ownership(xc_handle, mfn, domid) )
   7.237 -            {
   7.238 -                ERROR("Invalid frame number if pfn-to-mfn frame list");
   7.239 -                goto out;
   7.240 -            }
   7.241 -            if ( pfn_to_mfn_frame != NULL )
   7.242 -                unmap_pfn(pm_handle, pfn_to_mfn_frame);
   7.243 -            pfn_to_mfn_frame = map_pfn(pm_handle, mfn);
   7.244 -        }
   7.245 -        
   7.246 -        mfn = pfn_to_mfn_frame[i & 1023];
   7.247 -
   7.248 -        if ( !check_pfn_ownership(xc_handle, mfn, domid) )
   7.249 -        {
   7.250 -            ERROR("Invalid frame specified with pfn-to-mfn table");
   7.251 -            goto out;
   7.252 -        }
   7.253 -
   7.254 -        /* Did we map this MFN already? That would be invalid! */
   7.255 -        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   7.256 -        {
   7.257 -            ERROR("A machine frame appears twice in pseudophys space");
   7.258 -            goto out;
   7.259 -        }
   7.260 -
   7.261 -        pfn_to_mfn_table[i] = mfn;
   7.262 -        mfn_to_pfn_table[mfn] = i;
   7.263 -
   7.264 -        /* Query page type by MFN, but store it by PFN. */
   7.265 -        if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn)) == GETPFN_ERR )
   7.266 -            goto out;
   7.267 -    }
   7.268 -
   7.269 -    /* Canonicalise the suspend-record frame number. */
   7.270 -    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
   7.271 -    {
   7.272 -        ERROR("State record is not in range of pseudophys map");
   7.273 -        goto out;
   7.274 -    }
   7.275 -
   7.276 -    /* Canonicalise each GDT frame number. */
   7.277 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   7.278 -    {
   7.279 -        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
   7.280 -        {
   7.281 -            ERROR("GDT frame is not in range of pseudophys map");
   7.282 -            goto out;
   7.283 -        }
   7.284 -    }
   7.285 -
   7.286 -    /* Canonicalise the page table base pointer. */
   7.287 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
   7.288 -    {
   7.289 -        ERROR("PT base is not in range of pseudophys map");
   7.290 -        goto out;
   7.291 -    }
   7.292 -    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
   7.293 -
   7.294 -    /* Canonicalise the pfn-to-mfn table frame-number list. */
   7.295 -    for ( i = 0; i < srec.nr_pfns; i += 1024 )
   7.296 -    {
   7.297 -        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
   7.298 -        {
   7.299 -            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
   7.300 -            goto out;
   7.301 -        }
   7.302 -    }
   7.303 -
   7.304 -    /* Start writing out the saved-domain record. */
   7.305 -    ppage = map_pfn(pm_handle, shared_info_frame);
   7.306 -    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
   7.307 -         !checked_write(gfd, name,                  sizeof(name)) ||
   7.308 -         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
   7.309 -         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
   7.310 -         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
   7.311 -         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
   7.312 -         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
   7.313 -    {
   7.314 -        ERROR("Error when writing to state file");
   7.315 -        goto out;
   7.316 -    }
   7.317 -    unmap_pfn(pm_handle, ppage);
   7.318 -
   7.319 -    verbose_printf("Saving memory pages:   0%%");
   7.320 -
   7.321 -    /* Now write out each data page, canonicalising page tables as we go... */
   7.322 -    prev_pc = 0;
   7.323 -    for ( i = 0; i < srec.nr_pfns; i++ )
   7.324 -    {
   7.325 -        this_pc = (i * 100) / srec.nr_pfns;
   7.326 -        if ( (this_pc - prev_pc) >= 5 )
   7.327 -        {
   7.328 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
   7.329 -            prev_pc = this_pc;
   7.330 -        }
   7.331 -
   7.332 -        mfn = pfn_to_mfn_table[i];
   7.333 -
   7.334 -        ppage = map_pfn(pm_handle, mfn);
   7.335 -        memcpy(page, ppage, PAGE_SIZE);
   7.336 -        unmap_pfn(pm_handle, ppage);
   7.337 -
   7.338 -        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
   7.339 -        {
   7.340 -            for ( j = 0; 
   7.341 -                  j < ((pfn_type[i] == L2TAB) ? 
   7.342 -                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
   7.343 -                  j++ )
   7.344 -            {
   7.345 -                if ( !(page[j] & _PAGE_PRESENT) ) continue;
   7.346 -                mfn = page[j] >> PAGE_SHIFT;
   7.347 -                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   7.348 -                {
   7.349 -                    ERROR("Frame number in pagetable page is invalid");
   7.350 -                    goto out;
   7.351 -                }
   7.352 -                page[j] &= PAGE_SIZE - 1;
   7.353 -                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
   7.354 -            }
   7.355 -        }
   7.356 -
   7.357 -        if ( !checked_write(gfd, page, PAGE_SIZE) )
   7.358 -        {
   7.359 -            ERROR("Error when writing to state file");
   7.360 -            goto out;
   7.361 -        }
   7.362 -    }
   7.363 -
   7.364 -    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
   7.365 -
   7.366 -    /* Success! */
   7.367 -    rc = 0;
   7.368 -
   7.369 - out:
   7.370 -    /* Restart the domain if we had to stop it to save its state. */
   7.371 -    if ( we_stopped_it )
   7.372 -    {
   7.373 -        op.cmd = DOM0_STARTDOMAIN;
   7.374 -        op.u.startdomain.domain = domid;
   7.375 -        (void)do_dom0_op(xc_handle, &op);
   7.376 -    }
   7.377 -
   7.378 -    gzclose(gfd);
   7.379 -
   7.380 -    if ( pm_handle >= 0 )
   7.381 -        (void)close_pfn_mapper(pm_handle);
   7.382 -
   7.383 -    if ( pfn_to_mfn_table != NULL )
   7.384 -        free(pfn_to_mfn_table);
   7.385 -    if ( mfn_to_pfn_table != NULL )
   7.386 -        free(mfn_to_pfn_table);
   7.387 -    if ( pfn_type != NULL )
   7.388 -        free(pfn_type);
   7.389 -
   7.390 -    /* On error, make sure the file is deleted. */
   7.391 -    if ( rc != 0 )
   7.392 -        unlink(state_file);
   7.393 -    
   7.394 -    return !!rc;
   7.395 -}
     8.1 --- a/tools/xc/lib/libxc_misc.c	Fri Nov 21 16:46:39 2003 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,43 +0,0 @@
     8.4 -/******************************************************************************
     8.5 - * libxc_misc.c
     8.6 - * 
     8.7 - * Miscellaneous control interface functions.
     8.8 - */
     8.9 -
    8.10 -#include "libxc_private.h"
    8.11 -
    8.12 -int xc_interface_open(void)
    8.13 -{
    8.14 -    int fd = open("/proc/xeno/privcmd", O_RDWR);
    8.15 -    if ( fd == -1 )
    8.16 -        PERROR("Could not obtain handle on privileged command interface");
    8.17 -    return fd;
    8.18 -}
    8.19 -
    8.20 -int xc_interface_close(int xc_handle)
    8.21 -{
    8.22 -    return close(xc_handle);
    8.23 -}
    8.24 -
    8.25 -
    8.26 -#define CONSOLE_RING_CLEAR	1
    8.27 -
    8.28 -int xc_readconsolering(int xc_handle,
    8.29 -                       char *str, 
    8.30 -                       unsigned int max_chars, 
    8.31 -                       int clear)
    8.32 -{
    8.33 -    int ret;
    8.34 -    dom0_op_t op;
    8.35 -
    8.36 -    op.cmd = DOM0_READCONSOLE;
    8.37 -    op.u.readconsole.str = (unsigned long)str;
    8.38 -    op.u.readconsole.count = max_chars;
    8.39 -    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
    8.40 -
    8.41 -    if ( (ret = do_dom0_op(xc_handle, &op)) > 0 )
    8.42 -        str[ret] = '\0';
    8.43 -
    8.44 -    return ret;
    8.45 -}    
    8.46 -
     9.1 --- a/tools/xc/lib/libxc_private.c	Fri Nov 21 16:46:39 2003 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,31 +0,0 @@
     9.4 -/******************************************************************************
     9.5 - * libxc_private.c
     9.6 - * 
     9.7 - * Helper functions for the rest of the library.
     9.8 - */
     9.9 -
    9.10 -#include "libxc_private.h"
    9.11 -
    9.12 -int init_pfn_mapper(void)
    9.13 -{
    9.14 -    return open("/dev/mem", O_RDWR);
    9.15 -}
    9.16 -
    9.17 -int close_pfn_mapper(int pm_handle)
    9.18 -{
    9.19 -    return close(pm_handle);
    9.20 -}
    9.21 -
    9.22 -void *map_pfn(int pm_handle, unsigned long pfn)
    9.23 -{
    9.24 -    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
    9.25 -                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
    9.26 -    if ( vaddr == MAP_FAILED )
    9.27 -        return NULL;
    9.28 -    return vaddr;
    9.29 -}
    9.30 -
    9.31 -void unmap_pfn(int pm_handle, void *vaddr)
    9.32 -{
    9.33 -    (void)munmap(vaddr, PAGE_SIZE);
    9.34 -}
    10.1 --- a/tools/xc/lib/libxc_private.h	Fri Nov 21 16:46:39 2003 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,169 +0,0 @@
    10.4 -
    10.5 -#ifndef __LIBXC_PRIVATE_H__
    10.6 -#define __LIBXC_PRIVATE_H__
    10.7 -
    10.8 -typedef unsigned char      u8;
    10.9 -typedef unsigned short     u16;
   10.10 -typedef unsigned long      u32;
   10.11 -typedef unsigned long long u64;
   10.12 -typedef signed char        s8;
   10.13 -typedef signed short       s16;
   10.14 -typedef signed long        s32;
   10.15 -typedef signed long long   s64;
   10.16 -
   10.17 -#include <unistd.h>
   10.18 -#include <stdio.h>
   10.19 -#include <errno.h>
   10.20 -#include <fcntl.h>
   10.21 -#include <sys/mman.h>
   10.22 -#include <sys/types.h>
   10.23 -#include <sys/stat.h>
   10.24 -#include <stdlib.h>
   10.25 -#include <sys/ioctl.h>
   10.26 -#include <errno.h>
   10.27 -#include <string.h>
   10.28 -
   10.29 -#include "xc.h"
   10.30 -
   10.31 -#include <asm-xeno/proc_cmd.h>
   10.32 -#include <hypervisor-ifs/hypervisor-if.h>
   10.33 -#include <hypervisor-ifs/dom0_ops.h>
   10.34 -#include <hypervisor-ifs/vbd.h>
   10.35 -
   10.36 -#define _PAGE_PRESENT   0x001
   10.37 -#define _PAGE_RW        0x002
   10.38 -#define _PAGE_USER      0x004
   10.39 -#define _PAGE_PWT       0x008
   10.40 -#define _PAGE_PCD       0x010
   10.41 -#define _PAGE_ACCESSED  0x020
   10.42 -#define _PAGE_DIRTY     0x040
   10.43 -#define _PAGE_PAT       0x080
   10.44 -#define _PAGE_PSE       0x080
   10.45 -#define _PAGE_GLOBAL    0x100
   10.46 -
   10.47 -
   10.48 -#define L1_PAGETABLE_SHIFT       12
   10.49 -#define L2_PAGETABLE_SHIFT       22
   10.50 - 
   10.51 -#define ENTRIES_PER_L1_PAGETABLE 1024
   10.52 -#define ENTRIES_PER_L2_PAGETABLE 1024
   10.53 - 
   10.54 -#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
   10.55 -#define PAGE_SIZE               (1UL << PAGE_SHIFT)
   10.56 -#define PAGE_MASK               (~(PAGE_SIZE-1))
   10.57 -
   10.58 -typedef struct { unsigned long l1_lo; } l1_pgentry_t;
   10.59 -typedef struct { unsigned long l2_lo; } l2_pgentry_t;
   10.60 -
   10.61 -#define l1_table_offset(_a) \
   10.62 -          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
   10.63 -#define l2_table_offset(_a) \
   10.64 -          ((_a) >> L2_PAGETABLE_SHIFT)
   10.65 -
   10.66 -#define ERROR(_m)  \
   10.67 -    fprintf(stderr, "ERROR: %s\n", (_m))
   10.68 -
   10.69 -#define PERROR(_m) \
   10.70 -    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
   10.71 -
   10.72 -static inline int do_privcmd(int xc_handle,
   10.73 -                             unsigned int cmd, 
   10.74 -                             unsigned long data)
   10.75 -{
   10.76 -    return ioctl(xc_handle, cmd, data);
   10.77 -}
   10.78 -
   10.79 -static inline int do_xen_hypercall(int xc_handle,
   10.80 -                                   privcmd_hypercall_t *hypercall)
   10.81 -{
   10.82 -    return do_privcmd(xc_handle,
   10.83 -                      IOCTL_PRIVCMD_HYPERCALL, 
   10.84 -                      (unsigned long)hypercall);
   10.85 -}
   10.86 -
   10.87 -static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
   10.88 -{
   10.89 -    int ret = -1;
   10.90 -    privcmd_hypercall_t hypercall;
   10.91 -
   10.92 -    op->interface_version = DOM0_INTERFACE_VERSION;
   10.93 -
   10.94 -    hypercall.op     = __HYPERVISOR_dom0_op;
   10.95 -    hypercall.arg[0] = (unsigned long)op;
   10.96 -
   10.97 -    if ( mlock(op, sizeof(*op)) != 0 )
   10.98 -    {
   10.99 -        PERROR("Could not lock memory for Xen hypercall");
  10.100 -        goto out1;
  10.101 -    }
  10.102 -
  10.103 -    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  10.104 -    {
  10.105 -        if ( errno == EACCES )
  10.106 -            fprintf(stderr, "Dom0 operation failed -- need to"
  10.107 -                    " rebuild the user-space tool set?\n");
  10.108 -        goto out2;
  10.109 -    }
  10.110 -
  10.111 -    ret = 0;
  10.112 -
  10.113 - out2: (void)munlock(op, sizeof(*op));
  10.114 - out1: return ret;
  10.115 -}
  10.116 -
  10.117 -static inline int do_network_op(int xc_handle, network_op_t *op)
  10.118 -{
  10.119 -    int ret = -1;
  10.120 -    privcmd_hypercall_t hypercall;
  10.121 -
  10.122 -    hypercall.op     = __HYPERVISOR_network_op;
  10.123 -    hypercall.arg[0] = (unsigned long)op;
  10.124 -
  10.125 -    if ( mlock(op, sizeof(*op)) != 0 )
  10.126 -    {
  10.127 -        PERROR("Could not lock memory for Xen hypercall");
  10.128 -        goto out1;
  10.129 -    }
  10.130 -
  10.131 -    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  10.132 -        goto out2;
  10.133 -
  10.134 -    ret = 0;
  10.135 -
  10.136 - out2: (void)munlock(op, sizeof(*op));
  10.137 - out1: return ret;
  10.138 -}
  10.139 -
  10.140 -
  10.141 -static inline int do_block_io_op(int xc_handle, block_io_op_t *op)
  10.142 -{
  10.143 -    int ret = -1;
  10.144 -    privcmd_hypercall_t hypercall;
  10.145 -
  10.146 -    hypercall.op     = __HYPERVISOR_block_io_op;
  10.147 -    hypercall.arg[0] = (unsigned long)op;
  10.148 -
  10.149 -    if ( mlock(op, sizeof(*op)) != 0 )
  10.150 -    {
  10.151 -        PERROR("Could not lock memory for Xen hypercall");
  10.152 -        goto out1;
  10.153 -    }
  10.154 -
  10.155 -    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
  10.156 -        goto out2;
  10.157 -
  10.158 -    ret = 0;
  10.159 -
  10.160 - out2: (void)munlock(op, sizeof(*op));
  10.161 - out1: return ret;
  10.162 -}
  10.163 -
  10.164 -/*
  10.165 - * PFN mapping.
  10.166 - */
  10.167 -int init_pfn_mapper(void);
  10.168 -int close_pfn_mapper(int pm_handle);
  10.169 -void *map_pfn(int pm_handle, unsigned long pfn);
  10.170 -void unmap_pfn(int pm_handle, void *vaddr);
  10.171 -
  10.172 -#endif /* __LIBXC_PRIVATE_H__ */
    11.1 --- a/tools/xc/lib/libxc_vbd.c	Fri Nov 21 16:46:39 2003 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,123 +0,0 @@
    11.4 -/******************************************************************************
    11.5 - * libxc_vbd.c
    11.6 - * 
    11.7 - * API for manipulating and accessing per-domain virtual block devices.
    11.8 - * 
    11.9 - * Copyright (c) 2003, K A Fraser.
   11.10 - */
   11.11 -
   11.12 -#define _GNU_SOURCE
   11.13 -#include "libxc_private.h"
   11.14 -
   11.15 -int xc_vbd_create(int xc_handle,
   11.16 -                  unsigned int domid, 
   11.17 -                  unsigned short vbdid, 
   11.18 -                  int writeable)
   11.19 -{
   11.20 -    block_io_op_t op; 
   11.21 -    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   11.22 -    op.u.create_params.domain  = domid;
   11.23 -    op.u.create_params.vdevice = vbdid;
   11.24 -    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   11.25 -    return do_block_io_op(xc_handle, &op);
   11.26 -}
   11.27 -
   11.28 -
   11.29 -int xc_vbd_destroy(int xc_handle,
   11.30 -                   unsigned int domid, 
   11.31 -                   unsigned short vbdid)
   11.32 -{
   11.33 -    block_io_op_t op; 
   11.34 -    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   11.35 -    op.u.delete_params.domain  = domid;
   11.36 -    op.u.delete_params.vdevice = vbdid;
   11.37 -    return do_block_io_op(xc_handle, &op);
   11.38 -}
   11.39 -
   11.40 -
   11.41 -int xc_vbd_add_extent(int xc_handle,
   11.42 -                      unsigned int domid, 
   11.43 -                      unsigned short vbdid,
   11.44 -                      unsigned short real_device,
   11.45 -                      unsigned long start_sector,
   11.46 -                      unsigned long nr_sectors)
   11.47 -{
   11.48 -    block_io_op_t op; 
   11.49 -    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   11.50 -    op.u.add_params.domain  = domid; 
   11.51 -    op.u.add_params.vdevice = vbdid;
   11.52 -    op.u.add_params.extent.device       = real_device; 
   11.53 -    op.u.add_params.extent.start_sector = start_sector;
   11.54 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   11.55 -    return do_block_io_op(xc_handle, &op);
   11.56 -}
   11.57 -
   11.58 -
   11.59 -int xc_vbd_delete_extent(int xc_handle,
   11.60 -                         unsigned int domid, 
   11.61 -                         unsigned short vbdid,
   11.62 -                         unsigned short real_device,
   11.63 -                         unsigned long start_sector,
   11.64 -                         unsigned long nr_sectors)
   11.65 -{
   11.66 -    block_io_op_t op; 
   11.67 -    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   11.68 -    op.u.add_params.domain  = domid; 
   11.69 -    op.u.add_params.vdevice = vbdid;
   11.70 -    op.u.add_params.extent.device       = real_device; 
   11.71 -    op.u.add_params.extent.start_sector = start_sector;
   11.72 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   11.73 -    return do_block_io_op(xc_handle, &op);
   11.74 -}
   11.75 -
   11.76 -
   11.77 -int xc_vbd_probe(int xc_handle,
   11.78 -                 unsigned int domid,
   11.79 -                 unsigned int max_vbds,
   11.80 -                 xc_vbd_t *vbds)
   11.81 -{
   11.82 -    block_io_op_t op; 
   11.83 -    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   11.84 -    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   11.85 -
   11.86 -    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   11.87 -    op.u.probe_params.domain = domid; 
   11.88 -    
   11.89 -    xdi->max   = max_vbds;
   11.90 -    xdi->disks = malloc(allocsz);
   11.91 -    xdi->count = 0;
   11.92 -
   11.93 -    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   11.94 -    {
   11.95 -        if ( xdi->disks != NULL )
   11.96 -            free(xdi->disks);
   11.97 -        return -ENOMEM;
   11.98 -    }
   11.99 -
  11.100 -    ret = do_block_io_op(xc_handle, &op);
  11.101 -
  11.102 -    (void)munlock(xdi->disks, allocsz);
  11.103 -
  11.104 -    if ( ret >= 0 )
  11.105 -    {
  11.106 -	for ( i = 0, j = 0; i < xdi->count; i++ )
  11.107 -        {
  11.108 -            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  11.109 -                continue;
  11.110 -            
  11.111 -            vbds[j].domid = xdi->disks[i].domain;
  11.112 -            vbds[j].vbdid = xdi->disks[i].device;
  11.113 -            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  11.114 -                0 : XC_VBDF_WRITEABLE;
  11.115 -            vbds[j].nr_sectors = xdi->disks[i].capacity;
  11.116 -            
  11.117 -            j++;
  11.118 -        }
  11.119 -
  11.120 -        ret = j;
  11.121 -    }
  11.122 -    
  11.123 -    free(xdi->disks);
  11.124 -
  11.125 -    return ret;
  11.126 -}
    12.1 --- a/tools/xc/lib/libxc_vif.c	Fri Nov 21 16:46:39 2003 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,69 +0,0 @@
    12.4 -/******************************************************************************
    12.5 - * libxc_vif.c
    12.6 - * 
    12.7 - * API for manipulating and accessing per-network-interface parameters.
    12.8 - * 
    12.9 - * Copyright (c) 2003, K A Fraser.
   12.10 - */
   12.11 -
   12.12 -#include "libxc_private.h"
   12.13 -
   12.14 -int xc_vif_scheduler_set(int xc_handle,
   12.15 -                         unsigned int domid, 
   12.16 -                         unsigned int vifid, 
   12.17 -                         xc_vif_sched_params_t *params)
   12.18 -{
   12.19 -    network_op_t  netop;
   12.20 -    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   12.21 -    netop.u.vif_setparams.domain       = domid;
   12.22 -    netop.u.vif_setparams.vif          = vifid;
   12.23 -    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   12.24 -    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   12.25 -    return do_network_op(xc_handle, &netop);
   12.26 -}
   12.27 -
   12.28 -
   12.29 -int xc_vif_scheduler_get(int xc_handle,
   12.30 -                         unsigned int domid, 
   12.31 -                         unsigned int vifid, 
   12.32 -                         xc_vif_sched_params_t *params)
   12.33 -{
   12.34 -    network_op_t  netop;
   12.35 -    int rc;
   12.36 -
   12.37 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   12.38 -    netop.u.vif_getinfo.domain = domid;
   12.39 -    netop.u.vif_getinfo.vif    = vifid;
   12.40 -
   12.41 -    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   12.42 -    {
   12.43 -        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   12.44 -        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   12.45 -    }
   12.46 -
   12.47 -    return rc;
   12.48 -}
   12.49 -
   12.50 -
   12.51 -int xc_vif_stats_get(int xc_handle,
   12.52 -                     unsigned int domid, 
   12.53 -                     unsigned int vifid, 
   12.54 -                     xc_vif_stats_t *stats)
   12.55 -{
   12.56 -    network_op_t  netop;
   12.57 -    int rc;
   12.58 -
   12.59 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   12.60 -    netop.u.vif_getinfo.domain = domid;
   12.61 -    netop.u.vif_getinfo.vif    = vifid;
   12.62 -
   12.63 -    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   12.64 -    {
   12.65 -        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   12.66 -        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   12.67 -        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   12.68 -        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   12.69 -    }
   12.70 -
   12.71 -    return rc;
   12.72 -}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/xc/lib/xc_bvtsched.c	Sat Nov 22 11:43:43 2003 +0000
    13.3 @@ -0,0 +1,35 @@
    13.4 +/******************************************************************************
    13.5 + * xc_bvtsched.c
    13.6 + * 
    13.7 + * API for manipulating parameters of the Borrowed Virtual Time scheduler.
    13.8 + * 
    13.9 + * Copyright (c) 2003, K A Fraser.
   13.10 + */
   13.11 +
   13.12 +#include "xc_private.h"
   13.13 +
   13.14 +int xc_bvtsched_global_set(int xc_handle,
   13.15 +                           unsigned long ctx_allow)
   13.16 +{
   13.17 +    dom0_op_t op;
   13.18 +    op.cmd = DOM0_BVTCTL;
   13.19 +    op.u.bvtctl.ctx_allow = ctx_allow;
   13.20 +    return do_dom0_op(xc_handle, &op);
   13.21 +}
   13.22 +
   13.23 +int xc_bvtsched_domain_set(int xc_handle,
   13.24 +                           unsigned int domid,
   13.25 +                           unsigned long mcuadv,
   13.26 +                           unsigned long warp,
   13.27 +                           unsigned long warpl,
   13.28 +                           unsigned long warpu)
   13.29 +{
   13.30 +    dom0_op_t op;
   13.31 +    op.cmd = DOM0_ADJUSTDOM;
   13.32 +    op.u.adjustdom.domain  = domid;
   13.33 +    op.u.adjustdom.mcu_adv = mcuadv;
   13.34 +    op.u.adjustdom.warp    = warp;
   13.35 +    op.u.adjustdom.warpl   = warpl;
   13.36 +    op.u.adjustdom.warpu   = warpu;
   13.37 +    return do_dom0_op(xc_handle, &op);
   13.38 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/xc/lib/xc_domain.c	Sat Nov 22 11:43:43 2003 +0000
    14.3 @@ -0,0 +1,88 @@
    14.4 +/******************************************************************************
    14.5 + * xc_domain.c
    14.6 + * 
    14.7 + * API for manipulating and obtaining information on domains.
    14.8 + * 
    14.9 + * Copyright (c) 2003, K A Fraser.
   14.10 + */
   14.11 +
   14.12 +#include "xc_private.h"
   14.13 +
   14.14 +int xc_domain_create(int xc_handle,
   14.15 +                     unsigned int mem_kb, 
   14.16 +                     const char *name)
   14.17 +{
   14.18 +    int err;
   14.19 +    dom0_op_t op;
   14.20 +
   14.21 +    op.cmd = DOM0_CREATEDOMAIN;
   14.22 +    op.u.createdomain.memory_kb = mem_kb;
   14.23 +    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   14.24 +    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
   14.25 +
   14.26 +    err = do_dom0_op(xc_handle, &op);
   14.27 +
   14.28 +    return (err < 0) ? err : op.u.createdomain.domain;
   14.29 +}    
   14.30 +
   14.31 +
   14.32 +int xc_domain_start(int xc_handle,
   14.33 +                    unsigned int domid)
   14.34 +{
   14.35 +    dom0_op_t op;
   14.36 +    op.cmd = DOM0_STARTDOMAIN;
   14.37 +    op.u.startdomain.domain = domid;
   14.38 +    return do_dom0_op(xc_handle, &op);
   14.39 +}    
   14.40 +
   14.41 +
   14.42 +int xc_domain_stop(int xc_handle, 
   14.43 +                   unsigned int domid)
   14.44 +{
   14.45 +    dom0_op_t op;
   14.46 +    op.cmd = DOM0_STOPDOMAIN;
   14.47 +    op.u.stopdomain.domain = domid;
   14.48 +    return do_dom0_op(xc_handle, &op);
   14.49 +}    
   14.50 +
   14.51 +
   14.52 +int xc_domain_destroy(int xc_handle,
   14.53 +                      unsigned int domid, 
   14.54 +                      int force)
   14.55 +{
   14.56 +    dom0_op_t op;
   14.57 +    op.cmd = DOM0_DESTROYDOMAIN;
   14.58 +    op.u.destroydomain.domain = domid;
   14.59 +    op.u.destroydomain.force  = !!force;
   14.60 +    return do_dom0_op(xc_handle, &op);
   14.61 +}
   14.62 +
   14.63 +int xc_domain_getinfo(int xc_handle,
   14.64 +                      unsigned int first_domid,
   14.65 +                      unsigned int max_doms,
   14.66 +                      xc_dominfo_t *info)
   14.67 +{
   14.68 +    unsigned int nr_doms, next_domid = first_domid;
   14.69 +    dom0_op_t op;
   14.70 +
   14.71 +    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
   14.72 +    {
   14.73 +        op.cmd = DOM0_GETDOMAININFO;
   14.74 +        op.u.getdomaininfo.domain = next_domid;
   14.75 +        if ( do_dom0_op(xc_handle, &op) < 0 )
   14.76 +            break;
   14.77 +        info->domid   = op.u.getdomaininfo.domain;
   14.78 +        info->cpu     = op.u.getdomaininfo.processor;
   14.79 +        info->has_cpu = op.u.getdomaininfo.has_cpu;
   14.80 +        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
   14.81 +        info->nr_pages = op.u.getdomaininfo.tot_pages;
   14.82 +        info->cpu_time = op.u.getdomaininfo.cpu_time;
   14.83 +        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
   14.84 +        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
   14.85 +
   14.86 +        next_domid = op.u.getdomaininfo.domain + 1;
   14.87 +        info++;
   14.88 +    }
   14.89 +
   14.90 +    return nr_doms;
   14.91 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/xc/lib/xc_linux_build.c	Sat Nov 22 11:43:43 2003 +0000
    15.3 @@ -0,0 +1,478 @@
    15.4 +/******************************************************************************
    15.5 + * xc_linux_build.c
    15.6 + */
    15.7 +
    15.8 +#include "xc_private.h"
    15.9 +#include <zlib.h>
   15.10 +
   15.11 +/* This string is written to the head of every guest kernel image. */
   15.12 +#define GUEST_SIG   "XenoGues"
   15.13 +#define SIG_LEN    8
   15.14 +
   15.15 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   15.16 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   15.17 +
   15.18 +static long get_tot_pages(int xc_handle, int domid)
   15.19 +{
   15.20 +    dom0_op_t op;
   15.21 +    op.cmd = DOM0_GETDOMAININFO;
   15.22 +    op.u.getdomaininfo.domain = domid;
   15.23 +    return (do_dom0_op(xc_handle, &op) < 0) ? 
   15.24 +        -1 : op.u.getdomaininfo.tot_pages;
   15.25 +}
   15.26 +
   15.27 +static int get_pfn_list(int xc_handle,
   15.28 +                        int domid, 
   15.29 +                        unsigned long *pfn_buf, 
   15.30 +                        unsigned long max_pfns)
   15.31 +{
   15.32 +    dom0_op_t op;
   15.33 +    int ret;
   15.34 +    op.cmd = DOM0_GETMEMLIST;
   15.35 +    op.u.getmemlist.domain   = domid;
   15.36 +    op.u.getmemlist.max_pfns = max_pfns;
   15.37 +    op.u.getmemlist.buffer   = pfn_buf;
   15.38 +
   15.39 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   15.40 +        return -1;
   15.41 +
   15.42 +    ret = do_dom0_op(xc_handle, &op);
   15.43 +
   15.44 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   15.45 +
   15.46 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   15.47 +}
   15.48 +
   15.49 +static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates)
   15.50 +{
   15.51 +    int ret = -1;
   15.52 +    privcmd_hypercall_t hypercall;
   15.53 +
   15.54 +    hypercall.op     = __HYPERVISOR_mmu_update;
   15.55 +    hypercall.arg[0] = (unsigned long)updates;
   15.56 +    hypercall.arg[1] = (unsigned long)nr_updates;
   15.57 +
   15.58 +    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
   15.59 +        goto out1;
   15.60 +
   15.61 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
   15.62 +        goto out2;
   15.63 +
   15.64 +    ret = 0;
   15.65 +
   15.66 + out2: (void)munlock(updates, nr_updates * sizeof(*updates));
   15.67 + out1: return ret;
   15.68 +}
   15.69 +
   15.70 +/* Read the kernel header, extracting the image size and load address. */
   15.71 +static int read_kernel_header(gzFile gfd, long dom_size, 
   15.72 +                              unsigned long *load_addr)
   15.73 +{
   15.74 +    char signature[SIG_LEN];
   15.75 +
   15.76 +    gzread(gfd, signature, SIG_LEN);
   15.77 +    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
   15.78 +    {
   15.79 +        ERROR("Kernel image does not contain required signature");
   15.80 +        return -1;
   15.81 +    }
   15.82 +
   15.83 +    /* Read the load address which immediately follows the Xeno signature. */
   15.84 +    gzread(gfd, load_addr, sizeof(unsigned long));
   15.85 +
   15.86 +    return 0;
   15.87 +}
   15.88 +
   15.89 +static int copy_to_domain_page(int pm_handle,
   15.90 +                               unsigned long dst_pfn, 
   15.91 +                               void *src_page)
   15.92 +{
   15.93 +    void *vaddr = map_pfn(pm_handle, dst_pfn);
   15.94 +    if ( vaddr == NULL )
   15.95 +        return -1;
   15.96 +    memcpy(vaddr, src_page, PAGE_SIZE);
   15.97 +    unmap_pfn(pm_handle, vaddr);
   15.98 +    return 0;
   15.99 +}
  15.100 +
  15.101 +static int setup_guestos(int xc_handle,
  15.102 +                         int dom, 
  15.103 +                         gzFile kernel_gfd, 
  15.104 +                         int initrd_fd, 
  15.105 +                         unsigned long tot_pages,
  15.106 +                         unsigned long *virt_startinfo_addr, 
  15.107 +                         unsigned long virt_load_addr, 
  15.108 +                         dom0_builddomain_t *builddomain, 
  15.109 +                         const char *cmdline,
  15.110 +                         unsigned long shared_info_frame)
  15.111 +{
  15.112 +    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
  15.113 +    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
  15.114 +    unsigned long *page_array = NULL;
  15.115 +    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
  15.116 +    int alloc_index, num_pt_pages;
  15.117 +    unsigned long l2tab;
  15.118 +    unsigned long l1tab = 0;
  15.119 +    unsigned long num_pgt_updates = 0;
  15.120 +    unsigned long count, pt_start, i, j;
  15.121 +    unsigned long initrd_addr = 0, initrd_len = 0;
  15.122 +    start_info_t *start_info;
  15.123 +    shared_info_t *shared_info;
  15.124 +    unsigned long ksize;
  15.125 +    int pm_handle;
  15.126 +
  15.127 +    memset(builddomain, 0, sizeof(*builddomain));
  15.128 +
  15.129 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  15.130 +        goto error_out;
  15.131 +
  15.132 +    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
  15.133 +    page_array = malloc(tot_pages * sizeof(unsigned long));
  15.134 +    pgt_update_arr = pgt_updates;
  15.135 +    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
  15.136 +    {
  15.137 +        PERROR("Could not allocate memory");
  15.138 +        goto error_out;
  15.139 +    }
  15.140 +
  15.141 +    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
  15.142 +    {
  15.143 +        PERROR("Could not get the page frame list");
  15.144 +        goto error_out;
  15.145 +    }
  15.146 +
  15.147 +    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
  15.148 +    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
  15.149 +    {
  15.150 +        char page[PAGE_SIZE];
  15.151 +        int size;
  15.152 +        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
  15.153 +        {
  15.154 +            PERROR("Error reading kernel image, could not"
  15.155 +                   " read the whole image.");
  15.156 +            goto error_out;
  15.157 +        }
  15.158 +        if ( size == 0 )
  15.159 +            goto kernel_copied;
  15.160 +        copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
  15.161 +    }
  15.162 +    ERROR("Kernel too big to safely fit in domain memory");
  15.163 +    goto error_out;
  15.164 +
  15.165 + kernel_copied:
  15.166 +    /* ksize is kernel-image size rounded up to a page boundary. */
  15.167 +    ksize = i;
  15.168 +
  15.169 +    /* Load the initial ramdisk image. */
  15.170 +    if ( initrd_fd >= 0 )
  15.171 +    {
  15.172 +        struct stat stat;
  15.173 +        unsigned long isize;
  15.174 +
  15.175 +        if ( fstat(initrd_fd, &stat) < 0 )
  15.176 +        {
  15.177 +            PERROR("Could not stat the initrd image");
  15.178 +            goto error_out;
  15.179 +        }
  15.180 +        isize = stat.st_size;
  15.181 +        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
  15.182 +        {
  15.183 +            ERROR("Kernel/initrd too big to safely fit in domain memory");
  15.184 +            goto error_out;
  15.185 +        }
  15.186 +
  15.187 +        initrd_addr = virt_load_addr + ksize;
  15.188 +        initrd_len  = isize;
  15.189 +
  15.190 +        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
  15.191 +        {
  15.192 +            char page[PAGE_SIZE];
  15.193 +            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
  15.194 +            if ( read(initrd_fd, page, size) != size )
  15.195 +            {
  15.196 +                PERROR("Error reading initrd image, could not"
  15.197 +                       " read the whole image.");
  15.198 +                goto error_out;
  15.199 +            } 
  15.200 +            copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
  15.201 +        }
  15.202 +    }
  15.203 +
  15.204 +    alloc_index = tot_pages - 1;
  15.205 +
  15.206 +    /* Count bottom-level PTs, rounding up. */
  15.207 +    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
  15.208 +
  15.209 +    /* We must also count the page directory. */
  15.210 +    num_pt_pages++;
  15.211 +
  15.212 +    /* Index of first PT page. */
  15.213 +    pt_start = tot_pages - num_pt_pages;
  15.214 +
  15.215 +    /*
  15.216 +     * First allocate page for page dir. Allocation goes backwards from the end
  15.217 +     * of the allocated physical address space.
  15.218 +     */
  15.219 +    l2tab = page_array[alloc_index] << PAGE_SHIFT;
  15.220 +    alloc_index--;
  15.221 +    builddomain->ctxt.pt_base = l2tab;
  15.222 +
  15.223 +    /*
  15.224 +     * Pin down l2tab addr as page dir page - causes hypervisor to provide
  15.225 +     * correct protection for the page
  15.226 +     */ 
  15.227 +    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
  15.228 +    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
  15.229 +    pgt_updates++;
  15.230 +    num_pgt_updates++;
  15.231 +
  15.232 +    /* Initialise the page tables. */
  15.233 +    if ( (vl2tab = map_pfn(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
  15.234 +        goto error_out;
  15.235 +    memset(vl2tab, 0, PAGE_SIZE);
  15.236 +    vl2e = vl2tab + l2_table_offset(virt_load_addr);
  15.237 +    for ( count = 0; count < tot_pages; count++ )
  15.238 +    {    
  15.239 +        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
  15.240 +        {
  15.241 +            l1tab = page_array[alloc_index] << PAGE_SHIFT;
  15.242 +            if ( (vl1tab = map_pfn(pm_handle, l1tab >> PAGE_SHIFT)) == NULL )
  15.243 +                goto error_out;
  15.244 +            memset(vl1tab, 0, PAGE_SIZE);
  15.245 +            alloc_index--;
  15.246 +		
  15.247 +            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
  15.248 +                                            (count << PAGE_SHIFT));
  15.249 +
  15.250 +            /* make apropriate entry in the page directory */
  15.251 +            pgt_updates->ptr = (unsigned long)vl2e;
  15.252 +            pgt_updates->val = l1tab | L2_PROT;
  15.253 +            pgt_updates++;
  15.254 +            num_pgt_updates++;
  15.255 +            vl2e++;
  15.256 +        }
  15.257 +
  15.258 +        if ( count < pt_start )
  15.259 +        {
  15.260 +            pgt_updates->ptr = (unsigned long)vl1e;
  15.261 +            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
  15.262 +            pgt_updates++;
  15.263 +            num_pgt_updates++;
  15.264 +            vl1e++;
  15.265 +        }
  15.266 +        else
  15.267 +        {
  15.268 +            pgt_updates->ptr = (unsigned long)vl1e;
  15.269 +            pgt_updates->val = 
  15.270 +                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
  15.271 +            pgt_updates++;
  15.272 +            num_pgt_updates++;
  15.273 +            vl1e++;
  15.274 +        }
  15.275 +
  15.276 +        pgt_updates->ptr = 
  15.277 +            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
  15.278 +        pgt_updates->val = count;
  15.279 +        pgt_updates++;
  15.280 +        num_pgt_updates++;
  15.281 +    }
  15.282 +
  15.283 +    *virt_startinfo_addr =
  15.284 +        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
  15.285 +
  15.286 +    start_info = map_pfn(pm_handle, page_array[alloc_index-1]);
  15.287 +    memset(start_info, 0, sizeof(*start_info));
  15.288 +    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
  15.289 +    start_info->mod_start   = initrd_addr;
  15.290 +    start_info->mod_len     = initrd_len;
  15.291 +    start_info->nr_pages    = tot_pages;
  15.292 +    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  15.293 +    start_info->dom_id      = dom;
  15.294 +    start_info->flags       = 0;
  15.295 +    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
  15.296 +    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
  15.297 +
  15.298 +    unmap_pfn(pm_handle, start_info);
  15.299 +
  15.300 +    /* shared_info page starts its life empty. */
  15.301 +    shared_info = map_pfn(pm_handle, shared_info_frame);
  15.302 +    memset(shared_info, 0, PAGE_SIZE);
  15.303 +    unmap_pfn(pm_handle, shared_info);
  15.304 +
  15.305 +    /* Send the page update requests down to the hypervisor. */
  15.306 +    if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 )
  15.307 +        goto error_out;
  15.308 +
  15.309 +    free(page_array);
  15.310 +    free(pgt_update_arr);
  15.311 +    return 0;
  15.312 +
  15.313 + error_out:
  15.314 +    if ( pm_handle >= 0 )
  15.315 +        (void)close_pfn_mapper(pm_handle);
  15.316 +    if ( page_array == NULL )
  15.317 +        free(page_array);
  15.318 +    if ( pgt_update_arr == NULL )
  15.319 +        free(pgt_update_arr);
  15.320 +    return -1;
  15.321 +}
  15.322 +
  15.323 +int xc_linux_build(int xc_handle,
  15.324 +                   unsigned int domid,
  15.325 +                   const char *image_name,
  15.326 +                   const char *ramdisk_name,
  15.327 +                   const char *cmdline)
  15.328 +{
  15.329 +    dom0_op_t launch_op, op;
  15.330 +    unsigned long load_addr;
  15.331 +    long tot_pages;
  15.332 +    int kernel_fd, initrd_fd = -1;
  15.333 +    gzFile kernel_gfd;
  15.334 +    int rc, i;
  15.335 +    full_execution_context_t *ctxt;
  15.336 +    unsigned long virt_startinfo_addr;
  15.337 +
  15.338 +    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
  15.339 +    {
  15.340 +        PERROR("Could not find total pages for domain");
  15.341 +        return 1;
  15.342 +    }
  15.343 +
  15.344 +    kernel_fd = open(image_name, O_RDONLY);
  15.345 +    if ( kernel_fd < 0 )
  15.346 +    {
  15.347 +        PERROR("Could not open kernel image");
  15.348 +        return 1;
  15.349 +    }
  15.350 +
  15.351 +    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
  15.352 +    {
  15.353 +        PERROR("Could not allocate decompression state for state file");
  15.354 +        close(kernel_fd);
  15.355 +        return 1;
  15.356 +    }
  15.357 +
  15.358 +    rc = read_kernel_header(kernel_gfd,
  15.359 +                            tot_pages << (PAGE_SHIFT - 10), 
  15.360 +                            &load_addr);
  15.361 +    if ( rc < 0 )
  15.362 +        goto error_out;
  15.363 +    
  15.364 +    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
  15.365 +    {
  15.366 +        ERROR("We can only deal with page-aligned load addresses");
  15.367 +        goto error_out;
  15.368 +    }
  15.369 +
  15.370 +    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
  15.371 +    {
  15.372 +        ERROR("Cannot map all domain memory without hitting Xen space");
  15.373 +        goto error_out;
  15.374 +    }
  15.375 +
  15.376 +    if ( ramdisk_name != NULL )
  15.377 +    {
  15.378 +        initrd_fd = open(ramdisk_name, O_RDONLY);
  15.379 +        if ( initrd_fd < 0 )
  15.380 +        {
  15.381 +            PERROR("Could not open the initial ramdisk image");
  15.382 +            goto error_out;
  15.383 +        }
  15.384 +    }
  15.385 +
  15.386 +    op.cmd = DOM0_GETDOMAININFO;
  15.387 +    op.u.getdomaininfo.domain = domid;
  15.388 +    if ( (do_dom0_op(xc_handle, &op) < 0) || 
  15.389 +         (op.u.getdomaininfo.domain != domid) )
  15.390 +    {
  15.391 +        PERROR("Could not get info on domain");
  15.392 +        goto error_out;
  15.393 +    }
  15.394 +    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
  15.395 +         (op.u.getdomaininfo.ctxt.pt_base != 0) )
  15.396 +    {
  15.397 +        ERROR("Domain is already constructed");
  15.398 +        goto error_out;
  15.399 +    }
  15.400 +
  15.401 +    if ( setup_guestos(xc_handle, domid, kernel_gfd, initrd_fd, tot_pages,
  15.402 +                       &virt_startinfo_addr,
  15.403 +                       load_addr, &launch_op.u.builddomain, cmdline,
  15.404 +                       op.u.getdomaininfo.shared_info_frame) < 0 )
  15.405 +    {
  15.406 +        ERROR("Error constructing guest OS");
  15.407 +        goto error_out;
  15.408 +    }
  15.409 +
  15.410 +    if ( initrd_fd >= 0 )
  15.411 +        close(initrd_fd);
  15.412 +    gzclose(kernel_gfd);
  15.413 +
  15.414 +    ctxt = &launch_op.u.builddomain.ctxt;
  15.415 +
  15.416 +    ctxt->flags = 0;
  15.417 +
  15.418 +    /*
  15.419 +     * Initial register values:
  15.420 +     *  DS,ES,FS,GS = FLAT_RING1_DS
  15.421 +     *       CS:EIP = FLAT_RING1_CS:start_pc
  15.422 +     *       SS:ESP = FLAT_RING1_DS:start_stack
  15.423 +     *          ESI = start_info
  15.424 +     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
  15.425 +     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
  15.426 +     */
  15.427 +    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
  15.428 +    ctxt->i386_ctxt.es = FLAT_RING1_DS;
  15.429 +    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
  15.430 +    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
  15.431 +    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
  15.432 +    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
  15.433 +    ctxt->i386_ctxt.eip = load_addr;
  15.434 +    ctxt->i386_ctxt.esp = virt_startinfo_addr;
  15.435 +    ctxt->i386_ctxt.esi = virt_startinfo_addr;
  15.436 +    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
  15.437 +
  15.438 +    /* FPU is set up to default initial state. */
  15.439 +    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
  15.440 +
  15.441 +    /* Virtual IDT is empty at start-of-day. */
  15.442 +    for ( i = 0; i < 256; i++ )
  15.443 +    {
  15.444 +        ctxt->trap_ctxt[i].vector = i;
  15.445 +        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
  15.446 +    }
  15.447 +    ctxt->fast_trap_idx = 0;
  15.448 +
  15.449 +    /* No LDT. */
  15.450 +    ctxt->ldt_ents = 0;
  15.451 +    
  15.452 +    /* Use the default Xen-provided GDT. */
  15.453 +    ctxt->gdt_ents = 0;
  15.454 +
  15.455 +    /* Ring 1 stack is the initial stack. */
  15.456 +    ctxt->ring1_ss  = FLAT_RING1_DS;
  15.457 +    ctxt->ring1_esp = virt_startinfo_addr;
  15.458 +
  15.459 +    /* No debugging. */
  15.460 +    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
  15.461 +
  15.462 +    /* No callback handlers. */
  15.463 +    ctxt->event_callback_cs     = FLAT_RING1_CS;
  15.464 +    ctxt->event_callback_eip    = 0;
  15.465 +    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
  15.466 +    ctxt->failsafe_callback_eip = 0;
  15.467 +
  15.468 +    launch_op.u.builddomain.domain   = domid;
  15.469 +    launch_op.u.builddomain.num_vifs = 1;
  15.470 +
  15.471 +    launch_op.cmd = DOM0_BUILDDOMAIN;
  15.472 +    rc = do_dom0_op(xc_handle, &launch_op);
  15.473 +    
  15.474 +    return rc;
  15.475 +
  15.476 + error_out:
  15.477 +    if ( initrd_fd >= 0 )
  15.478 +        close(initrd_fd);
  15.479 +    gzclose(kernel_gfd);
  15.480 +    return -1;
  15.481 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/xc/lib/xc_linux_restore.c	Sat Nov 22 11:43:43 2003 +0000
    16.3 @@ -0,0 +1,488 @@
    16.4 +/******************************************************************************
    16.5 + * xc_linux_restore.c
    16.6 + * 
    16.7 + * Restore the state of a Xenolinux session.
    16.8 + * 
    16.9 + * Copyright (c) 2003, K A Fraser.
   16.10 + */
   16.11 +
   16.12 +#include "xc_private.h"
   16.13 +#include <asm-xeno/suspend.h>
   16.14 +#include <zlib.h>
   16.15 +
   16.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */
   16.17 +#define verbose_printf(_f, _a...) \
   16.18 +    do {                          \
   16.19 +        if ( !verbose ) break;    \
   16.20 +        printf( _f , ## _a );     \
   16.21 +        fflush(stdout);           \
   16.22 +    } while ( 0 )
   16.23 +
   16.24 +static int get_pfn_list(int xc_handle,
   16.25 +                        int domain_id, 
   16.26 +                        unsigned long *pfn_buf, 
   16.27 +                        unsigned long max_pfns)
   16.28 +{
   16.29 +    dom0_op_t op;
   16.30 +    int ret;
   16.31 +    op.cmd = DOM0_GETMEMLIST;
   16.32 +    op.u.getmemlist.domain   = domain_id;
   16.33 +    op.u.getmemlist.max_pfns = max_pfns;
   16.34 +    op.u.getmemlist.buffer   = pfn_buf;
   16.35 +
   16.36 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   16.37 +    {
   16.38 +        PERROR("Could not lock pfn list buffer");
   16.39 +        return -1;
   16.40 +    }    
   16.41 +
   16.42 +    ret = do_dom0_op(xc_handle, &op);
   16.43 +
   16.44 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   16.45 +
   16.46 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   16.47 +}
   16.48 +
   16.49 +#define MAX_MMU_UPDATES 1024
   16.50 +
   16.51 +static int flush_mmu_updates(int xc_handle,
   16.52 +                             mmu_update_t *mmu_updates,
   16.53 +                             int *mmu_update_idx)
   16.54 +{
   16.55 +    int err = 0;
   16.56 +    privcmd_hypercall_t hypercall;
   16.57 +
   16.58 +    if ( *mmu_update_idx == 0 )
   16.59 +        return 0;
   16.60 +
   16.61 +    hypercall.op     = __HYPERVISOR_mmu_update;
   16.62 +    hypercall.arg[0] = (unsigned long)mmu_updates;
   16.63 +    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
   16.64 +
   16.65 +    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
   16.66 +    {
   16.67 +        PERROR("Could not lock pagetable update array");
   16.68 +        err = 1;
   16.69 +        goto out;
   16.70 +    }
   16.71 +
   16.72 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
   16.73 +    {
   16.74 +        ERROR("Failure when submitting mmu updates");
   16.75 +        err = 1;
   16.76 +    }
   16.77 +
   16.78 +    *mmu_update_idx = 0;
   16.79 +    
   16.80 +    (void)munlock(mmu_updates, sizeof(mmu_updates));
   16.81 +
   16.82 + out:
   16.83 +    return err;
   16.84 +}
   16.85 +
   16.86 +static int add_mmu_update(int xc_handle,
   16.87 +                          mmu_update_t *mmu_updates,
   16.88 +                          int *mmu_update_idx,
   16.89 +                          unsigned long ptr, 
   16.90 +                          unsigned long val)
   16.91 +{
   16.92 +    mmu_updates[*mmu_update_idx].ptr = ptr;
   16.93 +    mmu_updates[*mmu_update_idx].val = val;
   16.94 +    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
   16.95 +        return flush_mmu_updates(xc_handle, mmu_updates, mmu_update_idx);
   16.96 +    return 0;
   16.97 +}
   16.98 +
   16.99 +static int checked_read(gzFile fd, void *buf, size_t count)
  16.100 +{
  16.101 +    int rc;
  16.102 +    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
  16.103 +        continue;
  16.104 +    return rc == count;
  16.105 +}
  16.106 +
  16.107 +int xc_linux_restore(int xc_handle,
  16.108 +                     const char *state_file,
  16.109 +                     int verbose)
  16.110 +{
  16.111 +    dom0_op_t op;
  16.112 +    int rc = 1, i, j;
  16.113 +    unsigned long mfn, pfn, dom = 0;
  16.114 +    unsigned int prev_pc, this_pc;
  16.115 +    
  16.116 +    /* Number of page frames in use by this XenoLinux session. */
  16.117 +    unsigned long nr_pfns;
  16.118 +
  16.119 +    /* The new domain's shared-info frame number. */
  16.120 +    unsigned long shared_info_frame;
  16.121 +    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
  16.122 +    
  16.123 +    /* A copy of the CPU context of the guest. */
  16.124 +    full_execution_context_t ctxt;
  16.125 +
  16.126 +    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
  16.127 +    char signature[16];
  16.128 +    
  16.129 +    /* A copy of the domain's name. */
  16.130 +    char name[MAX_DOMAIN_NAME];
  16.131 +
  16.132 +    /* A table containg the type of each PFN (/not/ MFN!). */
  16.133 +    unsigned long *pfn_type = NULL;
  16.134 +
  16.135 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
  16.136 +    unsigned long *ppage, page[1024];
  16.137 +
  16.138 +    /* A copy of the pfn-to-mfn table frame list. */
  16.139 +    unsigned long pfn_to_mfn_frame_list[1024];
  16.140 +
  16.141 +    /* A table mapping each PFN to its new MFN. */
  16.142 +    unsigned long *pfn_to_mfn_table = NULL;
  16.143 +
  16.144 +    /* A temporary mapping of the guest's suspend record. */
  16.145 +    suspend_record_t *p_srec;
  16.146 +
  16.147 +    /* The name and descriptor of the file that we are reading from. */
  16.148 +    int    fd;
  16.149 +    gzFile gfd;
  16.150 +
  16.151 +    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
  16.152 +    int mmu_update_idx = 0;
  16.153 +
  16.154 +    int pm_handle = -1;
  16.155 +
  16.156 +    if ( (fd = open(state_file, O_RDONLY)) == -1 )
  16.157 +    {
  16.158 +        PERROR("Could not open state file for reading");
  16.159 +        return 1;
  16.160 +    }
  16.161 +
  16.162 +    if ( (gfd = gzdopen(fd, "rb")) == NULL )
  16.163 +    {
  16.164 +        ERROR("Could not allocate decompression state for state file");
  16.165 +        close(fd);
  16.166 +        return 1;
  16.167 +    }
  16.168 +
  16.169 +    /* Start writing out the saved-domain record. */
  16.170 +    if ( !checked_read(gfd, signature, 16) ||
  16.171 +         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
  16.172 +    {
  16.173 +        ERROR("Unrecognised state format -- no signature found");
  16.174 +        goto out;
  16.175 +    }
  16.176 +
  16.177 +    if ( !checked_read(gfd, name,                  sizeof(name)) ||
  16.178 +         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
  16.179 +         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
  16.180 +         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
  16.181 +         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
  16.182 +    {
  16.183 +        ERROR("Error when reading from state file");
  16.184 +        goto out;
  16.185 +    }
  16.186 +
  16.187 +    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
  16.188 +    {
  16.189 +        if ( name[i] == '\0' ) break;
  16.190 +        if ( name[i] & 0x80 )
  16.191 +        {
  16.192 +            ERROR("Random characters in domain name");
  16.193 +            goto out;
  16.194 +        }
  16.195 +    }
  16.196 +    name[MAX_DOMAIN_NAME-1] = '\0';
  16.197 +
  16.198 +    if ( nr_pfns > 1024*1024 )
  16.199 +    {
  16.200 +        ERROR("Invalid state file -- pfn count out of range");
  16.201 +        goto out;
  16.202 +    }
  16.203 +
  16.204 +    /* We want zeroed memory so use calloc rather than malloc. */
  16.205 +    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
  16.206 +    pfn_type         = calloc(1, 4 * nr_pfns);    
  16.207 +
  16.208 +    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
  16.209 +    {
  16.210 +        errno = ENOMEM;
  16.211 +        goto out;
  16.212 +    }
  16.213 +
  16.214 +    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
  16.215 +    {
  16.216 +        ERROR("Error when reading from state file");
  16.217 +        goto out;
  16.218 +    }
  16.219 +
  16.220 +    /* Create a new domain of the appropriate size, and find it's dom_id. */
  16.221 +    op.cmd = DOM0_CREATEDOMAIN;
  16.222 +    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
  16.223 +    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
  16.224 +    if ( do_dom0_op(xc_handle, &op) < 0 )
  16.225 +    {
  16.226 +        ERROR("Could not create new domain");
  16.227 +        goto out;
  16.228 +    }
  16.229 +    dom = op.u.createdomain.domain;
  16.230 +
  16.231 +    /* Get the domain's shared-info frame. */
  16.232 +    op.cmd = DOM0_GETDOMAININFO;
  16.233 +    op.u.getdomaininfo.domain = dom;
  16.234 +    if ( do_dom0_op(xc_handle, &op) < 0 )
  16.235 +    {
  16.236 +        ERROR("Could not get information on new domain");
  16.237 +        goto out;
  16.238 +    }
  16.239 +    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  16.240 +
  16.241 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  16.242 +        goto out;
  16.243 +
  16.244 +    /* Copy saved contents of shared-info page. No checking needed. */
  16.245 +    ppage = map_pfn(pm_handle, shared_info_frame);
  16.246 +    memcpy(ppage, shared_info, PAGE_SIZE);
  16.247 +    unmap_pfn(pm_handle, ppage);
  16.248 +
  16.249 +    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
  16.250 +    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
  16.251 +    {
  16.252 +        ERROR("Did not read correct number of frame numbers for new dom");
  16.253 +        goto out;
  16.254 +    }
  16.255 +
  16.256 +    verbose_printf("Reloading memory pages:   0%%");
  16.257 +
  16.258 +    /*
  16.259 +     * Now simply read each saved frame into its new machine frame.
  16.260 +     * We uncanonicalise page tables as we go.
  16.261 +     */
  16.262 +    prev_pc = 0;
  16.263 +    for ( i = 0; i < nr_pfns; i++ )
  16.264 +    {
  16.265 +        this_pc = (i * 100) / nr_pfns;
  16.266 +        if ( (this_pc - prev_pc) >= 5 )
  16.267 +        {
  16.268 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
  16.269 +            prev_pc = this_pc;
  16.270 +        }
  16.271 +
  16.272 +        mfn = pfn_to_mfn_table[i];
  16.273 +
  16.274 +        if ( !checked_read(gfd, page, PAGE_SIZE) )
  16.275 +        {
  16.276 +            ERROR("Error when reading from state file");
  16.277 +            goto out;
  16.278 +        }
  16.279 +
  16.280 +        ppage = map_pfn(pm_handle, mfn);
  16.281 +        switch ( pfn_type[i] )
  16.282 +        {
  16.283 +        case L1TAB:
  16.284 +            memset(ppage, 0, PAGE_SIZE);
  16.285 +            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  16.286 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  16.287 +                                MMUEXT_PIN_L1_TABLE) )
  16.288 +                goto out;
  16.289 +            for ( j = 0; j < 1024; j++ )
  16.290 +            {
  16.291 +                if ( page[j] & _PAGE_PRESENT )
  16.292 +                {
  16.293 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  16.294 +                    {
  16.295 +                        ERROR("Frame number in page table is out of range");
  16.296 +                        goto out;
  16.297 +                    }
  16.298 +                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
  16.299 +                    {
  16.300 +                        ERROR("Write access requested for a restricted frame");
  16.301 +                        goto out;
  16.302 +                    }
  16.303 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
  16.304 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  16.305 +                }
  16.306 +                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  16.307 +                                    (unsigned long)&ppage[j], page[j]) )
  16.308 +                    goto out;
  16.309 +            }
  16.310 +            break;
  16.311 +        case L2TAB:
  16.312 +            memset(ppage, 0, PAGE_SIZE);
  16.313 +            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  16.314 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  16.315 +                                MMUEXT_PIN_L2_TABLE) )
  16.316 +                goto out;
  16.317 +            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
  16.318 +            {
  16.319 +                if ( page[j] & _PAGE_PRESENT )
  16.320 +                {
  16.321 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  16.322 +                    {
  16.323 +                        ERROR("Frame number in page table is out of range");
  16.324 +                        goto out;
  16.325 +                    }
  16.326 +                    if ( pfn_type[pfn] != L1TAB )
  16.327 +                    {
  16.328 +                        ERROR("Page table mistyping");
  16.329 +                        goto out;
  16.330 +                    }
  16.331 +                    /* Haven't reached the L1 table yet. Ensure it is safe! */
  16.332 +                    if ( pfn > i )
  16.333 +                    {
  16.334 +                        unsigned long **l1 = map_pfn(pm_handle, 
  16.335 +                                                     pfn_to_mfn_table[pfn]);
  16.336 +                        memset(l1, 0, PAGE_SIZE);
  16.337 +                        unmap_pfn(pm_handle, l1);
  16.338 +                    }
  16.339 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
  16.340 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  16.341 +                }
  16.342 +                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  16.343 +                                    (unsigned long)&ppage[j], page[j]) )
  16.344 +                    goto out;
  16.345 +            }
  16.346 +            break;
  16.347 +        default:
  16.348 +            memcpy(ppage, page, PAGE_SIZE);
  16.349 +            break;
  16.350 +        }
  16.351 +        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
  16.352 +        if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
  16.353 +            goto out;
  16.354 +        unmap_pfn(pm_handle, ppage);
  16.355 +
  16.356 +        if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
  16.357 +                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
  16.358 +            goto out;
  16.359 +    }
  16.360 +
  16.361 +    if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
  16.362 +        goto out;
  16.363 +
  16.364 +    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
  16.365 +
  16.366 +    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
  16.367 +    pfn = ctxt.i386_ctxt.esi;
  16.368 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  16.369 +    {
  16.370 +        ERROR("Suspend record frame number is bad");
  16.371 +        goto out;
  16.372 +    }
  16.373 +    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
  16.374 +    p_srec = map_pfn(pm_handle, mfn);
  16.375 +    p_srec->resume_info.nr_pages    = nr_pfns;
  16.376 +    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
  16.377 +    p_srec->resume_info.dom_id      = dom;
  16.378 +    p_srec->resume_info.flags       = 0;
  16.379 +    unmap_pfn(pm_handle, p_srec);
  16.380 +
  16.381 +    /* Uncanonicalise each GDT frame number. */
  16.382 +    if ( ctxt.gdt_ents > 8192 )
  16.383 +    {
  16.384 +        ERROR("GDT entry count out of range");
  16.385 +        goto out;
  16.386 +    }
  16.387 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  16.388 +    {
  16.389 +        pfn = ctxt.gdt_frames[i];
  16.390 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  16.391 +        {
  16.392 +            ERROR("GDT frame number is bad");
  16.393 +            goto out;
  16.394 +        }
  16.395 +        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
  16.396 +    }
  16.397 +
  16.398 +    /* Uncanonicalise the page table base pointer. */
  16.399 +    pfn = ctxt.pt_base >> PAGE_SHIFT;
  16.400 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
  16.401 +    {
  16.402 +        ERROR("PT base is bad");
  16.403 +        goto out;
  16.404 +    }
  16.405 +    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  16.406 +
  16.407 +    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
  16.408 +    for ( i = 0; i < nr_pfns; i += 1024 )
  16.409 +    {
  16.410 +        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
  16.411 +        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
  16.412 +        pfn = pfn_to_mfn_frame_list[i/1024];
  16.413 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  16.414 +        {
  16.415 +            ERROR("PFN-to-MFN frame number is bad");
  16.416 +            goto out;
  16.417 +        }
  16.418 +        ppage = map_pfn(pm_handle, pfn_to_mfn_table[pfn]);
  16.419 +        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
  16.420 +        unmap_pfn(pm_handle, ppage);
  16.421 +    }
  16.422 +
  16.423 +    /*
  16.424 +     * Safety checking of saved context:
  16.425 +     *  1. i386_ctxt is fine, as Xen checks that on context switch.
  16.426 +     *  2. i387_ctxt is fine, as it can't hurt Xen.
  16.427 +     *  3. trap_ctxt needs the code selectors checked.
  16.428 +     *  4. fast_trap_idx is checked by Xen.
  16.429 +     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
  16.430 +     *  6. gdt already done, and further checking is done by Xen.
  16.431 +     *  7. check that ring1_ss is safe.
  16.432 +     *  8. pt_base is already done.
  16.433 +     *  9. debugregs are checked by Xen.
  16.434 +     *  10. callback code selectors need checking.
  16.435 +     */
  16.436 +    for ( i = 0; i < 256; i++ )
  16.437 +    {
  16.438 +        ctxt.trap_ctxt[i].vector = i;
  16.439 +        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
  16.440 +            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
  16.441 +    }
  16.442 +    if ( (ctxt.ring1_ss & 3) == 0 )
  16.443 +        ctxt.ring1_ss = FLAT_RING1_DS;
  16.444 +    if ( (ctxt.event_callback_cs & 3) == 0 )
  16.445 +        ctxt.event_callback_cs = FLAT_RING1_CS;
  16.446 +    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
  16.447 +        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
  16.448 +    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
  16.449 +         (ctxt.ldt_ents > 8192) ||
  16.450 +         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
  16.451 +         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
  16.452 +    {
  16.453 +        ERROR("Bad LDT base or size");
  16.454 +        goto out;
  16.455 +    }
  16.456 +
  16.457 +    op.cmd = DOM0_BUILDDOMAIN;
  16.458 +    op.u.builddomain.domain   = dom;
  16.459 +    op.u.builddomain.num_vifs = 1;
  16.460 +    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
  16.461 +    rc = do_dom0_op(xc_handle, &op);
  16.462 +
  16.463 + out:
  16.464 +    if ( rc != 0 )
  16.465 +    {
  16.466 +        if ( dom != 0 )
  16.467 +        {
  16.468 +            op.cmd = DOM0_DESTROYDOMAIN;
  16.469 +            op.u.destroydomain.domain = dom;
  16.470 +            op.u.destroydomain.force  = 1;
  16.471 +            (void)do_dom0_op(xc_handle, &op);
  16.472 +        }
  16.473 +    }
  16.474 +    else
  16.475 +    {
  16.476 +        /* Success: print the domain id. */
  16.477 +        verbose_printf("DOM=%ld\n", dom);
  16.478 +    }
  16.479 +
  16.480 +    if ( pm_handle >= 0 )
  16.481 +        (void)close_pfn_mapper(pm_handle);
  16.482 +
  16.483 +    if ( pfn_to_mfn_table != NULL )
  16.484 +        free(pfn_to_mfn_table);
  16.485 +    if ( pfn_type != NULL )
  16.486 +        free(pfn_type);
  16.487 +
  16.488 +    gzclose(gfd);
  16.489 +
  16.490 +    return (rc == 0) ? dom : rc;
  16.491 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/xc/lib/xc_linux_save.c	Sat Nov 22 11:43:43 2003 +0000
    17.3 @@ -0,0 +1,392 @@
    17.4 +/******************************************************************************
    17.5 + * xc_linux_save.c
    17.6 + * 
    17.7 + * Save the state of a running Xenolinux session.
    17.8 + * 
    17.9 + * Copyright (c) 2003, K A Fraser.
   17.10 + */
   17.11 +
   17.12 +#include "xc_private.h"
   17.13 +#include <asm-xeno/suspend.h>
   17.14 +#include <zlib.h>
   17.15 +
   17.16 +/* This may allow us to create a 'quiet' command-line option, if necessary. */
   17.17 +#define verbose_printf(_f, _a...) \
   17.18 +    do {                          \
   17.19 +        if ( !verbose ) break;    \
   17.20 +        printf( _f , ## _a );     \
   17.21 +        fflush(stdout);           \
   17.22 +    } while ( 0 )
   17.23 +
   17.24 +/*
   17.25 + * Returns TRUE if the given machine frame number has a unique mapping
   17.26 + * in the guest's pseudophysical map.
   17.27 + */
   17.28 +#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
   17.29 +    (((_mfn) < (1024*1024)) &&          \
   17.30 +     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
   17.31 +
   17.32 +/* Returns TRUE if MFN is successfully converted to a PFN. */
   17.33 +#define translate_mfn_to_pfn(_pmfn)         \
   17.34 +({                                          \
   17.35 +    unsigned long mfn = *(_pmfn);           \
   17.36 +    int _res = 1;                           \
   17.37 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
   17.38 +        _res = 0;                           \
   17.39 +    else                                    \
   17.40 +        *(_pmfn) = mfn_to_pfn_table[mfn];   \
   17.41 +    _res;                                   \
   17.42 +})
   17.43 +
   17.44 +static int check_pfn_ownership(int xc_handle, 
   17.45 +                               unsigned long mfn, 
   17.46 +                               unsigned int dom)
   17.47 +{
   17.48 +    dom0_op_t op;
   17.49 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
   17.50 +    op.u.getpageframeinfo.pfn = mfn;
   17.51 +    if ( (do_dom0_op(xc_handle, &op) < 0) || 
   17.52 +         (op.u.getpageframeinfo.domain != dom) )
   17.53 +        return 0;
   17.54 +    return 1;
   17.55 +}
   17.56 +
   17.57 +#define GETPFN_ERR (~0U)
   17.58 +static unsigned int get_pfn_type(int xc_handle, unsigned long mfn)
   17.59 +{
   17.60 +    dom0_op_t op;
   17.61 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
   17.62 +    op.u.getpageframeinfo.pfn = mfn;
   17.63 +    if ( do_dom0_op(xc_handle, &op) < 0 )
   17.64 +    {
   17.65 +        PERROR("Unexpected failure when getting page frame info!");
   17.66 +        return GETPFN_ERR;
   17.67 +    }
   17.68 +    return op.u.getpageframeinfo.type;
   17.69 +}
   17.70 +
   17.71 +static int checked_write(gzFile fd, void *buf, size_t count)
   17.72 +{
   17.73 +    int rc;
   17.74 +    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
   17.75 +        continue;
   17.76 +    return rc == count;
   17.77 +}
   17.78 +
   17.79 +int xc_linux_save(int xc_handle,
   17.80 +                  unsigned int domid, 
   17.81 +                  const char *state_file, 
   17.82 +                  int verbose)
   17.83 +{
   17.84 +    dom0_op_t op;
   17.85 +    int rc = 1, i, j;
   17.86 +    unsigned long mfn;
   17.87 +    unsigned int prev_pc, this_pc;
   17.88 +
   17.89 +    /* Remember if we stopped the guest, so we can restart it on exit. */
   17.90 +    int we_stopped_it = 0;
   17.91 +
   17.92 +    /* The new domain's shared-info frame number. */
   17.93 +    unsigned long shared_info_frame;
   17.94 +    
   17.95 +    /* A copy of the CPU context of the guest. */
   17.96 +    full_execution_context_t ctxt;
   17.97 +
   17.98 +    /* A copy of the domain's name. */
   17.99 +    char name[MAX_DOMAIN_NAME];
  17.100 +
  17.101 +    /* A table containg the type of each PFN (/not/ MFN!). */
  17.102 +    unsigned long *pfn_type = NULL;
  17.103 +
  17.104 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
  17.105 +    unsigned long *ppage, page[1024];
  17.106 +
  17.107 +    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
  17.108 +    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
  17.109 +    /* A temporary mapping of one frame in the above list. */
  17.110 +    unsigned long *pfn_to_mfn_frame;
  17.111 +
  17.112 +    /* A table mapping each PFN to its current MFN. */
  17.113 +    unsigned long *pfn_to_mfn_table = NULL;
  17.114 +    /* A table mapping each current MFN to its canonical PFN. */
  17.115 +    unsigned long *mfn_to_pfn_table = NULL;
  17.116 +    
  17.117 +    /* A temporary mapping, and a copy, of the guest's suspend record. */
  17.118 +    suspend_record_t *p_srec, srec;
  17.119 +
  17.120 +    /* The name and descriptor of the file that we are writing to. */
  17.121 +    int    fd;
  17.122 +    gzFile gfd;
  17.123 +
  17.124 +    int pm_handle = -1;
  17.125 +
  17.126 +    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
  17.127 +    {
  17.128 +        PERROR("Could not open file for writing");
  17.129 +        return 1;
  17.130 +    }
  17.131 +
  17.132 +    /*
  17.133 +     * Compression rate 1: we want speed over compression. We're mainly going
  17.134 +     * for those zero pages, after all.
  17.135 +     */
  17.136 +    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
  17.137 +    {
  17.138 +        ERROR("Could not allocate compression state for state file");
  17.139 +        close(fd);
  17.140 +        return 1;
  17.141 +    }
  17.142 +
  17.143 +    /* Ensure that the domain exists, and that it is stopped. */
  17.144 +    for ( ; ; )
  17.145 +    {
  17.146 +        op.cmd = DOM0_GETDOMAININFO;
  17.147 +        op.u.getdomaininfo.domain = domid;
  17.148 +        if ( (do_dom0_op(xc_handle, &op) < 0) || 
  17.149 +             (op.u.getdomaininfo.domain != domid) )
  17.150 +        {
  17.151 +            PERROR("Could not get info on domain");
  17.152 +            goto out;
  17.153 +        }
  17.154 +
  17.155 +        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
  17.156 +        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
  17.157 +        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  17.158 +
  17.159 +        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
  17.160 +            break;
  17.161 +
  17.162 +        we_stopped_it = 1;
  17.163 +
  17.164 +        op.cmd = DOM0_STOPDOMAIN;
  17.165 +        op.u.stopdomain.domain = domid;
  17.166 +        (void)do_dom0_op(xc_handle, &op);
  17.167 +
  17.168 +        sleep(1);
  17.169 +    }
  17.170 +
  17.171 +    /* A cheesy test to see whether the domain contains valid state. */
  17.172 +    if ( ctxt.pt_base == 0 )
  17.173 +    {
  17.174 +        ERROR("Domain is not in a valid Xenolinux state");
  17.175 +        goto out;
  17.176 +    }
  17.177 +
  17.178 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  17.179 +        goto out;
  17.180 +
  17.181 +    /* Is the suspend-record MFN actually valid for this domain? */
  17.182 +    if ( !check_pfn_ownership(xc_handle, ctxt.i386_ctxt.esi, domid) )
  17.183 +    {
  17.184 +        ERROR("Invalid state record pointer");
  17.185 +        goto out;
  17.186 +    }
  17.187 +
  17.188 +    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
  17.189 +    p_srec = map_pfn(pm_handle, ctxt.i386_ctxt.esi);
  17.190 +    memcpy(&srec, p_srec, sizeof(srec));
  17.191 +    unmap_pfn(pm_handle, p_srec);
  17.192 +
  17.193 +    if ( srec.nr_pfns > 1024*1024 )
  17.194 +    {
  17.195 +        ERROR("Invalid state record -- pfn count out of range");
  17.196 +        goto out;
  17.197 +    }
  17.198 +
  17.199 +    if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) )
  17.200 +    {
  17.201 +        ERROR("Invalid pfn-to-mfn frame list pointer");
  17.202 +        goto out;
  17.203 +    }
  17.204 +
  17.205 +    /* Grab a copy of the pfn-to-mfn table frame list. */
  17.206 +    p_pfn_to_mfn_frame_list = map_pfn(pm_handle, srec.pfn_to_mfn_frame_list);
  17.207 +    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
  17.208 +    unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list);
  17.209 +
  17.210 +    /* We want zeroed memory so use calloc rather than malloc. */
  17.211 +    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
  17.212 +    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
  17.213 +    pfn_type         = calloc(1, 4 * srec.nr_pfns);
  17.214 +
  17.215 +    if ( (mfn_to_pfn_table == NULL) ||
  17.216 +         (pfn_to_mfn_table == NULL) ||
  17.217 +         (pfn_type == NULL) )
  17.218 +    {
  17.219 +        errno = ENOMEM;
  17.220 +        goto out;
  17.221 +    }
  17.222 +
  17.223 +
  17.224 +    /*
  17.225 +     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
  17.226 +     * loop we have each MFN mapped at most once. Note that there may be MFNs
  17.227 +     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
  17.228 +     */
  17.229 +    pfn_to_mfn_frame = NULL;
  17.230 +    for ( i = 0; i < srec.nr_pfns; i++ )
  17.231 +    {
  17.232 +        /* Each frameful of table frames must be checked & mapped on demand. */
  17.233 +        if ( (i & 1023) == 0 )
  17.234 +        {
  17.235 +            mfn = pfn_to_mfn_frame_list[i/1024];
  17.236 +            if ( !check_pfn_ownership(xc_handle, mfn, domid) )
  17.237 +            {
  17.238 +                ERROR("Invalid frame number if pfn-to-mfn frame list");
  17.239 +                goto out;
  17.240 +            }
  17.241 +            if ( pfn_to_mfn_frame != NULL )
  17.242 +                unmap_pfn(pm_handle, pfn_to_mfn_frame);
  17.243 +            pfn_to_mfn_frame = map_pfn(pm_handle, mfn);
  17.244 +        }
  17.245 +        
  17.246 +        mfn = pfn_to_mfn_frame[i & 1023];
  17.247 +
  17.248 +        if ( !check_pfn_ownership(xc_handle, mfn, domid) )
  17.249 +        {
  17.250 +            ERROR("Invalid frame specified with pfn-to-mfn table");
  17.251 +            goto out;
  17.252 +        }
  17.253 +
  17.254 +        /* Did we map this MFN already? That would be invalid! */
  17.255 +        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  17.256 +        {
  17.257 +            ERROR("A machine frame appears twice in pseudophys space");
  17.258 +            goto out;
  17.259 +        }
  17.260 +
  17.261 +        pfn_to_mfn_table[i] = mfn;
  17.262 +        mfn_to_pfn_table[mfn] = i;
  17.263 +
  17.264 +        /* Query page type by MFN, but store it by PFN. */
  17.265 +        if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn)) == GETPFN_ERR )
  17.266 +            goto out;
  17.267 +    }
  17.268 +
  17.269 +    /* Canonicalise the suspend-record frame number. */
  17.270 +    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
  17.271 +    {
  17.272 +        ERROR("State record is not in range of pseudophys map");
  17.273 +        goto out;
  17.274 +    }
  17.275 +
  17.276 +    /* Canonicalise each GDT frame number. */
  17.277 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  17.278 +    {
  17.279 +        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
  17.280 +        {
  17.281 +            ERROR("GDT frame is not in range of pseudophys map");
  17.282 +            goto out;
  17.283 +        }
  17.284 +    }
  17.285 +
  17.286 +    /* Canonicalise the page table base pointer. */
  17.287 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
  17.288 +    {
  17.289 +        ERROR("PT base is not in range of pseudophys map");
  17.290 +        goto out;
  17.291 +    }
  17.292 +    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
  17.293 +
  17.294 +    /* Canonicalise the pfn-to-mfn table frame-number list. */
  17.295 +    for ( i = 0; i < srec.nr_pfns; i += 1024 )
  17.296 +    {
  17.297 +        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
  17.298 +        {
  17.299 +            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
  17.300 +            goto out;
  17.301 +        }
  17.302 +    }
  17.303 +
  17.304 +    /* Start writing out the saved-domain record. */
  17.305 +    ppage = map_pfn(pm_handle, shared_info_frame);
  17.306 +    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
  17.307 +         !checked_write(gfd, name,                  sizeof(name)) ||
  17.308 +         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
  17.309 +         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
  17.310 +         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
  17.311 +         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
  17.312 +         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
  17.313 +    {
  17.314 +        ERROR("Error when writing to state file");
  17.315 +        goto out;
  17.316 +    }
  17.317 +    unmap_pfn(pm_handle, ppage);
  17.318 +
  17.319 +    verbose_printf("Saving memory pages:   0%%");
  17.320 +
  17.321 +    /* Now write out each data page, canonicalising page tables as we go... */
  17.322 +    prev_pc = 0;
  17.323 +    for ( i = 0; i < srec.nr_pfns; i++ )
  17.324 +    {
  17.325 +        this_pc = (i * 100) / srec.nr_pfns;
  17.326 +        if ( (this_pc - prev_pc) >= 5 )
  17.327 +        {
  17.328 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
  17.329 +            prev_pc = this_pc;
  17.330 +        }
  17.331 +
  17.332 +        mfn = pfn_to_mfn_table[i];
  17.333 +
  17.334 +        ppage = map_pfn(pm_handle, mfn);
  17.335 +        memcpy(page, ppage, PAGE_SIZE);
  17.336 +        unmap_pfn(pm_handle, ppage);
  17.337 +
  17.338 +        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
  17.339 +        {
  17.340 +            for ( j = 0; 
  17.341 +                  j < ((pfn_type[i] == L2TAB) ? 
  17.342 +                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
  17.343 +                  j++ )
  17.344 +            {
  17.345 +                if ( !(page[j] & _PAGE_PRESENT) ) continue;
  17.346 +                mfn = page[j] >> PAGE_SHIFT;
  17.347 +                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  17.348 +                {
  17.349 +                    ERROR("Frame number in pagetable page is invalid");
  17.350 +                    goto out;
  17.351 +                }
  17.352 +                page[j] &= PAGE_SIZE - 1;
  17.353 +                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
  17.354 +            }
  17.355 +        }
  17.356 +
  17.357 +        if ( !checked_write(gfd, page, PAGE_SIZE) )
  17.358 +        {
  17.359 +            ERROR("Error when writing to state file");
  17.360 +            goto out;
  17.361 +        }
  17.362 +    }
  17.363 +
  17.364 +    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
  17.365 +
  17.366 +    /* Success! */
  17.367 +    rc = 0;
  17.368 +
  17.369 + out:
  17.370 +    /* Restart the domain if we had to stop it to save its state. */
  17.371 +    if ( we_stopped_it )
  17.372 +    {
  17.373 +        op.cmd = DOM0_STARTDOMAIN;
  17.374 +        op.u.startdomain.domain = domid;
  17.375 +        (void)do_dom0_op(xc_handle, &op);
  17.376 +    }
  17.377 +
  17.378 +    gzclose(gfd);
  17.379 +
  17.380 +    if ( pm_handle >= 0 )
  17.381 +        (void)close_pfn_mapper(pm_handle);
  17.382 +
  17.383 +    if ( pfn_to_mfn_table != NULL )
  17.384 +        free(pfn_to_mfn_table);
  17.385 +    if ( mfn_to_pfn_table != NULL )
  17.386 +        free(mfn_to_pfn_table);
  17.387 +    if ( pfn_type != NULL )
  17.388 +        free(pfn_type);
  17.389 +
  17.390 +    /* On error, make sure the file is deleted. */
  17.391 +    if ( rc != 0 )
  17.392 +        unlink(state_file);
  17.393 +    
  17.394 +    return !!rc;
  17.395 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/xc/lib/xc_misc.c	Sat Nov 22 11:43:43 2003 +0000
    18.3 @@ -0,0 +1,43 @@
    18.4 +/******************************************************************************
    18.5 + * xc_misc.c
    18.6 + * 
    18.7 + * Miscellaneous control interface functions.
    18.8 + */
    18.9 +
   18.10 +#include "xc_private.h"
   18.11 +
   18.12 +int xc_interface_open(void)
   18.13 +{
   18.14 +    int fd = open("/proc/xeno/privcmd", O_RDWR);
   18.15 +    if ( fd == -1 )
   18.16 +        PERROR("Could not obtain handle on privileged command interface");
   18.17 +    return fd;
   18.18 +}
   18.19 +
   18.20 +int xc_interface_close(int xc_handle)
   18.21 +{
   18.22 +    return close(xc_handle);
   18.23 +}
   18.24 +
   18.25 +
   18.26 +#define CONSOLE_RING_CLEAR	1
   18.27 +
   18.28 +int xc_readconsolering(int xc_handle,
   18.29 +                       char *str, 
   18.30 +                       unsigned int max_chars, 
   18.31 +                       int clear)
   18.32 +{
   18.33 +    int ret;
   18.34 +    dom0_op_t op;
   18.35 +
   18.36 +    op.cmd = DOM0_READCONSOLE;
   18.37 +    op.u.readconsole.str = (unsigned long)str;
   18.38 +    op.u.readconsole.count = max_chars;
   18.39 +    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
   18.40 +
   18.41 +    if ( (ret = do_dom0_op(xc_handle, &op)) > 0 )
   18.42 +        str[ret] = '\0';
   18.43 +
   18.44 +    return ret;
   18.45 +}    
   18.46 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/xc/lib/xc_private.c	Sat Nov 22 11:43:43 2003 +0000
    19.3 @@ -0,0 +1,31 @@
    19.4 +/******************************************************************************
    19.5 + * xc_private.c
    19.6 + * 
    19.7 + * Helper functions for the rest of the library.
    19.8 + */
    19.9 +
   19.10 +#include "xc_private.h"
   19.11 +
   19.12 +int init_pfn_mapper(void)
   19.13 +{
   19.14 +    return open("/dev/mem", O_RDWR);
   19.15 +}
   19.16 +
   19.17 +int close_pfn_mapper(int pm_handle)
   19.18 +{
   19.19 +    return close(pm_handle);
   19.20 +}
   19.21 +
   19.22 +void *map_pfn(int pm_handle, unsigned long pfn)
   19.23 +{
   19.24 +    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   19.25 +                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
   19.26 +    if ( vaddr == MAP_FAILED )
   19.27 +        return NULL;
   19.28 +    return vaddr;
   19.29 +}
   19.30 +
   19.31 +void unmap_pfn(int pm_handle, void *vaddr)
   19.32 +{
   19.33 +    (void)munmap(vaddr, PAGE_SIZE);
   19.34 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/xc/lib/xc_private.h	Sat Nov 22 11:43:43 2003 +0000
    20.3 @@ -0,0 +1,169 @@
    20.4 +
    20.5 +#ifndef __XC_PRIVATE_H__
    20.6 +#define __XC_PRIVATE_H__
    20.7 +
    20.8 +typedef unsigned char      u8;
    20.9 +typedef unsigned short     u16;
   20.10 +typedef unsigned long      u32;
   20.11 +typedef unsigned long long u64;
   20.12 +typedef signed char        s8;
   20.13 +typedef signed short       s16;
   20.14 +typedef signed long        s32;
   20.15 +typedef signed long long   s64;
   20.16 +
   20.17 +#include <unistd.h>
   20.18 +#include <stdio.h>
   20.19 +#include <errno.h>
   20.20 +#include <fcntl.h>
   20.21 +#include <sys/mman.h>
   20.22 +#include <sys/types.h>
   20.23 +#include <sys/stat.h>
   20.24 +#include <stdlib.h>
   20.25 +#include <sys/ioctl.h>
   20.26 +#include <errno.h>
   20.27 +#include <string.h>
   20.28 +
   20.29 +#include "xc.h"
   20.30 +
   20.31 +#include <asm-xeno/proc_cmd.h>
   20.32 +#include <hypervisor-ifs/hypervisor-if.h>
   20.33 +#include <hypervisor-ifs/dom0_ops.h>
   20.34 +#include <hypervisor-ifs/vbd.h>
   20.35 +
   20.36 +#define _PAGE_PRESENT   0x001
   20.37 +#define _PAGE_RW        0x002
   20.38 +#define _PAGE_USER      0x004
   20.39 +#define _PAGE_PWT       0x008
   20.40 +#define _PAGE_PCD       0x010
   20.41 +#define _PAGE_ACCESSED  0x020
   20.42 +#define _PAGE_DIRTY     0x040
   20.43 +#define _PAGE_PAT       0x080
   20.44 +#define _PAGE_PSE       0x080
   20.45 +#define _PAGE_GLOBAL    0x100
   20.46 +
   20.47 +
   20.48 +#define L1_PAGETABLE_SHIFT       12
   20.49 +#define L2_PAGETABLE_SHIFT       22
   20.50 + 
   20.51 +#define ENTRIES_PER_L1_PAGETABLE 1024
   20.52 +#define ENTRIES_PER_L2_PAGETABLE 1024
   20.53 + 
   20.54 +#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
   20.55 +#define PAGE_SIZE               (1UL << PAGE_SHIFT)
   20.56 +#define PAGE_MASK               (~(PAGE_SIZE-1))
   20.57 +
   20.58 +typedef struct { unsigned long l1_lo; } l1_pgentry_t;
   20.59 +typedef struct { unsigned long l2_lo; } l2_pgentry_t;
   20.60 +
   20.61 +#define l1_table_offset(_a) \
   20.62 +          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
   20.63 +#define l2_table_offset(_a) \
   20.64 +          ((_a) >> L2_PAGETABLE_SHIFT)
   20.65 +
   20.66 +#define ERROR(_m)  \
   20.67 +    fprintf(stderr, "ERROR: %s\n", (_m))
   20.68 +
   20.69 +#define PERROR(_m) \
   20.70 +    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
   20.71 +
   20.72 +static inline int do_privcmd(int xc_handle,
   20.73 +                             unsigned int cmd, 
   20.74 +                             unsigned long data)
   20.75 +{
   20.76 +    return ioctl(xc_handle, cmd, data);
   20.77 +}
   20.78 +
   20.79 +static inline int do_xen_hypercall(int xc_handle,
   20.80 +                                   privcmd_hypercall_t *hypercall)
   20.81 +{
   20.82 +    return do_privcmd(xc_handle,
   20.83 +                      IOCTL_PRIVCMD_HYPERCALL, 
   20.84 +                      (unsigned long)hypercall);
   20.85 +}
   20.86 +
   20.87 +static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
   20.88 +{
   20.89 +    int ret = -1;
   20.90 +    privcmd_hypercall_t hypercall;
   20.91 +
   20.92 +    op->interface_version = DOM0_INTERFACE_VERSION;
   20.93 +
   20.94 +    hypercall.op     = __HYPERVISOR_dom0_op;
   20.95 +    hypercall.arg[0] = (unsigned long)op;
   20.96 +
   20.97 +    if ( mlock(op, sizeof(*op)) != 0 )
   20.98 +    {
   20.99 +        PERROR("Could not lock memory for Xen hypercall");
  20.100 +        goto out1;
  20.101 +    }
  20.102 +
  20.103 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  20.104 +    {
  20.105 +        if ( errno == EACCES )
  20.106 +            fprintf(stderr, "Dom0 operation failed -- need to"
  20.107 +                    " rebuild the user-space tool set?\n");
  20.108 +        goto out2;
  20.109 +    }
  20.110 +
  20.111 +    ret = 0;
  20.112 +
  20.113 + out2: (void)munlock(op, sizeof(*op));
  20.114 + out1: return ret;
  20.115 +}
  20.116 +
  20.117 +static inline int do_network_op(int xc_handle, network_op_t *op)
  20.118 +{
  20.119 +    int ret = -1;
  20.120 +    privcmd_hypercall_t hypercall;
  20.121 +
  20.122 +    hypercall.op     = __HYPERVISOR_network_op;
  20.123 +    hypercall.arg[0] = (unsigned long)op;
  20.124 +
  20.125 +    if ( mlock(op, sizeof(*op)) != 0 )
  20.126 +    {
  20.127 +        PERROR("Could not lock memory for Xen hypercall");
  20.128 +        goto out1;
  20.129 +    }
  20.130 +
  20.131 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
  20.132 +        goto out2;
  20.133 +
  20.134 +    ret = 0;
  20.135 +
  20.136 + out2: (void)munlock(op, sizeof(*op));
  20.137 + out1: return ret;
  20.138 +}
  20.139 +
  20.140 +
  20.141 +static inline int do_block_io_op(int xc_handle, block_io_op_t *op)
  20.142 +{
  20.143 +    int ret = -1;
  20.144 +    privcmd_hypercall_t hypercall;
  20.145 +
  20.146 +    hypercall.op     = __HYPERVISOR_block_io_op;
  20.147 +    hypercall.arg[0] = (unsigned long)op;
  20.148 +
  20.149 +    if ( mlock(op, sizeof(*op)) != 0 )
  20.150 +    {
  20.151 +        PERROR("Could not lock memory for Xen hypercall");
  20.152 +        goto out1;
  20.153 +    }
  20.154 +
  20.155 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
  20.156 +        goto out2;
  20.157 +
  20.158 +    ret = 0;
  20.159 +
  20.160 + out2: (void)munlock(op, sizeof(*op));
  20.161 + out1: return ret;
  20.162 +}
  20.163 +
  20.164 +/*
  20.165 + * PFN mapping.
  20.166 + */
  20.167 +int init_pfn_mapper(void);
  20.168 +int close_pfn_mapper(int pm_handle);
  20.169 +void *map_pfn(int pm_handle, unsigned long pfn);
  20.170 +void unmap_pfn(int pm_handle, void *vaddr);
  20.171 +
  20.172 +#endif /* __XC_PRIVATE_H__ */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/xc/lib/xc_vbd.c	Sat Nov 22 11:43:43 2003 +0000
    21.3 @@ -0,0 +1,123 @@
    21.4 +/******************************************************************************
    21.5 + * xc_vbd.c
    21.6 + * 
    21.7 + * API for manipulating and accessing per-domain virtual block devices.
    21.8 + * 
    21.9 + * Copyright (c) 2003, K A Fraser.
   21.10 + */
   21.11 +
   21.12 +#define _GNU_SOURCE
   21.13 +#include "xc_private.h"
   21.14 +
   21.15 +int xc_vbd_create(int xc_handle,
   21.16 +                  unsigned int domid, 
   21.17 +                  unsigned short vbdid, 
   21.18 +                  int writeable)
   21.19 +{
   21.20 +    block_io_op_t op; 
   21.21 +    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   21.22 +    op.u.create_params.domain  = domid;
   21.23 +    op.u.create_params.vdevice = vbdid;
   21.24 +    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   21.25 +    return do_block_io_op(xc_handle, &op);
   21.26 +}
   21.27 +
   21.28 +
   21.29 +int xc_vbd_destroy(int xc_handle,
   21.30 +                   unsigned int domid, 
   21.31 +                   unsigned short vbdid)
   21.32 +{
   21.33 +    block_io_op_t op; 
   21.34 +    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   21.35 +    op.u.delete_params.domain  = domid;
   21.36 +    op.u.delete_params.vdevice = vbdid;
   21.37 +    return do_block_io_op(xc_handle, &op);
   21.38 +}
   21.39 +
   21.40 +
   21.41 +int xc_vbd_add_extent(int xc_handle,
   21.42 +                      unsigned int domid, 
   21.43 +                      unsigned short vbdid,
   21.44 +                      unsigned short real_device,
   21.45 +                      unsigned long start_sector,
   21.46 +                      unsigned long nr_sectors)
   21.47 +{
   21.48 +    block_io_op_t op; 
   21.49 +    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   21.50 +    op.u.add_params.domain  = domid; 
   21.51 +    op.u.add_params.vdevice = vbdid;
   21.52 +    op.u.add_params.extent.device       = real_device; 
   21.53 +    op.u.add_params.extent.start_sector = start_sector;
   21.54 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   21.55 +    return do_block_io_op(xc_handle, &op);
   21.56 +}
   21.57 +
   21.58 +
   21.59 +int xc_vbd_delete_extent(int xc_handle,
   21.60 +                         unsigned int domid, 
   21.61 +                         unsigned short vbdid,
   21.62 +                         unsigned short real_device,
   21.63 +                         unsigned long start_sector,
   21.64 +                         unsigned long nr_sectors)
   21.65 +{
   21.66 +    block_io_op_t op; 
   21.67 +    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   21.68 +    op.u.add_params.domain  = domid; 
   21.69 +    op.u.add_params.vdevice = vbdid;
   21.70 +    op.u.add_params.extent.device       = real_device; 
   21.71 +    op.u.add_params.extent.start_sector = start_sector;
   21.72 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   21.73 +    return do_block_io_op(xc_handle, &op);
   21.74 +}
   21.75 +
   21.76 +
   21.77 +int xc_vbd_probe(int xc_handle,
   21.78 +                 unsigned int domid,
   21.79 +                 unsigned int max_vbds,
   21.80 +                 xc_vbd_t *vbds)
   21.81 +{
   21.82 +    block_io_op_t op; 
   21.83 +    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   21.84 +    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   21.85 +
   21.86 +    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   21.87 +    op.u.probe_params.domain = domid; 
   21.88 +    
   21.89 +    xdi->max   = max_vbds;
   21.90 +    xdi->disks = malloc(allocsz);
   21.91 +    xdi->count = 0;
   21.92 +
   21.93 +    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   21.94 +    {
   21.95 +        if ( xdi->disks != NULL )
   21.96 +            free(xdi->disks);
   21.97 +        return -ENOMEM;
   21.98 +    }
   21.99 +
  21.100 +    ret = do_block_io_op(xc_handle, &op);
  21.101 +
  21.102 +    (void)munlock(xdi->disks, allocsz);
  21.103 +
  21.104 +    if ( ret >= 0 )
  21.105 +    {
  21.106 +	for ( i = 0, j = 0; i < xdi->count; i++ )
  21.107 +        {
  21.108 +            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  21.109 +                continue;
  21.110 +            
  21.111 +            vbds[j].domid = xdi->disks[i].domain;
  21.112 +            vbds[j].vbdid = xdi->disks[i].device;
  21.113 +            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  21.114 +                0 : XC_VBDF_WRITEABLE;
  21.115 +            vbds[j].nr_sectors = xdi->disks[i].capacity;
  21.116 +            
  21.117 +            j++;
  21.118 +        }
  21.119 +
  21.120 +        ret = j;
  21.121 +    }
  21.122 +    
  21.123 +    free(xdi->disks);
  21.124 +
  21.125 +    return ret;
  21.126 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/xc/lib/xc_vif.c	Sat Nov 22 11:43:43 2003 +0000
    22.3 @@ -0,0 +1,69 @@
    22.4 +/******************************************************************************
    22.5 + * xc_vif.c
    22.6 + * 
    22.7 + * API for manipulating and accessing per-network-interface parameters.
    22.8 + * 
    22.9 + * Copyright (c) 2003, K A Fraser.
   22.10 + */
   22.11 +
   22.12 +#include "xc_private.h"
   22.13 +
   22.14 +int xc_vif_scheduler_set(int xc_handle,
   22.15 +                         unsigned int domid, 
   22.16 +                         unsigned int vifid, 
   22.17 +                         xc_vif_sched_params_t *params)
   22.18 +{
   22.19 +    network_op_t  netop;
   22.20 +    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   22.21 +    netop.u.vif_setparams.domain       = domid;
   22.22 +    netop.u.vif_setparams.vif          = vifid;
   22.23 +    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   22.24 +    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   22.25 +    return do_network_op(xc_handle, &netop);
   22.26 +}
   22.27 +
   22.28 +
   22.29 +int xc_vif_scheduler_get(int xc_handle,
   22.30 +                         unsigned int domid, 
   22.31 +                         unsigned int vifid, 
   22.32 +                         xc_vif_sched_params_t *params)
   22.33 +{
   22.34 +    network_op_t  netop;
   22.35 +    int rc;
   22.36 +
   22.37 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   22.38 +    netop.u.vif_getinfo.domain = domid;
   22.39 +    netop.u.vif_getinfo.vif    = vifid;
   22.40 +
   22.41 +    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   22.42 +    {
   22.43 +        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   22.44 +        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   22.45 +    }
   22.46 +
   22.47 +    return rc;
   22.48 +}
   22.49 +
   22.50 +
   22.51 +int xc_vif_stats_get(int xc_handle,
   22.52 +                     unsigned int domid, 
   22.53 +                     unsigned int vifid, 
   22.54 +                     xc_vif_stats_t *stats)
   22.55 +{
   22.56 +    network_op_t  netop;
   22.57 +    int rc;
   22.58 +
   22.59 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   22.60 +    netop.u.vif_getinfo.domain = domid;
   22.61 +    netop.u.vif_getinfo.vif    = vifid;
   22.62 +
   22.63 +    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
   22.64 +    {
   22.65 +        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   22.66 +        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   22.67 +        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   22.68 +        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   22.69 +    }
   22.70 +
   22.71 +    return rc;
   22.72 +}
    23.1 --- a/tools/xc/py/Makefile	Fri Nov 21 16:46:39 2003 +0000
    23.2 +++ b/tools/xc/py/Makefile	Sat Nov 22 11:43:43 2003 +0000
    23.3 @@ -1,5 +1,5 @@
    23.4  
    23.5 -all: ../lib/libxc.a
    23.6 +all: ../lib/libxc.so ../lib/xc.h
    23.7  	python setup.py build
    23.8  
    23.9  install: all
    24.1 --- a/tools/xc/py/setup.py	Fri Nov 21 16:46:39 2003 +0000
    24.2 +++ b/tools/xc/py/setup.py	Sat Nov 22 11:43:43 2003 +0000
    24.3 @@ -4,15 +4,9 @@ from distutils.core import setup, Extens
    24.4  module = Extension("Xc",
    24.5                     include_dirs         = ["../lib"],
    24.6                     library_dirs         = ["../lib"],
    24.7 +                   libraries            = ["xc"],
    24.8                     sources              = ["Xc.c"])
    24.9  
   24.10 -# Include the following line to link against shared libxc.so
   24.11 -#module.libraries = ["xc"]
   24.12 -
   24.13 -# Include the following lines to link against static libxc.a
   24.14 -module.extra_objects = ["../lib/libxc.a"]
   24.15 -module.libraries     = ["z"]
   24.16 -
   24.17  setup(name = "Xc", version = "1.0", ext_modules = [module])
   24.18  
   24.19  setup(name = "XenoUtil", version = "1.0", py_modules = ["XenoUtil"])