ia64/xen-unstable

changeset 958:b86d78981ae9

bitkeeper revision 1.613 (3fbbf72duBrrL77JwhqU9DkVTwQtFA)

Many files:
Rename new library to 'xc' (Xen Control).
xc.h:
Rename: tools/libxc/xi.h -> tools/libxc/xc.h
libxc_private.h:
Rename: tools/libxc/libxi_private.h -> tools/libxc/libxc_private.h
libxc_vif.c:
Rename: tools/libxc/libxi_vif.c -> tools/libxc/libxc_vif.c
libxc_vbd.c:
Rename: tools/libxc/libxi_vbd.c -> tools/libxc/libxc_vbd.c
libxc_private.c:
Rename: tools/libxc/libxi_private.c -> tools/libxc/libxc_private.c
libxc_misc.c:
Rename: tools/libxc/libxi_misc.c -> tools/libxc/libxc_misc.c
libxc_linux_restore.c:
Rename: tools/libxc/libxi_linux_restore.c -> tools/libxc/libxc_linux_restore.c
libxc_linux_save.c:
Rename: tools/libxc/libxi_linux_save.c -> tools/libxc/libxc_linux_save.c
libxc_linux_build.c:
Rename: tools/libxc/libxi_linux_build.c -> tools/libxc/libxc_linux_build.c
libxc_domain.c:
Rename: tools/libxc/libxi_domain.c -> tools/libxc/libxc_domain.c
libxc_bvtsched.c:
Rename: tools/libxc/libxi_bvtsched.c -> tools/libxc/libxc_bvtsched.c
Many files:
mvdir
author kaf24@scramble.cl.cam.ac.uk
date Wed Nov 19 23:05:17 2003 +0000 (2003-11-19)
parents 603ae09a1314
children 461fc928a4bf
files .rootkeys tools/libxc/Makefile tools/libxc/libxc_bvtsched.c tools/libxc/libxc_domain.c tools/libxc/libxc_linux_build.c tools/libxc/libxc_linux_restore.c tools/libxc/libxc_linux_save.c tools/libxc/libxc_misc.c tools/libxc/libxc_private.c tools/libxc/libxc_private.h tools/libxc/libxc_vbd.c tools/libxc/libxc_vif.c tools/libxc/rpm.spec tools/libxc/xc.h tools/libxi/Makefile tools/libxi/libxi_bvtsched.c tools/libxi/libxi_domain.c tools/libxi/libxi_linux_build.c tools/libxi/libxi_linux_restore.c tools/libxi/libxi_linux_save.c tools/libxi/libxi_misc.c tools/libxi/libxi_private.c tools/libxi/libxi_private.h tools/libxi/libxi_vbd.c tools/libxi/libxi_vif.c tools/libxi/rpm.spec tools/libxi/xi.h
line diff
     1.1 --- a/.rootkeys	Wed Nov 19 17:22:42 2003 +0000
     1.2 +++ b/.rootkeys	Wed Nov 19 23:05:17 2003 +0000
     1.3 @@ -184,19 +184,19 @@ 3fb01fd54I4P44vZDb1CtDt1BytDtA tools/int
     1.4  3fb01fd5B-UeibZkmSCOUZckNyNFYA tools/internal/xi_vbd_list.c
     1.5  3f86be322bd0h9jG3krZFOUgCDoxZg tools/internal/xi_vif_params.c
     1.6  3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
     1.7 -3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxi/Makefile
     1.8 -3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxi/libxi_bvtsched.c
     1.9 -3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxi/libxi_domain.c
    1.10 -3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxi/libxi_linux_build.c
    1.11 -3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxi/libxi_linux_restore.c
    1.12 -3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxi/libxi_linux_save.c
    1.13 -3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxi/libxi_misc.c
    1.14 -3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxi/libxi_private.c
    1.15 -3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxi/libxi_private.h
    1.16 -3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxi/libxi_vbd.c
    1.17 -3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxi/libxi_vif.c
    1.18 -3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxi/rpm.spec
    1.19 -3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxi/xi.h
    1.20 +3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
    1.21 +3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/libxc_bvtsched.c
    1.22 +3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/libxc_domain.c
    1.23 +3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/libxc_linux_build.c
    1.24 +3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxc/libxc_linux_restore.c
    1.25 +3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/libxc_linux_save.c
    1.26 +3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/libxc_misc.c
    1.27 +3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/libxc_private.c
    1.28 +3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/libxc_private.h
    1.29 +3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxc/libxc_vbd.c
    1.30 +3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxc/libxc_vif.c
    1.31 +3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec
    1.32 +3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h
    1.33  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.34  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.35  3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxc/Makefile	Wed Nov 19 23:05:17 2003 +0000
     2.3 @@ -0,0 +1,48 @@
     2.4 +
     2.5 +CC       = gcc
     2.6 +CFLAGS   = -c -Wall -O3 
     2.7 +CFLAGS  += -I../../xen/include -I../../xenolinux-sparse/include
     2.8 +
     2.9 +HDRS     = $(wildcard *.h)
    2.10 +OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
    2.11 +
    2.12 +LIBS     = libxc.a libxc.so
    2.13 +
    2.14 +all: check-for-zlib $(LIBS)
    2.15 +	ranlib libxc.a
    2.16 +
    2.17 +check-for-zlib:
    2.18 +	@if [ ! -e /usr/include/zlib.h ]; then \
    2.19 +	echo "***********************************************************"; \
    2.20 +	echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
    2.21 +	echo "***********************************************************"; \
    2.22 +	false; \
    2.23 +	fi
    2.24 +
    2.25 +install: all
    2.26 +	mkdir -p ../../../install/lib
    2.27 +	mkdir -p ../../../install/include
    2.28 +	cp -a $(LIBS) ../../../install/lib
    2.29 +	for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done
    2.30 +	cp -a xc.h ../../../install/include
    2.31 +	chmod 644 ../../../install/include/xc.h
    2.32 +
    2.33 +clean:
    2.34 +	$(RM) *.a *.so *.o *.rpm $(LIBS)
    2.35 +
    2.36 +rpm: all
    2.37 +	rm -rf staging
    2.38 +	mkdir staging
    2.39 +	mkdir staging/i386
    2.40 +	rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
    2.41 +		--define "_rpmdir$$PWD/staging" -bb rpm.spec
    2.42 +	mv staging/i386/*.rpm .
    2.43 +	rm -rf staging
    2.44 +
    2.45 +libxc.so: $(OBJS)
    2.46 +	$(LD) -shared -o $@ $^ -lz
    2.47 +
    2.48 +libxc.a: libxc.a($(OBJS))
    2.49 +
    2.50 +%.o: %.c $(HDRS) Makefile
    2.51 +	$(CC) $(CFLAGS) -o $@ $<
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/libxc_bvtsched.c	Wed Nov 19 23:05:17 2003 +0000
     3.3 @@ -0,0 +1,33 @@
     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(unsigned long ctx_allow)
    3.15 +{
    3.16 +    dom0_op_t op;
    3.17 +    op.cmd = DOM0_BVTCTL;
    3.18 +    op.u.bvtctl.ctx_allow = ctx_allow;
    3.19 +    return do_dom0_op(&op);
    3.20 +}
    3.21 +
    3.22 +int xc_bvtsched_domain_set(unsigned int domid,
    3.23 +                           unsigned long mcuadv,
    3.24 +                           unsigned long warp,
    3.25 +                           unsigned long warpl,
    3.26 +                           unsigned long warpu)
    3.27 +{
    3.28 +    dom0_op_t op;
    3.29 +    op.cmd = DOM0_ADJUSTDOM;
    3.30 +    op.u.adjustdom.domain  = domid;
    3.31 +    op.u.adjustdom.mcu_adv = mcuadv;
    3.32 +    op.u.adjustdom.warp    = warp;
    3.33 +    op.u.adjustdom.warpl   = warpl;
    3.34 +    op.u.adjustdom.warpu   = warpu;
    3.35 +    return do_dom0_op(&op);
    3.36 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxc/libxc_domain.c	Wed Nov 19 23:05:17 2003 +0000
     4.3 @@ -0,0 +1,80 @@
     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(unsigned int mem_kb, const char *name)
    4.15 +{
    4.16 +    int err;
    4.17 +    dom0_op_t op;
    4.18 +
    4.19 +    op.cmd = DOM0_CREATEDOMAIN;
    4.20 +    op.u.createdomain.memory_kb = mem_kb;
    4.21 +    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
    4.22 +    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
    4.23 +
    4.24 +    err = do_dom0_op(&op);
    4.25 +
    4.26 +    return (err < 0) ? err : op.u.createdomain.domain;
    4.27 +}    
    4.28 +
    4.29 +
    4.30 +int xc_domain_start(unsigned int domid)
    4.31 +{
    4.32 +    dom0_op_t op;
    4.33 +    op.cmd = DOM0_STARTDOMAIN;
    4.34 +    op.u.startdomain.domain = domid;
    4.35 +    return do_dom0_op(&op);
    4.36 +}    
    4.37 +
    4.38 +
    4.39 +int xc_domain_stop(unsigned int domid)
    4.40 +{
    4.41 +    dom0_op_t op;
    4.42 +    op.cmd = DOM0_STOPDOMAIN;
    4.43 +    op.u.stopdomain.domain = domid;
    4.44 +    return do_dom0_op(&op);
    4.45 +}    
    4.46 +
    4.47 +
    4.48 +int xc_domain_destroy(unsigned int domid, int force)
    4.49 +{
    4.50 +    dom0_op_t op;
    4.51 +    op.cmd = DOM0_DESTROYDOMAIN;
    4.52 +    op.u.destroydomain.domain = domid;
    4.53 +    op.u.destroydomain.force  = !!force;
    4.54 +    return do_dom0_op(&op);
    4.55 +}
    4.56 +
    4.57 +int xc_domain_getinfo(unsigned int first_domid,
    4.58 +                      unsigned int max_doms,
    4.59 +                      xc_dominfo_t *info)
    4.60 +{
    4.61 +    unsigned int nr_doms, next_domid = first_domid;
    4.62 +    dom0_op_t op;
    4.63 +
    4.64 +    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
    4.65 +    {
    4.66 +        op.cmd = DOM0_GETDOMAININFO;
    4.67 +        op.u.getdomaininfo.domain = next_domid;
    4.68 +        if ( do_dom0_op(&op) < 0 )
    4.69 +            break;
    4.70 +        info->domid   = op.u.getdomaininfo.domain;
    4.71 +        info->cpu     = op.u.getdomaininfo.processor;
    4.72 +        info->has_cpu = op.u.getdomaininfo.has_cpu;
    4.73 +        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
    4.74 +        info->nr_pages = op.u.getdomaininfo.tot_pages;
    4.75 +        info->cpu_time = op.u.getdomaininfo.cpu_time;
    4.76 +        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
    4.77 +        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
    4.78 +
    4.79 +        next_domid = op.u.getdomaininfo.domain + 1;
    4.80 +    }
    4.81 +
    4.82 +    return nr_doms;
    4.83 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxc/libxc_linux_build.c	Wed Nov 19 23:05:17 2003 +0000
     5.3 @@ -0,0 +1,481 @@
     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 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(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages;
    5.24 +}
    5.25 +
    5.26 +static int get_pfn_list(
    5.27 +    int domid, unsigned long *pfn_buf, unsigned long max_pfns)
    5.28 +{
    5.29 +    dom0_op_t op;
    5.30 +    int ret;
    5.31 +    op.cmd = DOM0_GETMEMLIST;
    5.32 +    op.u.getmemlist.domain   = domid;
    5.33 +    op.u.getmemlist.max_pfns = max_pfns;
    5.34 +    op.u.getmemlist.buffer   = pfn_buf;
    5.35 +
    5.36 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    5.37 +        return -1;
    5.38 +
    5.39 +    ret = do_dom0_op(&op);
    5.40 +
    5.41 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    5.42 +
    5.43 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    5.44 +}
    5.45 +
    5.46 +static int send_pgupdates(mmu_update_t *updates, int nr_updates)
    5.47 +{
    5.48 +    int ret = -1;
    5.49 +    privcmd_hypercall_t hypercall;
    5.50 +
    5.51 +    hypercall.op     = __HYPERVISOR_mmu_update;
    5.52 +    hypercall.arg[0] = (unsigned long)updates;
    5.53 +    hypercall.arg[1] = (unsigned long)nr_updates;
    5.54 +
    5.55 +    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
    5.56 +        goto out1;
    5.57 +
    5.58 +    if ( do_xen_hypercall(&hypercall) < 0 )
    5.59 +        goto out2;
    5.60 +
    5.61 +    ret = 0;
    5.62 +
    5.63 + out2: (void)munlock(updates, nr_updates * sizeof(*updates));
    5.64 + out1: return ret;
    5.65 +}
    5.66 +
    5.67 +/* Read the kernel header, extracting the image size and load address. */
    5.68 +static int read_kernel_header(gzFile gfd, long dom_size, 
    5.69 +                              unsigned long *load_addr, int verbose)
    5.70 +{
    5.71 +    char signature[SIG_LEN];
    5.72 +
    5.73 +    gzread(gfd, signature, SIG_LEN);
    5.74 +    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
    5.75 +    {
    5.76 +        if ( verbose )
    5.77 +            ERROR("Kernel image does not contain required signature");
    5.78 +        return -1;
    5.79 +    }
    5.80 +
    5.81 +    /* Read the load address which immediately follows the Xeno signature. */
    5.82 +    gzread(gfd, load_addr, sizeof(unsigned long));
    5.83 +
    5.84 +    return 0;
    5.85 +}
    5.86 +
    5.87 +static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
    5.88 +{
    5.89 +    void *vaddr = map_pfn(dst_pfn);
    5.90 +    if ( vaddr == NULL )
    5.91 +        return -1;
    5.92 +    memcpy(vaddr, src_page, PAGE_SIZE);
    5.93 +    unmap_pfn(vaddr);
    5.94 +    return 0;
    5.95 +}
    5.96 +
    5.97 +static int setup_guestos(
    5.98 +    int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages,
    5.99 +    unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 
   5.100 +    dom0_builddomain_t *builddomain, const char *cmdline,
   5.101 +    unsigned long shared_info_frame, int verbose)
   5.102 +{
   5.103 +    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
   5.104 +    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
   5.105 +    unsigned long *page_array = NULL;
   5.106 +    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
   5.107 +    int alloc_index, num_pt_pages;
   5.108 +    unsigned long l2tab;
   5.109 +    unsigned long l1tab = 0;
   5.110 +    unsigned long num_pgt_updates = 0;
   5.111 +    unsigned long count, pt_start, i, j;
   5.112 +    unsigned long initrd_addr = 0, initrd_len = 0;
   5.113 +    start_info_t *start_info;
   5.114 +    shared_info_t *shared_info;
   5.115 +    unsigned long ksize;
   5.116 +
   5.117 +    memset(builddomain, 0, sizeof(*builddomain));
   5.118 +
   5.119 +    if ( init_pfn_mapper() < 0 )
   5.120 +        goto error_out;
   5.121 +
   5.122 +    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
   5.123 +    page_array = malloc(tot_pages * sizeof(unsigned long));
   5.124 +    pgt_update_arr = pgt_updates;
   5.125 +    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
   5.126 +    {
   5.127 +        if ( verbose )
   5.128 +            PERROR("Could not allocate memory");
   5.129 +        goto error_out;
   5.130 +    }
   5.131 +
   5.132 +    if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
   5.133 +    {
   5.134 +        if ( verbose )
   5.135 +            PERROR("Could not get the page frame list");
   5.136 +        goto error_out;
   5.137 +    }
   5.138 +
   5.139 +    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
   5.140 +    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
   5.141 +    {
   5.142 +        char page[PAGE_SIZE];
   5.143 +        int size;
   5.144 +        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
   5.145 +        {
   5.146 +            if ( verbose )
   5.147 +                PERROR("Error reading kernel image, could not"
   5.148 +                       " read the whole image.");
   5.149 +            goto error_out;
   5.150 +        }
   5.151 +        if ( size == 0 )
   5.152 +            goto kernel_copied;
   5.153 +        copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
   5.154 +    }
   5.155 +    if ( verbose )
   5.156 +        ERROR("Kernel too big to safely fit in domain memory");
   5.157 +    goto error_out;
   5.158 +
   5.159 + kernel_copied:
   5.160 +    /* ksize is kernel-image size rounded up to a page boundary. */
   5.161 +    ksize = i;
   5.162 +
   5.163 +    /* Load the initial ramdisk image. */
   5.164 +    if ( initrd_fd >= 0 )
   5.165 +    {
   5.166 +        struct stat stat;
   5.167 +        unsigned long isize;
   5.168 +
   5.169 +        if ( fstat(initrd_fd, &stat) < 0 )
   5.170 +        {
   5.171 +            if ( verbose )
   5.172 +                PERROR("Could not stat the initrd image");
   5.173 +            goto error_out;
   5.174 +        }
   5.175 +        isize = stat.st_size;
   5.176 +        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
   5.177 +        {
   5.178 +            if ( verbose )
   5.179 +                ERROR("Kernel/initrd too big to safely fit in domain memory");
   5.180 +            goto error_out;
   5.181 +        }
   5.182 +
   5.183 +        initrd_addr = virt_load_addr + ksize;
   5.184 +        initrd_len  = isize;
   5.185 +
   5.186 +        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
   5.187 +        {
   5.188 +            char page[PAGE_SIZE];
   5.189 +            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
   5.190 +            if ( read(initrd_fd, page, size) != size )
   5.191 +            {
   5.192 +                if ( verbose )
   5.193 +                    PERROR("Error reading initrd image, could not"
   5.194 +                           " read the whole image.");
   5.195 +                goto error_out;
   5.196 +            } 
   5.197 +            copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
   5.198 +        }
   5.199 +    }
   5.200 +
   5.201 +    alloc_index = tot_pages - 1;
   5.202 +
   5.203 +    /* Count bottom-level PTs, rounding up. */
   5.204 +    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
   5.205 +
   5.206 +    /* We must also count the page directory. */
   5.207 +    num_pt_pages++;
   5.208 +
   5.209 +    /* Index of first PT page. */
   5.210 +    pt_start = tot_pages - num_pt_pages;
   5.211 +
   5.212 +    /*
   5.213 +     * First allocate page for page dir. Allocation goes backwards from the end
   5.214 +     * of the allocated physical address space.
   5.215 +     */
   5.216 +    l2tab = page_array[alloc_index] << PAGE_SHIFT;
   5.217 +    alloc_index--;
   5.218 +    builddomain->ctxt.pt_base = l2tab;
   5.219 +
   5.220 +    /*
   5.221 +     * Pin down l2tab addr as page dir page - causes hypervisor to provide
   5.222 +     * correct protection for the page
   5.223 +     */ 
   5.224 +    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
   5.225 +    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
   5.226 +    pgt_updates++;
   5.227 +    num_pgt_updates++;
   5.228 +
   5.229 +    /* Initialise the page tables. */
   5.230 +    if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL )
   5.231 +        goto error_out;
   5.232 +    memset(vl2tab, 0, PAGE_SIZE);
   5.233 +    vl2e = vl2tab + l2_table_offset(virt_load_addr);
   5.234 +    for ( count = 0; count < tot_pages; count++ )
   5.235 +    {    
   5.236 +        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
   5.237 +        {
   5.238 +            l1tab = page_array[alloc_index] << PAGE_SHIFT;
   5.239 +            if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL )
   5.240 +                goto error_out;
   5.241 +            memset(vl1tab, 0, PAGE_SIZE);
   5.242 +            alloc_index--;
   5.243 +		
   5.244 +            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
   5.245 +                                            (count << PAGE_SHIFT));
   5.246 +
   5.247 +            /* make apropriate entry in the page directory */
   5.248 +            pgt_updates->ptr = (unsigned long)vl2e;
   5.249 +            pgt_updates->val = l1tab | L2_PROT;
   5.250 +            pgt_updates++;
   5.251 +            num_pgt_updates++;
   5.252 +            vl2e++;
   5.253 +        }
   5.254 +
   5.255 +        if ( count < pt_start )
   5.256 +        {
   5.257 +            pgt_updates->ptr = (unsigned long)vl1e;
   5.258 +            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
   5.259 +            pgt_updates++;
   5.260 +            num_pgt_updates++;
   5.261 +            vl1e++;
   5.262 +        }
   5.263 +        else
   5.264 +        {
   5.265 +            pgt_updates->ptr = (unsigned long)vl1e;
   5.266 +            pgt_updates->val = 
   5.267 +                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
   5.268 +            pgt_updates++;
   5.269 +            num_pgt_updates++;
   5.270 +            vl1e++;
   5.271 +        }
   5.272 +
   5.273 +        pgt_updates->ptr = 
   5.274 +            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   5.275 +        pgt_updates->val = count;
   5.276 +        pgt_updates++;
   5.277 +        num_pgt_updates++;
   5.278 +    }
   5.279 +
   5.280 +    *virt_startinfo_addr =
   5.281 +        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
   5.282 +
   5.283 +    start_info = map_pfn(page_array[alloc_index-1]);
   5.284 +    memset(start_info, 0, sizeof(*start_info));
   5.285 +    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
   5.286 +    start_info->mod_start   = initrd_addr;
   5.287 +    start_info->mod_len     = initrd_len;
   5.288 +    start_info->nr_pages    = tot_pages;
   5.289 +    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
   5.290 +    start_info->dom_id      = dom;
   5.291 +    start_info->flags       = 0;
   5.292 +    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
   5.293 +    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
   5.294 +
   5.295 +    unmap_pfn(start_info);
   5.296 +
   5.297 +    /* shared_info page starts its life empty. */
   5.298 +    shared_info = map_pfn(shared_info_frame);
   5.299 +    memset(shared_info, 0, PAGE_SIZE);
   5.300 +    unmap_pfn(shared_info);
   5.301 +
   5.302 +    /* Send the page update requests down to the hypervisor. */
   5.303 +    if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
   5.304 +        goto error_out;
   5.305 +
   5.306 +    free(page_array);
   5.307 +    free(pgt_update_arr);
   5.308 +    return 0;
   5.309 +
   5.310 + error_out:
   5.311 +    if ( page_array == NULL )
   5.312 +        free(page_array);
   5.313 +    if ( pgt_update_arr == NULL )
   5.314 +        free(pgt_update_arr);
   5.315 +    return -1;
   5.316 +}
   5.317 +
   5.318 +int xc_domain_build(unsigned int domid,
   5.319 +                    const char *image_name,
   5.320 +                    const char *ramdisk_name,
   5.321 +                    const char *cmdline,
   5.322 +                    int verbose)
   5.323 +{
   5.324 +    dom0_op_t launch_op, op;
   5.325 +    unsigned long load_addr;
   5.326 +    long tot_pages;
   5.327 +    int kernel_fd, initrd_fd = -1;
   5.328 +    gzFile kernel_gfd;
   5.329 +    int rc, i;
   5.330 +    full_execution_context_t *ctxt;
   5.331 +    unsigned long virt_startinfo_addr;
   5.332 +
   5.333 +    if ( (tot_pages = get_tot_pages(domid)) < 0 )
   5.334 +    {
   5.335 +        if ( verbose )
   5.336 +            PERROR("Could not find total pages for domain");
   5.337 +        return 1;
   5.338 +    }
   5.339 +
   5.340 +    kernel_fd = open(image_name, O_RDONLY);
   5.341 +    if ( kernel_fd < 0 )
   5.342 +    {
   5.343 +        if ( verbose )
   5.344 +            PERROR("Could not open kernel image");
   5.345 +        return 1;
   5.346 +    }
   5.347 +
   5.348 +    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
   5.349 +    {
   5.350 +        if ( verbose )
   5.351 +            PERROR("Could not allocate decompression state for state file");
   5.352 +        close(kernel_fd);
   5.353 +        return 1;
   5.354 +    }
   5.355 +
   5.356 +    rc = read_kernel_header(kernel_gfd,
   5.357 +                            tot_pages << (PAGE_SHIFT - 10), 
   5.358 +                            &load_addr, verbose);
   5.359 +    if ( rc < 0 )
   5.360 +        goto error_out;
   5.361 +    
   5.362 +    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
   5.363 +    {
   5.364 +        if ( verbose )
   5.365 +            ERROR("We can only deal with page-aligned load addresses");
   5.366 +        goto error_out;
   5.367 +    }
   5.368 +
   5.369 +    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
   5.370 +    {
   5.371 +        if ( verbose )
   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 +            if ( verbose )
   5.382 +                PERROR("Could not open the initial ramdisk image");
   5.383 +            goto error_out;
   5.384 +        }
   5.385 +    }
   5.386 +
   5.387 +    op.cmd = DOM0_GETDOMAININFO;
   5.388 +    op.u.getdomaininfo.domain = domid;
   5.389 +    if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
   5.390 +    {
   5.391 +        if ( verbose )
   5.392 +            PERROR("Could not get info on domain");
   5.393 +        goto error_out;
   5.394 +    }
   5.395 +    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
   5.396 +         (op.u.getdomaininfo.ctxt.pt_base != 0) )
   5.397 +    {
   5.398 +        if ( verbose )
   5.399 +            ERROR("Domain is already constructed");
   5.400 +        goto error_out;
   5.401 +    }
   5.402 +
   5.403 +    if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages,
   5.404 +                       &virt_startinfo_addr,
   5.405 +                       load_addr, &launch_op.u.builddomain, cmdline,
   5.406 +                       op.u.getdomaininfo.shared_info_frame, verbose) < 0 )
   5.407 +    {
   5.408 +        if ( verbose )
   5.409 +            ERROR("Error constructing guest OS");
   5.410 +        goto error_out;
   5.411 +    }
   5.412 +
   5.413 +    if ( initrd_fd >= 0 )
   5.414 +        close(initrd_fd);
   5.415 +    gzclose(kernel_gfd);
   5.416 +
   5.417 +    ctxt = &launch_op.u.builddomain.ctxt;
   5.418 +
   5.419 +    ctxt->flags = 0;
   5.420 +
   5.421 +    /*
   5.422 +     * Initial register values:
   5.423 +     *  DS,ES,FS,GS = FLAT_RING1_DS
   5.424 +     *       CS:EIP = FLAT_RING1_CS:start_pc
   5.425 +     *       SS:ESP = FLAT_RING1_DS:start_stack
   5.426 +     *          ESI = start_info
   5.427 +     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
   5.428 +     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
   5.429 +     */
   5.430 +    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
   5.431 +    ctxt->i386_ctxt.es = FLAT_RING1_DS;
   5.432 +    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
   5.433 +    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
   5.434 +    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
   5.435 +    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
   5.436 +    ctxt->i386_ctxt.eip = load_addr;
   5.437 +    ctxt->i386_ctxt.esp = virt_startinfo_addr;
   5.438 +    ctxt->i386_ctxt.esi = virt_startinfo_addr;
   5.439 +    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
   5.440 +
   5.441 +    /* FPU is set up to default initial state. */
   5.442 +    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
   5.443 +
   5.444 +    /* Virtual IDT is empty at start-of-day. */
   5.445 +    for ( i = 0; i < 256; i++ )
   5.446 +    {
   5.447 +        ctxt->trap_ctxt[i].vector = i;
   5.448 +        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
   5.449 +    }
   5.450 +    ctxt->fast_trap_idx = 0;
   5.451 +
   5.452 +    /* No LDT. */
   5.453 +    ctxt->ldt_ents = 0;
   5.454 +    
   5.455 +    /* Use the default Xen-provided GDT. */
   5.456 +    ctxt->gdt_ents = 0;
   5.457 +
   5.458 +    /* Ring 1 stack is the initial stack. */
   5.459 +    ctxt->ring1_ss  = FLAT_RING1_DS;
   5.460 +    ctxt->ring1_esp = virt_startinfo_addr;
   5.461 +
   5.462 +    /* No debugging. */
   5.463 +    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
   5.464 +
   5.465 +    /* No callback handlers. */
   5.466 +    ctxt->event_callback_cs     = FLAT_RING1_CS;
   5.467 +    ctxt->event_callback_eip    = 0;
   5.468 +    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
   5.469 +    ctxt->failsafe_callback_eip = 0;
   5.470 +
   5.471 +    launch_op.u.builddomain.domain   = domid;
   5.472 +    launch_op.u.builddomain.num_vifs = 1;
   5.473 +
   5.474 +    launch_op.cmd = DOM0_BUILDDOMAIN;
   5.475 +    rc = do_dom0_op(&launch_op);
   5.476 +    
   5.477 +    return rc;
   5.478 +
   5.479 + error_out:
   5.480 +    if ( initrd_fd >= 0 )
   5.481 +        close(initrd_fd);
   5.482 +    gzclose(kernel_gfd);
   5.483 +    return -1;
   5.484 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxc/libxc_linux_restore.c	Wed Nov 19 23:05:17 2003 +0000
     6.3 @@ -0,0 +1,476 @@
     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(
    6.25 +    int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
    6.26 +{
    6.27 +    dom0_op_t op;
    6.28 +    int ret;
    6.29 +    op.cmd = DOM0_GETMEMLIST;
    6.30 +    op.u.getmemlist.domain   = domain_id;
    6.31 +    op.u.getmemlist.max_pfns = max_pfns;
    6.32 +    op.u.getmemlist.buffer   = pfn_buf;
    6.33 +
    6.34 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
    6.35 +    {
    6.36 +        PERROR("Could not lock pfn list buffer");
    6.37 +        return -1;
    6.38 +    }    
    6.39 +
    6.40 +    ret = do_dom0_op(&op);
    6.41 +
    6.42 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
    6.43 +
    6.44 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    6.45 +}
    6.46 +
    6.47 +#define MAX_MMU_UPDATES 1024
    6.48 +
    6.49 +static int flush_mmu_updates(mmu_update_t *mmu_updates,
    6.50 +                             int *mmu_update_idx)
    6.51 +{
    6.52 +    int err = 0;
    6.53 +    privcmd_hypercall_t hypercall;
    6.54 +
    6.55 +    if ( *mmu_update_idx == 0 )
    6.56 +        return 0;
    6.57 +
    6.58 +    hypercall.op     = __HYPERVISOR_mmu_update;
    6.59 +    hypercall.arg[0] = (unsigned long)mmu_updates;
    6.60 +    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
    6.61 +
    6.62 +    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
    6.63 +    {
    6.64 +        PERROR("Could not lock pagetable update array");
    6.65 +        err = 1;
    6.66 +        goto out;
    6.67 +    }
    6.68 +
    6.69 +    if ( do_xen_hypercall(&hypercall) < 0 )
    6.70 +    {
    6.71 +        ERROR("Failure when submitting mmu updates");
    6.72 +        err = 1;
    6.73 +    }
    6.74 +
    6.75 +    *mmu_update_idx = 0;
    6.76 +    
    6.77 +    (void)munlock(mmu_updates, sizeof(mmu_updates));
    6.78 +
    6.79 + out:
    6.80 +    return err;
    6.81 +}
    6.82 +
    6.83 +static int add_mmu_update(mmu_update_t *mmu_updates,
    6.84 +                          int *mmu_update_idx,
    6.85 +                          unsigned long ptr, 
    6.86 +                          unsigned long val)
    6.87 +{
    6.88 +    mmu_updates[*mmu_update_idx].ptr = ptr;
    6.89 +    mmu_updates[*mmu_update_idx].val = val;
    6.90 +    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
    6.91 +        return flush_mmu_updates(mmu_updates, mmu_update_idx);
    6.92 +    return 0;
    6.93 +}
    6.94 +
    6.95 +static int checked_read(gzFile fd, void *buf, size_t count)
    6.96 +{
    6.97 +    int rc;
    6.98 +    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
    6.99 +        continue;
   6.100 +    return rc == count;
   6.101 +}
   6.102 +
   6.103 +int xc_linux_restore(const char *state_file, int verbose)
   6.104 +{
   6.105 +    dom0_op_t op;
   6.106 +    int rc = 1, i, j;
   6.107 +    unsigned long mfn, pfn, dom = 0;
   6.108 +    unsigned int prev_pc, this_pc;
   6.109 +    
   6.110 +    /* Number of page frames in use by this XenoLinux session. */
   6.111 +    unsigned long nr_pfns;
   6.112 +
   6.113 +    /* The new domain's shared-info frame number. */
   6.114 +    unsigned long shared_info_frame;
   6.115 +    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
   6.116 +    
   6.117 +    /* A copy of the CPU context of the guest. */
   6.118 +    full_execution_context_t ctxt;
   6.119 +
   6.120 +    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
   6.121 +    char signature[16];
   6.122 +    
   6.123 +    /* A copy of the domain's name. */
   6.124 +    char name[MAX_DOMAIN_NAME];
   6.125 +
   6.126 +    /* A table containg the type of each PFN (/not/ MFN!). */
   6.127 +    unsigned long *pfn_type = NULL;
   6.128 +
   6.129 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
   6.130 +    unsigned long *ppage, page[1024];
   6.131 +
   6.132 +    /* A copy of the pfn-to-mfn table frame list. */
   6.133 +    unsigned long pfn_to_mfn_frame_list[1024];
   6.134 +
   6.135 +    /* A table mapping each PFN to its new MFN. */
   6.136 +    unsigned long *pfn_to_mfn_table = NULL;
   6.137 +
   6.138 +    /* A temporary mapping of the guest's suspend record. */
   6.139 +    suspend_record_t *p_srec;
   6.140 +
   6.141 +    /* The name and descriptor of the file that we are reading from. */
   6.142 +    int    fd;
   6.143 +    gzFile gfd;
   6.144 +
   6.145 +    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
   6.146 +    int mmu_update_idx = 0;
   6.147 +
   6.148 +    if ( (fd = open(state_file, O_RDONLY)) == -1 )
   6.149 +    {
   6.150 +        PERROR("Could not open state file for reading");
   6.151 +        return 1;
   6.152 +    }
   6.153 +
   6.154 +    if ( (gfd = gzdopen(fd, "rb")) == NULL )
   6.155 +    {
   6.156 +        ERROR("Could not allocate decompression state for state file");
   6.157 +        close(fd);
   6.158 +        return 1;
   6.159 +    }
   6.160 +
   6.161 +    /* Start writing out the saved-domain record. */
   6.162 +    if ( !checked_read(gfd, signature, 16) ||
   6.163 +         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
   6.164 +    {
   6.165 +        ERROR("Unrecognised state format -- no signature found");
   6.166 +        goto out;
   6.167 +    }
   6.168 +
   6.169 +    if ( !checked_read(gfd, name,                  sizeof(name)) ||
   6.170 +         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
   6.171 +         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
   6.172 +         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
   6.173 +         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
   6.174 +    {
   6.175 +        ERROR("Error when reading from state file");
   6.176 +        goto out;
   6.177 +    }
   6.178 +
   6.179 +    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
   6.180 +    {
   6.181 +        if ( name[i] == '\0' ) break;
   6.182 +        if ( name[i] & 0x80 )
   6.183 +        {
   6.184 +            ERROR("Random characters in domain name");
   6.185 +            goto out;
   6.186 +        }
   6.187 +    }
   6.188 +    name[MAX_DOMAIN_NAME-1] = '\0';
   6.189 +
   6.190 +    if ( nr_pfns > 1024*1024 )
   6.191 +    {
   6.192 +        ERROR("Invalid state file -- pfn count out of range");
   6.193 +        goto out;
   6.194 +    }
   6.195 +
   6.196 +    /* We want zeroed memory so use calloc rather than malloc. */
   6.197 +    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
   6.198 +    pfn_type         = calloc(1, 4 * nr_pfns);    
   6.199 +
   6.200 +    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
   6.201 +    {
   6.202 +        errno = ENOMEM;
   6.203 +        goto out;
   6.204 +    }
   6.205 +
   6.206 +    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
   6.207 +    {
   6.208 +        ERROR("Error when reading from state file");
   6.209 +        goto out;
   6.210 +    }
   6.211 +
   6.212 +    /* Create a new domain of the appropriate size, and find it's dom_id. */
   6.213 +    op.cmd = DOM0_CREATEDOMAIN;
   6.214 +    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
   6.215 +    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   6.216 +    if ( do_dom0_op(&op) < 0 )
   6.217 +    {
   6.218 +        ERROR("Could not create new domain");
   6.219 +        goto out;
   6.220 +    }
   6.221 +    dom = op.u.createdomain.domain;
   6.222 +
   6.223 +    /* Get the domain's shared-info frame. */
   6.224 +    op.cmd = DOM0_GETDOMAININFO;
   6.225 +    op.u.getdomaininfo.domain = dom;
   6.226 +    if ( do_dom0_op(&op) < 0 )
   6.227 +    {
   6.228 +        ERROR("Could not get information on new domain");
   6.229 +        goto out;
   6.230 +    }
   6.231 +    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   6.232 +
   6.233 +    if ( init_pfn_mapper() < 0 )
   6.234 +        goto out;
   6.235 +
   6.236 +    /* Copy saved contents of shared-info page. No checking needed. */
   6.237 +    ppage = map_pfn(shared_info_frame);
   6.238 +    memcpy(ppage, shared_info, PAGE_SIZE);
   6.239 +    unmap_pfn(ppage);
   6.240 +
   6.241 +    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
   6.242 +    if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
   6.243 +    {
   6.244 +        ERROR("Did not read correct number of frame numbers for new dom");
   6.245 +        goto out;
   6.246 +    }
   6.247 +
   6.248 +    verbose_printf("Reloading memory pages:   0%%");
   6.249 +
   6.250 +    /*
   6.251 +     * Now simply read each saved frame into its new machine frame.
   6.252 +     * We uncanonicalise page tables as we go.
   6.253 +     */
   6.254 +    prev_pc = 0;
   6.255 +    for ( i = 0; i < nr_pfns; i++ )
   6.256 +    {
   6.257 +        this_pc = (i * 100) / nr_pfns;
   6.258 +        if ( (this_pc - prev_pc) >= 5 )
   6.259 +        {
   6.260 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
   6.261 +            prev_pc = this_pc;
   6.262 +        }
   6.263 +
   6.264 +        mfn = pfn_to_mfn_table[i];
   6.265 +
   6.266 +        if ( !checked_read(gfd, page, PAGE_SIZE) )
   6.267 +        {
   6.268 +            ERROR("Error when reading from state file");
   6.269 +            goto out;
   6.270 +        }
   6.271 +
   6.272 +        ppage = map_pfn(mfn);
   6.273 +        switch ( pfn_type[i] )
   6.274 +        {
   6.275 +        case L1TAB:
   6.276 +            memset(ppage, 0, PAGE_SIZE);
   6.277 +            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   6.278 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   6.279 +                                MMUEXT_PIN_L1_TABLE) )
   6.280 +                goto out;
   6.281 +            for ( j = 0; j < 1024; j++ )
   6.282 +            {
   6.283 +                if ( page[j] & _PAGE_PRESENT )
   6.284 +                {
   6.285 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   6.286 +                    {
   6.287 +                        ERROR("Frame number in page table is out of range");
   6.288 +                        goto out;
   6.289 +                    }
   6.290 +                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
   6.291 +                    {
   6.292 +                        ERROR("Write access requested for a restricted frame");
   6.293 +                        goto out;
   6.294 +                    }
   6.295 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
   6.296 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.297 +                }
   6.298 +                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   6.299 +                                    (unsigned long)&ppage[j], page[j]) )
   6.300 +                    goto out;
   6.301 +            }
   6.302 +            break;
   6.303 +        case L2TAB:
   6.304 +            memset(ppage, 0, PAGE_SIZE);
   6.305 +            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   6.306 +                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
   6.307 +                                MMUEXT_PIN_L2_TABLE) )
   6.308 +                goto out;
   6.309 +            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
   6.310 +            {
   6.311 +                if ( page[j] & _PAGE_PRESENT )
   6.312 +                {
   6.313 +                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
   6.314 +                    {
   6.315 +                        ERROR("Frame number in page table is out of range");
   6.316 +                        goto out;
   6.317 +                    }
   6.318 +                    if ( pfn_type[pfn] != L1TAB )
   6.319 +                    {
   6.320 +                        ERROR("Page table mistyping");
   6.321 +                        goto out;
   6.322 +                    }
   6.323 +                    /* Haven't reached the L1 table yet. Ensure it is safe! */
   6.324 +                    if ( pfn > i )
   6.325 +                    {
   6.326 +                        unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]);
   6.327 +                        memset(l1, 0, PAGE_SIZE);
   6.328 +                        unmap_pfn(l1);
   6.329 +                    }
   6.330 +                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
   6.331 +                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.332 +                }
   6.333 +                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   6.334 +                                    (unsigned long)&ppage[j], page[j]) )
   6.335 +                    goto out;
   6.336 +            }
   6.337 +            break;
   6.338 +        default:
   6.339 +            memcpy(ppage, page, PAGE_SIZE);
   6.340 +            break;
   6.341 +        }
   6.342 +        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
   6.343 +        if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
   6.344 +            goto out;
   6.345 +        unmap_pfn(ppage);
   6.346 +
   6.347 +        if ( add_mmu_update(mmu_updates, &mmu_update_idx,
   6.348 +                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
   6.349 +            goto out;
   6.350 +    }
   6.351 +
   6.352 +    if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
   6.353 +        goto out;
   6.354 +
   6.355 +    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
   6.356 +
   6.357 +    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
   6.358 +    pfn = ctxt.i386_ctxt.esi;
   6.359 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.360 +    {
   6.361 +        ERROR("Suspend record frame number is bad");
   6.362 +        goto out;
   6.363 +    }
   6.364 +    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
   6.365 +    p_srec = map_pfn(mfn);
   6.366 +    p_srec->resume_info.nr_pages    = nr_pfns;
   6.367 +    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
   6.368 +    p_srec->resume_info.dom_id      = dom;
   6.369 +    p_srec->resume_info.flags       = 0;
   6.370 +    unmap_pfn(p_srec);
   6.371 +
   6.372 +    /* Uncanonicalise each GDT frame number. */
   6.373 +    if ( ctxt.gdt_ents > 8192 )
   6.374 +    {
   6.375 +        ERROR("GDT entry count out of range");
   6.376 +        goto out;
   6.377 +    }
   6.378 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   6.379 +    {
   6.380 +        pfn = ctxt.gdt_frames[i];
   6.381 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.382 +        {
   6.383 +            ERROR("GDT frame number is bad");
   6.384 +            goto out;
   6.385 +        }
   6.386 +        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
   6.387 +    }
   6.388 +
   6.389 +    /* Uncanonicalise the page table base pointer. */
   6.390 +    pfn = ctxt.pt_base >> PAGE_SHIFT;
   6.391 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
   6.392 +    {
   6.393 +        ERROR("PT base is bad");
   6.394 +        goto out;
   6.395 +    }
   6.396 +    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
   6.397 +
   6.398 +    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
   6.399 +    for ( i = 0; i < nr_pfns; i += 1024 )
   6.400 +    {
   6.401 +        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
   6.402 +        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
   6.403 +        pfn = pfn_to_mfn_frame_list[i/1024];
   6.404 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
   6.405 +        {
   6.406 +            ERROR("PFN-to-MFN frame number is bad");
   6.407 +            goto out;
   6.408 +        }
   6.409 +        ppage = map_pfn(pfn_to_mfn_table[pfn]);
   6.410 +        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
   6.411 +        unmap_pfn(ppage);
   6.412 +    }
   6.413 +
   6.414 +    /*
   6.415 +     * Safety checking of saved context:
   6.416 +     *  1. i386_ctxt is fine, as Xen checks that on context switch.
   6.417 +     *  2. i387_ctxt is fine, as it can't hurt Xen.
   6.418 +     *  3. trap_ctxt needs the code selectors checked.
   6.419 +     *  4. fast_trap_idx is checked by Xen.
   6.420 +     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
   6.421 +     *  6. gdt already done, and further checking is done by Xen.
   6.422 +     *  7. check that ring1_ss is safe.
   6.423 +     *  8. pt_base is already done.
   6.424 +     *  9. debugregs are checked by Xen.
   6.425 +     *  10. callback code selectors need checking.
   6.426 +     */
   6.427 +    for ( i = 0; i < 256; i++ )
   6.428 +    {
   6.429 +        ctxt.trap_ctxt[i].vector = i;
   6.430 +        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
   6.431 +            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
   6.432 +    }
   6.433 +    if ( (ctxt.ring1_ss & 3) == 0 )
   6.434 +        ctxt.ring1_ss = FLAT_RING1_DS;
   6.435 +    if ( (ctxt.event_callback_cs & 3) == 0 )
   6.436 +        ctxt.event_callback_cs = FLAT_RING1_CS;
   6.437 +    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
   6.438 +        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
   6.439 +    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
   6.440 +         (ctxt.ldt_ents > 8192) ||
   6.441 +         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
   6.442 +         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
   6.443 +    {
   6.444 +        ERROR("Bad LDT base or size");
   6.445 +        goto out;
   6.446 +    }
   6.447 +
   6.448 +    op.cmd = DOM0_BUILDDOMAIN;
   6.449 +    op.u.builddomain.domain   = dom;
   6.450 +    op.u.builddomain.num_vifs = 1;
   6.451 +    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
   6.452 +    rc = do_dom0_op(&op);
   6.453 +
   6.454 + out:
   6.455 +    if ( rc != 0 )
   6.456 +    {
   6.457 +        if ( dom != 0 )
   6.458 +        {
   6.459 +            op.cmd = DOM0_DESTROYDOMAIN;
   6.460 +            op.u.destroydomain.domain = dom;
   6.461 +            op.u.destroydomain.force  = 1;
   6.462 +            (void)do_dom0_op(&op);
   6.463 +        }
   6.464 +    }
   6.465 +    else
   6.466 +    {
   6.467 +        /* Success: print the domain id. */
   6.468 +        verbose_printf("DOM=%ld\n", dom);
   6.469 +    }
   6.470 +
   6.471 +    if ( pfn_to_mfn_table != NULL )
   6.472 +        free(pfn_to_mfn_table);
   6.473 +    if ( pfn_type != NULL )
   6.474 +        free(pfn_type);
   6.475 +
   6.476 +    gzclose(gfd);
   6.477 +
   6.478 +    return (rc == 0) ? dom : rc;
   6.479 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxc/libxc_linux_save.c	Wed Nov 19 23:05:17 2003 +0000
     7.3 @@ -0,0 +1,380 @@
     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(unsigned long mfn, unsigned int dom)
    7.45 +{
    7.46 +    dom0_op_t op;
    7.47 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
    7.48 +    op.u.getpageframeinfo.pfn = mfn;
    7.49 +    if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) )
    7.50 +        return 0;
    7.51 +    return 1;
    7.52 +}
    7.53 +
    7.54 +#define GETPFN_ERR (~0U)
    7.55 +static unsigned int get_pfn_type(unsigned long mfn)
    7.56 +{
    7.57 +    dom0_op_t op;
    7.58 +    op.cmd = DOM0_GETPAGEFRAMEINFO;
    7.59 +    op.u.getpageframeinfo.pfn = mfn;
    7.60 +    if ( do_dom0_op(&op) < 0 )
    7.61 +    {
    7.62 +        PERROR("Unexpected failure when getting page frame info!");
    7.63 +        return GETPFN_ERR;
    7.64 +    }
    7.65 +    return op.u.getpageframeinfo.type;
    7.66 +}
    7.67 +
    7.68 +static int checked_write(gzFile fd, void *buf, size_t count)
    7.69 +{
    7.70 +    int rc;
    7.71 +    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
    7.72 +        continue;
    7.73 +    return rc == count;
    7.74 +}
    7.75 +
    7.76 +int xc_linux_save(unsigned int domid, const char *state_file, int verbose)
    7.77 +{
    7.78 +    dom0_op_t op;
    7.79 +    int rc = 1, i, j;
    7.80 +    unsigned long mfn;
    7.81 +    unsigned int prev_pc, this_pc;
    7.82 +
    7.83 +    /* Remember if we stopped the guest, so we can restart it on exit. */
    7.84 +    int we_stopped_it = 0;
    7.85 +
    7.86 +    /* The new domain's shared-info frame number. */
    7.87 +    unsigned long shared_info_frame;
    7.88 +    
    7.89 +    /* A copy of the CPU context of the guest. */
    7.90 +    full_execution_context_t ctxt;
    7.91 +
    7.92 +    /* A copy of the domain's name. */
    7.93 +    char name[MAX_DOMAIN_NAME];
    7.94 +
    7.95 +    /* A table containg the type of each PFN (/not/ MFN!). */
    7.96 +    unsigned long *pfn_type = NULL;
    7.97 +
    7.98 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
    7.99 +    unsigned long *ppage, page[1024];
   7.100 +
   7.101 +    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
   7.102 +    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
   7.103 +    /* A temporary mapping of one frame in the above list. */
   7.104 +    unsigned long *pfn_to_mfn_frame;
   7.105 +
   7.106 +    /* A table mapping each PFN to its current MFN. */
   7.107 +    unsigned long *pfn_to_mfn_table = NULL;
   7.108 +    /* A table mapping each current MFN to its canonical PFN. */
   7.109 +    unsigned long *mfn_to_pfn_table = NULL;
   7.110 +    
   7.111 +    /* A temporary mapping, and a copy, of the guest's suspend record. */
   7.112 +    suspend_record_t *p_srec, srec;
   7.113 +
   7.114 +    /* The name and descriptor of the file that we are writing to. */
   7.115 +    int    fd;
   7.116 +    gzFile gfd;
   7.117 +
   7.118 +    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
   7.119 +    {
   7.120 +        PERROR("Could not open file for writing");
   7.121 +        return 1;
   7.122 +    }
   7.123 +
   7.124 +    /*
   7.125 +     * Compression rate 1: we want speed over compression. We're mainly going
   7.126 +     * for those zero pages, after all.
   7.127 +     */
   7.128 +    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
   7.129 +    {
   7.130 +        ERROR("Could not allocate compression state for state file");
   7.131 +        close(fd);
   7.132 +        return 1;
   7.133 +    }
   7.134 +
   7.135 +    /* Ensure that the domain exists, and that it is stopped. */
   7.136 +    for ( ; ; )
   7.137 +    {
   7.138 +        op.cmd = DOM0_GETDOMAININFO;
   7.139 +        op.u.getdomaininfo.domain = domid;
   7.140 +        if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
   7.141 +        {
   7.142 +            PERROR("Could not get info on domain");
   7.143 +            goto out;
   7.144 +        }
   7.145 +
   7.146 +        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
   7.147 +        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
   7.148 +        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
   7.149 +
   7.150 +        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
   7.151 +            break;
   7.152 +
   7.153 +        we_stopped_it = 1;
   7.154 +
   7.155 +        op.cmd = DOM0_STOPDOMAIN;
   7.156 +        op.u.stopdomain.domain = domid;
   7.157 +        (void)do_dom0_op(&op);
   7.158 +
   7.159 +        sleep(1);
   7.160 +    }
   7.161 +
   7.162 +    /* A cheesy test to see whether the domain contains valid state. */
   7.163 +    if ( ctxt.pt_base == 0 )
   7.164 +    {
   7.165 +        ERROR("Domain is not in a valid Xenolinux state");
   7.166 +        goto out;
   7.167 +    }
   7.168 +
   7.169 +    if ( init_pfn_mapper() < 0 )
   7.170 +        goto out;
   7.171 +
   7.172 +    /* Is the suspend-record MFN actually valid for this domain? */
   7.173 +    if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) )
   7.174 +    {
   7.175 +        ERROR("Invalid state record pointer");
   7.176 +        goto out;
   7.177 +    }
   7.178 +
   7.179 +    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
   7.180 +    p_srec = map_pfn(ctxt.i386_ctxt.esi);
   7.181 +    memcpy(&srec, p_srec, sizeof(srec));
   7.182 +    unmap_pfn(p_srec);
   7.183 +
   7.184 +    if ( srec.nr_pfns > 1024*1024 )
   7.185 +    {
   7.186 +        ERROR("Invalid state record -- pfn count out of range");
   7.187 +        goto out;
   7.188 +    }
   7.189 +
   7.190 +    if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) )
   7.191 +    {
   7.192 +        ERROR("Invalid pfn-to-mfn frame list pointer");
   7.193 +        goto out;
   7.194 +    }
   7.195 +
   7.196 +    /* Grab a copy of the pfn-to-mfn table frame list. */
   7.197 +    p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list);
   7.198 +    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
   7.199 +    unmap_pfn(p_pfn_to_mfn_frame_list);
   7.200 +
   7.201 +    /* We want zeroed memory so use calloc rather than malloc. */
   7.202 +    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
   7.203 +    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
   7.204 +    pfn_type         = calloc(1, 4 * srec.nr_pfns);
   7.205 +
   7.206 +    if ( (mfn_to_pfn_table == NULL) ||
   7.207 +         (pfn_to_mfn_table == NULL) ||
   7.208 +         (pfn_type == NULL) )
   7.209 +    {
   7.210 +        errno = ENOMEM;
   7.211 +        goto out;
   7.212 +    }
   7.213 +
   7.214 +
   7.215 +    /*
   7.216 +     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
   7.217 +     * loop we have each MFN mapped at most once. Note that there may be MFNs
   7.218 +     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
   7.219 +     */
   7.220 +    pfn_to_mfn_frame = NULL;
   7.221 +    for ( i = 0; i < srec.nr_pfns; i++ )
   7.222 +    {
   7.223 +        /* Each frameful of table frames must be checked & mapped on demand. */
   7.224 +        if ( (i & 1023) == 0 )
   7.225 +        {
   7.226 +            mfn = pfn_to_mfn_frame_list[i/1024];
   7.227 +            if ( !check_pfn_ownership(mfn, domid) )
   7.228 +            {
   7.229 +                ERROR("Invalid frame number if pfn-to-mfn frame list");
   7.230 +                goto out;
   7.231 +            }
   7.232 +            if ( pfn_to_mfn_frame != NULL )
   7.233 +                unmap_pfn(pfn_to_mfn_frame);
   7.234 +            pfn_to_mfn_frame = map_pfn(mfn);
   7.235 +        }
   7.236 +        
   7.237 +        mfn = pfn_to_mfn_frame[i & 1023];
   7.238 +
   7.239 +        if ( !check_pfn_ownership(mfn, domid) )
   7.240 +        {
   7.241 +            ERROR("Invalid frame specified with pfn-to-mfn table");
   7.242 +            goto out;
   7.243 +        }
   7.244 +
   7.245 +        /* Did we map this MFN already? That would be invalid! */
   7.246 +        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   7.247 +        {
   7.248 +            ERROR("A machine frame appears twice in pseudophys space");
   7.249 +            goto out;
   7.250 +        }
   7.251 +
   7.252 +        pfn_to_mfn_table[i] = mfn;
   7.253 +        mfn_to_pfn_table[mfn] = i;
   7.254 +
   7.255 +        /* Query page type by MFN, but store it by PFN. */
   7.256 +        if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR )
   7.257 +            goto out;
   7.258 +    }
   7.259 +
   7.260 +    /* Canonicalise the suspend-record frame number. */
   7.261 +    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
   7.262 +    {
   7.263 +        ERROR("State record is not in range of pseudophys map");
   7.264 +        goto out;
   7.265 +    }
   7.266 +
   7.267 +    /* Canonicalise each GDT frame number. */
   7.268 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
   7.269 +    {
   7.270 +        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
   7.271 +        {
   7.272 +            ERROR("GDT frame is not in range of pseudophys map");
   7.273 +            goto out;
   7.274 +        }
   7.275 +    }
   7.276 +
   7.277 +    /* Canonicalise the page table base pointer. */
   7.278 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
   7.279 +    {
   7.280 +        ERROR("PT base is not in range of pseudophys map");
   7.281 +        goto out;
   7.282 +    }
   7.283 +    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
   7.284 +
   7.285 +    /* Canonicalise the pfn-to-mfn table frame-number list. */
   7.286 +    for ( i = 0; i < srec.nr_pfns; i += 1024 )
   7.287 +    {
   7.288 +        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
   7.289 +        {
   7.290 +            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
   7.291 +            goto out;
   7.292 +        }
   7.293 +    }
   7.294 +
   7.295 +    /* Start writing out the saved-domain record. */
   7.296 +    ppage = map_pfn(shared_info_frame);
   7.297 +    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
   7.298 +         !checked_write(gfd, name,                  sizeof(name)) ||
   7.299 +         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
   7.300 +         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
   7.301 +         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
   7.302 +         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
   7.303 +         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
   7.304 +    {
   7.305 +        ERROR("Error when writing to state file");
   7.306 +        goto out;
   7.307 +    }
   7.308 +    unmap_pfn(ppage);
   7.309 +
   7.310 +    verbose_printf("Saving memory pages:   0%%");
   7.311 +
   7.312 +    /* Now write out each data page, canonicalising page tables as we go... */
   7.313 +    prev_pc = 0;
   7.314 +    for ( i = 0; i < srec.nr_pfns; i++ )
   7.315 +    {
   7.316 +        this_pc = (i * 100) / srec.nr_pfns;
   7.317 +        if ( (this_pc - prev_pc) >= 5 )
   7.318 +        {
   7.319 +            verbose_printf("\b\b\b\b%3d%%", this_pc);
   7.320 +            prev_pc = this_pc;
   7.321 +        }
   7.322 +
   7.323 +        mfn = pfn_to_mfn_table[i];
   7.324 +
   7.325 +        ppage = map_pfn(mfn);
   7.326 +        memcpy(page, ppage, PAGE_SIZE);
   7.327 +        unmap_pfn(ppage);
   7.328 +
   7.329 +        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
   7.330 +        {
   7.331 +            for ( j = 0; 
   7.332 +                  j < ((pfn_type[i] == L2TAB) ? 
   7.333 +                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
   7.334 +                  j++ )
   7.335 +            {
   7.336 +                if ( !(page[j] & _PAGE_PRESENT) ) continue;
   7.337 +                mfn = page[j] >> PAGE_SHIFT;
   7.338 +                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   7.339 +                {
   7.340 +                    ERROR("Frame number in pagetable page is invalid");
   7.341 +                    goto out;
   7.342 +                }
   7.343 +                page[j] &= PAGE_SIZE - 1;
   7.344 +                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
   7.345 +            }
   7.346 +        }
   7.347 +
   7.348 +        if ( !checked_write(gfd, page, PAGE_SIZE) )
   7.349 +        {
   7.350 +            ERROR("Error when writing to state file");
   7.351 +            goto out;
   7.352 +        }
   7.353 +    }
   7.354 +
   7.355 +    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
   7.356 +
   7.357 +    /* Success! */
   7.358 +    rc = 0;
   7.359 +
   7.360 + out:
   7.361 +    /* Restart the domain if we had to stop it to save its state. */
   7.362 +    if ( we_stopped_it )
   7.363 +    {
   7.364 +        op.cmd = DOM0_STARTDOMAIN;
   7.365 +        op.u.startdomain.domain = domid;
   7.366 +        (void)do_dom0_op(&op);
   7.367 +    }
   7.368 +
   7.369 +    gzclose(gfd);
   7.370 +
   7.371 +    if ( pfn_to_mfn_table != NULL )
   7.372 +        free(pfn_to_mfn_table);
   7.373 +    if ( mfn_to_pfn_table != NULL )
   7.374 +        free(mfn_to_pfn_table);
   7.375 +    if ( pfn_type != NULL )
   7.376 +        free(pfn_type);
   7.377 +
   7.378 +    /* On error, make sure the file is deleted. */
   7.379 +    if ( rc != 0 )
   7.380 +        unlink(state_file);
   7.381 +    
   7.382 +    return !!rc;
   7.383 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libxc/libxc_misc.c	Wed Nov 19 23:05:17 2003 +0000
     8.3 @@ -0,0 +1,50 @@
     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 privcmd_fd = -1;
    8.13 +
    8.14 +int xc_interface_open(void)
    8.15 +{
    8.16 +    if ( (privcmd_fd == -1) &&
    8.17 +         ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) )
    8.18 +    {
    8.19 +        privcmd_fd = -1;
    8.20 +        return -1;
    8.21 +    }
    8.22 +    return 0;
    8.23 +}
    8.24 +
    8.25 +int xc_interface_close(void)
    8.26 +{
    8.27 +    if ( privcmd_fd != -1 )
    8.28 +    {
    8.29 +        close(privcmd_fd);
    8.30 +        privcmd_fd = -1;
    8.31 +    }
    8.32 +    return 0;
    8.33 +}
    8.34 +
    8.35 +
    8.36 +#define CONSOLE_RING_CLEAR	1
    8.37 +
    8.38 +int xc_readconsolering(char *str, unsigned int max_chars, int clear)
    8.39 +{
    8.40 +    int ret;
    8.41 +    dom0_op_t op;
    8.42 +
    8.43 +    op.cmd = DOM0_READCONSOLE;
    8.44 +    op.u.readconsole.str = (unsigned long)str;
    8.45 +    op.u.readconsole.count = max_chars;
    8.46 +    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
    8.47 +
    8.48 +    if ( (ret = do_dom0_op(&op)) > 0 )
    8.49 +        str[ret] = '\0';
    8.50 +
    8.51 +    return ret;
    8.52 +}    
    8.53 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libxc/libxc_private.c	Wed Nov 19 23:05:17 2003 +0000
     9.3 @@ -0,0 +1,34 @@
     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 +static int devmem_fd = -1;
    9.13 +
    9.14 +int init_pfn_mapper(void)
    9.15 +{
    9.16 +    if ( (devmem_fd == -1) &&
    9.17 +         ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) )
    9.18 +    {
    9.19 +        devmem_fd = -1;
    9.20 +        return -1;
    9.21 +    }
    9.22 +    return 0;
    9.23 +}
    9.24 +
    9.25 +void *map_pfn(unsigned long pfn)
    9.26 +{
    9.27 +    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
    9.28 +                       MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT);
    9.29 +    if ( vaddr == MAP_FAILED )
    9.30 +        return NULL;
    9.31 +    return vaddr;
    9.32 +}
    9.33 +
    9.34 +void unmap_pfn(void *vaddr)
    9.35 +{
    9.36 +    (void)munmap(vaddr, PAGE_SIZE);
    9.37 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/libxc/libxc_private.h	Wed Nov 19 23:05:17 2003 +0000
    10.3 @@ -0,0 +1,155 @@
    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 +extern int privcmd_fd;
   10.73 +static inline int do_privcmd(unsigned int cmd, unsigned long data)
   10.74 +{
   10.75 +    return ioctl(privcmd_fd, cmd, data);
   10.76 +}
   10.77 +
   10.78 +static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
   10.79 +{
   10.80 +    return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
   10.81 +}
   10.82 +
   10.83 +static inline int do_dom0_op(dom0_op_t *op)
   10.84 +{
   10.85 +    int ret = -1;
   10.86 +    privcmd_hypercall_t hypercall;
   10.87 +
   10.88 +    op->interface_version = DOM0_INTERFACE_VERSION;
   10.89 +
   10.90 +    hypercall.op     = __HYPERVISOR_dom0_op;
   10.91 +    hypercall.arg[0] = (unsigned long)op;
   10.92 +
   10.93 +    if ( mlock(op, sizeof(*op)) != 0 )
   10.94 +        goto out1;
   10.95 +
   10.96 +    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
   10.97 +    {
   10.98 +        if ( errno == EACCES )
   10.99 +            fprintf(stderr, "Dom0 operation failed -- need to"
  10.100 +                    " rebuild the user-space tool set?\n");
  10.101 +        goto out2;
  10.102 +    }
  10.103 +
  10.104 +    ret = 0;
  10.105 +
  10.106 + out2: (void)munlock(op, sizeof(*op));
  10.107 + out1: return ret;
  10.108 +}
  10.109 +
  10.110 +static inline int do_network_op(network_op_t *op)
  10.111 +{
  10.112 +    int ret = -1;
  10.113 +    privcmd_hypercall_t hypercall;
  10.114 +
  10.115 +    hypercall.op     = __HYPERVISOR_network_op;
  10.116 +    hypercall.arg[0] = (unsigned long)op;
  10.117 +
  10.118 +    if ( mlock(op, sizeof(*op)) != 0 )
  10.119 +        goto out1;
  10.120 +
  10.121 +    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
  10.122 +        goto out2;
  10.123 +
  10.124 +    ret = 0;
  10.125 +
  10.126 + out2: (void)munlock(op, sizeof(*op));
  10.127 + out1: return ret;
  10.128 +}
  10.129 +
  10.130 +
  10.131 +static inline int do_block_io_op(block_io_op_t *op)
  10.132 +{
  10.133 +    int ret = -1;
  10.134 +    privcmd_hypercall_t hypercall;
  10.135 +
  10.136 +    hypercall.op     = __HYPERVISOR_block_io_op;
  10.137 +    hypercall.arg[0] = (unsigned long)op;
  10.138 +
  10.139 +    if ( mlock(op, sizeof(*op)) != 0 )
  10.140 +        goto out1;
  10.141 +
  10.142 +    if ( do_xen_hypercall(&hypercall) < 0 )
  10.143 +        goto out2;
  10.144 +
  10.145 +    ret = 0;
  10.146 +
  10.147 + out2: (void)munlock(op, sizeof(*op));
  10.148 + out1: return ret;
  10.149 +}
  10.150 +
  10.151 +/*
  10.152 + * PFN mapping.
  10.153 + */
  10.154 +int init_pfn_mapper(void);
  10.155 +void *map_pfn(unsigned long pfn);
  10.156 +void unmap_pfn(void *vaddr);
  10.157 +
  10.158 +#endif /* __LIBXC_PRIVATE_H__ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/libxc/libxc_vbd.c	Wed Nov 19 23:05:17 2003 +0000
    11.3 @@ -0,0 +1,116 @@
    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(unsigned int domid, unsigned short vbdid, int writeable)
   11.16 +{
   11.17 +    block_io_op_t op; 
   11.18 +    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   11.19 +    op.u.create_params.domain  = domid;
   11.20 +    op.u.create_params.vdevice = vbdid;
   11.21 +    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   11.22 +    return do_block_io_op(&op);
   11.23 +}
   11.24 +
   11.25 +
   11.26 +int xc_vbd_destroy(unsigned int domid, unsigned short vbdid)
   11.27 +{
   11.28 +    block_io_op_t op; 
   11.29 +    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   11.30 +    op.u.delete_params.domain  = domid;
   11.31 +    op.u.delete_params.vdevice = vbdid;
   11.32 +    return do_block_io_op(&op);
   11.33 +}
   11.34 +
   11.35 +
   11.36 +int xc_vbd_add_extent(unsigned int domid, 
   11.37 +                      unsigned short vbdid,
   11.38 +                      unsigned short real_device,
   11.39 +                      unsigned long start_sector,
   11.40 +                      unsigned long nr_sectors)
   11.41 +{
   11.42 +    block_io_op_t op; 
   11.43 +    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   11.44 +    op.u.add_params.domain  = domid; 
   11.45 +    op.u.add_params.vdevice = vbdid;
   11.46 +    op.u.add_params.extent.device       = real_device; 
   11.47 +    op.u.add_params.extent.start_sector = start_sector;
   11.48 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   11.49 +    return do_block_io_op(&op);
   11.50 +}
   11.51 +
   11.52 +
   11.53 +int xc_vbd_delete_extent(unsigned int domid, 
   11.54 +                         unsigned short vbdid,
   11.55 +                         unsigned short real_device,
   11.56 +                         unsigned long start_sector,
   11.57 +                         unsigned long nr_sectors)
   11.58 +{
   11.59 +    block_io_op_t op; 
   11.60 +    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   11.61 +    op.u.add_params.domain  = domid; 
   11.62 +    op.u.add_params.vdevice = vbdid;
   11.63 +    op.u.add_params.extent.device       = real_device; 
   11.64 +    op.u.add_params.extent.start_sector = start_sector;
   11.65 +    op.u.add_params.extent.nr_sectors   = nr_sectors;
   11.66 +    return do_block_io_op(&op);
   11.67 +}
   11.68 +
   11.69 +
   11.70 +int xc_vbd_probe(unsigned int domid,
   11.71 +                 unsigned short vbdid,
   11.72 +                 unsigned int max_vbds,
   11.73 +                 xc_vbd_t *vbds)
   11.74 +{
   11.75 +    block_io_op_t op; 
   11.76 +    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   11.77 +    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   11.78 +
   11.79 +    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   11.80 +    op.u.probe_params.domain    = domid; 
   11.81 +    
   11.82 +    xdi->max   = max_vbds;
   11.83 +    xdi->disks = malloc(allocsz);
   11.84 +    xdi->count = 0;
   11.85 +
   11.86 +    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   11.87 +    {
   11.88 +        if ( xdi->disks != NULL )
   11.89 +            free(xdi->disks);
   11.90 +        return -ENOMEM;
   11.91 +    }
   11.92 +
   11.93 +    ret = do_block_io_op(&op);
   11.94 +
   11.95 +    (void)munlock(xdi->disks, allocsz);
   11.96 +
   11.97 +    if ( ret >= 0 )
   11.98 +    {
   11.99 +	for ( i = 0, j = 0; i < xdi->count; i++ )
  11.100 +        {
  11.101 +            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  11.102 +                continue;
  11.103 +            
  11.104 +            vbds[j].domid = xdi->disks[i].domain;
  11.105 +            vbds[j].vbdid = xdi->disks[i].device;
  11.106 +            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  11.107 +                0 : XC_VBDF_WRITEABLE;
  11.108 +            vbds[j].nr_sectors = xdi->disks[i].capacity;
  11.109 +            
  11.110 +            j++;
  11.111 +        }
  11.112 +
  11.113 +        ret = j;
  11.114 +    }
  11.115 +    
  11.116 +    free(xdi->disks);
  11.117 +
  11.118 +    return ret;
  11.119 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/libxc/libxc_vif.c	Wed Nov 19 23:05:17 2003 +0000
    12.3 @@ -0,0 +1,66 @@
    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(unsigned int domid, 
   12.15 +                         unsigned int vifid, 
   12.16 +                         xc_vif_sched_params_t *params)
   12.17 +{
   12.18 +    network_op_t  netop;
   12.19 +    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   12.20 +    netop.u.vif_setparams.domain       = domid;
   12.21 +    netop.u.vif_setparams.vif          = vifid;
   12.22 +    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   12.23 +    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   12.24 +    return do_network_op(&netop);
   12.25 +}
   12.26 +
   12.27 +
   12.28 +int xc_vif_scheduler_get(unsigned int domid, 
   12.29 +                         unsigned int vifid, 
   12.30 +                         xc_vif_sched_params_t *params)
   12.31 +{
   12.32 +    network_op_t  netop;
   12.33 +    int rc;
   12.34 +
   12.35 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   12.36 +    netop.u.vif_getinfo.domain = domid;
   12.37 +    netop.u.vif_getinfo.vif    = vifid;
   12.38 +
   12.39 +    if ( (rc = do_network_op(&netop)) >= 0 )
   12.40 +    {
   12.41 +        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   12.42 +        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   12.43 +    }
   12.44 +
   12.45 +    return rc;
   12.46 +}
   12.47 +
   12.48 +
   12.49 +int xc_vif_stats_get(unsigned int domid, 
   12.50 +                     unsigned int vifid, 
   12.51 +                     xc_vif_stats_t *stats)
   12.52 +{
   12.53 +    network_op_t  netop;
   12.54 +    int rc;
   12.55 +
   12.56 +    netop.cmd = NETWORK_OP_VIFGETINFO;
   12.57 +    netop.u.vif_getinfo.domain = domid;
   12.58 +    netop.u.vif_getinfo.vif    = vifid;
   12.59 +
   12.60 +    if ( (rc = do_network_op(&netop)) >= 0 )
   12.61 +    {
   12.62 +        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   12.63 +        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   12.64 +        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   12.65 +        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   12.66 +    }
   12.67 +
   12.68 +    return rc;
   12.69 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/libxc/rpm.spec	Wed Nov 19 23:05:17 2003 +0000
    13.3 @@ -0,0 +1,28 @@
    13.4 +Summary: Xen control interface library
    13.5 +Name: xen-internal-library
    13.6 +Version: 1.2
    13.7 +Release: 1
    13.8 +License: Xen
    13.9 +Group: Xen
   13.10 +BuildRoot: %{staging}
   13.11 +%description
   13.12 +Library to make it easier to access the Xen control interfaces.
   13.13 +
   13.14 +%pre
   13.15 +%preun
   13.16 +%install
   13.17 +install -m 0755 -d $RPM_BUILD_ROOT/lib
   13.18 +install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
   13.19 +install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
   13.20 +install -m 0755 -d $RPM_BUILD_ROOT/include
   13.21 +install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
   13.22 +%clean
   13.23 +%post
   13.24 +%postun
   13.25 +%files
   13.26 +%defattr(-,root,root)
   13.27 +%dir /lib
   13.28 +/lib/libxc.a
   13.29 +/lib/libxc.so
   13.30 +%dir /include
   13.31 +/include/xc.h
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/libxc/xc.h	Wed Nov 19 23:05:17 2003 +0000
    14.3 @@ -0,0 +1,99 @@
    14.4 +/******************************************************************************
    14.5 + * xc.h
    14.6 + * 
    14.7 + * A library for low-level access to the Xen control interfaces.
    14.8 + * 
    14.9 + * Copyright (c) 2003, K A Fraser.
   14.10 + */
   14.11 +
   14.12 +#ifndef __XC_H__
   14.13 +#define __XC_H__
   14.14 +
   14.15 +int xc_interface_open(void);
   14.16 +int xc_interface_close(void);
   14.17 +
   14.18 +typedef struct {
   14.19 +    unsigned int  domid;
   14.20 +    unsigned int  cpu;
   14.21 +    int           has_cpu;
   14.22 +    int           stopped;
   14.23 +    unsigned long nr_pages;
   14.24 +    unsigned long long cpu_time;
   14.25 +#define XC_DOMINFO_MAXNAME 16
   14.26 +    char          name[XC_DOMINFO_MAXNAME];
   14.27 +} xc_dominfo_t;
   14.28 +
   14.29 +int xc_domain_create(unsigned int mem_kb, const char *name);
   14.30 +int xc_domain_start(unsigned int domid);
   14.31 +int xc_domain_stop(unsigned int domid);
   14.32 +int xc_domain_destroy(unsigned int domid, int force);
   14.33 +int xc_domain_getinfo(unsigned int first_domid, 
   14.34 +                      unsigned int max_doms,
   14.35 +                      xc_dominfo_t *info);
   14.36 +
   14.37 +int xc_linux_save(unsigned int domid, const char *state_file, int verbose);
   14.38 +int xc_linux_restore(const char *state_file, int verbose);
   14.39 +int xc_linux_build(unsigned int domid,
   14.40 +                   const char *image_name,
   14.41 +                   const char *ramdisk_name,
   14.42 +                   const char *cmdline,
   14.43 +                   int verbose);
   14.44 +
   14.45 +int xc_bvtsched_global_set(unsigned long ctx_allow);
   14.46 +int xc_bvtsched_domain_set(unsigned int domid,
   14.47 +                           unsigned long mcuadv,
   14.48 +                           unsigned long warp,
   14.49 +                           unsigned long warpl,
   14.50 +                           unsigned long warpu);
   14.51 +
   14.52 +typedef struct {
   14.53 +    unsigned long credit_bytes;
   14.54 +    unsigned long credit_usec;
   14.55 +} xc_vif_sched_params_t;
   14.56 +
   14.57 +typedef struct {
   14.58 +    unsigned long long tx_bytes, tx_pkts;
   14.59 +    unsigned long long rx_bytes, rx_pkts;
   14.60 +} xc_vif_stats_t;
   14.61 +
   14.62 +int xc_vif_scheduler_set(unsigned int domid, 
   14.63 +                         unsigned int vifid,
   14.64 +                         xc_vif_sched_params_t *params);
   14.65 +int xc_vif_scheduler_get(unsigned int domid, 
   14.66 +                         unsigned int vifid,
   14.67 +                         xc_vif_sched_params_t *params);
   14.68 +int xc_vif_stats_get(unsigned int domid, 
   14.69 +                         unsigned int vifid,
   14.70 +                         xc_vif_stats_t *stats);
   14.71 +
   14.72 +typedef struct {
   14.73 +#define XC_VBDDOM_PROBE_ALL (~0U)
   14.74 +    unsigned int   domid;
   14.75 +    unsigned short vbdid;
   14.76 +#define XC_VBDF_WRITEABLE (1<<0)
   14.77 +    unsigned long  flags;
   14.78 +    unsigned long  nr_sectors;
   14.79 +} xc_vbd_t;
   14.80 +
   14.81 +
   14.82 +int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable);
   14.83 +int xc_vbd_destroy(unsigned int domid, unsigned short vbdid);
   14.84 +int xc_vbd_add_extent(unsigned int domid, 
   14.85 +                      unsigned short vbdid,
   14.86 +                      unsigned short real_device,
   14.87 +                      unsigned long start_sector,
   14.88 +                      unsigned long nr_sectors);
   14.89 +int xc_vbd_delete_extent(unsigned int domid, 
   14.90 +                         unsigned short vbdid,
   14.91 +                         unsigned short real_device,
   14.92 +                         unsigned long start_sector,
   14.93 +                         unsigned long nr_sectors);
   14.94 +int xc_vbd_probe(unsigned int domid,
   14.95 +                 unsigned short vbdid,
   14.96 +                 unsigned int max_vbds,
   14.97 +                 xc_vbd_t *vbds);
   14.98 +
   14.99 +int xc_readconsolering(char *str, unsigned int max_chars, int clear);
  14.100 +
  14.101 +
  14.102 +#endif /* __XC_H__ */
    15.1 --- a/tools/libxi/Makefile	Wed Nov 19 17:22:42 2003 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,48 +0,0 @@
    15.4 -
    15.5 -CC       = gcc
    15.6 -CFLAGS   = -c -Wall -O3 
    15.7 -CFLAGS  += -I../../xen/include -I../../xenolinux-sparse/include
    15.8 -
    15.9 -HDRS     = $(wildcard *.h)
   15.10 -OBJS     = $(patsubst %.c,%.o,$(wildcard libxi_*.c))
   15.11 -
   15.12 -LIBS     = libxi.a libxi.so
   15.13 -
   15.14 -all: check-for-zlib $(LIBS)
   15.15 -	ranlib libxi.a
   15.16 -
   15.17 -check-for-zlib:
   15.18 -	@if [ ! -e /usr/include/zlib.h ]; then \
   15.19 -	echo "***********************************************************"; \
   15.20 -	echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
   15.21 -	echo "***********************************************************"; \
   15.22 -	false; \
   15.23 -	fi
   15.24 -
   15.25 -install: all
   15.26 -	mkdir -p ../../../install/lib
   15.27 -	mkdir -p ../../../install/include
   15.28 -	cp -a $(LIBS) ../../../install/lib
   15.29 -	for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done
   15.30 -	cp -a xi.h ../../../install/include
   15.31 -	chmod 644 ../../../install/include/xi.h
   15.32 -
   15.33 -clean:
   15.34 -	$(RM) *.a *.so *.o *.rpm $(LIBS)
   15.35 -
   15.36 -rpm: all
   15.37 -	rm -rf staging
   15.38 -	mkdir staging
   15.39 -	mkdir staging/i386
   15.40 -	rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
   15.41 -		--define "_rpmdir$$PWD/staging" -bb rpm.spec
   15.42 -	mv staging/i386/*.rpm .
   15.43 -	rm -rf staging
   15.44 -
   15.45 -libxi.so: $(OBJS)
   15.46 -	$(LD) -shared -o $@ $^ -lz
   15.47 -
   15.48 -libxi.a: libxi.a($(OBJS))
   15.49 -
   15.50 -%.o: %.c $(HDRS) Makefile
   15.51 -	$(CC) $(CFLAGS) -o $@ $<
    16.1 --- a/tools/libxi/libxi_bvtsched.c	Wed Nov 19 17:22:42 2003 +0000
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,33 +0,0 @@
    16.4 -/******************************************************************************
    16.5 - * libxi_bvtsched.c
    16.6 - * 
    16.7 - * API for manipulating parameters of the Borrowed Virtual Time scheduler.
    16.8 - * 
    16.9 - * Copyright (c) 2003, K A Fraser.
   16.10 - */
   16.11 -
   16.12 -#include "libxi_private.h"
   16.13 -
   16.14 -int xi_bvtsched_global_set(unsigned long ctx_allow)
   16.15 -{
   16.16 -    dom0_op_t op;
   16.17 -    op.cmd = DOM0_BVTCTL;
   16.18 -    op.u.bvtctl.ctx_allow = ctx_allow;
   16.19 -    return do_dom0_op(&op);
   16.20 -}
   16.21 -
   16.22 -int xi_bvtsched_domain_set(unsigned int domid,
   16.23 -                           unsigned long mcuadv,
   16.24 -                           unsigned long warp,
   16.25 -                           unsigned long warpl,
   16.26 -                           unsigned long warpu)
   16.27 -{
   16.28 -    dom0_op_t op;
   16.29 -    op.cmd = DOM0_ADJUSTDOM;
   16.30 -    op.u.adjustdom.domain  = domid;
   16.31 -    op.u.adjustdom.mcu_adv = mcuadv;
   16.32 -    op.u.adjustdom.warp    = warp;
   16.33 -    op.u.adjustdom.warpl   = warpl;
   16.34 -    op.u.adjustdom.warpu   = warpu;
   16.35 -    return do_dom0_op(&op);
   16.36 -}
    17.1 --- a/tools/libxi/libxi_domain.c	Wed Nov 19 17:22:42 2003 +0000
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,80 +0,0 @@
    17.4 -/******************************************************************************
    17.5 - * libxi_domain.c
    17.6 - * 
    17.7 - * API for manipulating and obtaining information on domains.
    17.8 - * 
    17.9 - * Copyright (c) 2003, K A Fraser.
   17.10 - */
   17.11 -
   17.12 -#include "libxi_private.h"
   17.13 -
   17.14 -int xi_domain_create(unsigned int mem_kb, const char *name)
   17.15 -{
   17.16 -    int err;
   17.17 -    dom0_op_t op;
   17.18 -
   17.19 -    op.cmd = DOM0_CREATEDOMAIN;
   17.20 -    op.u.createdomain.memory_kb = mem_kb;
   17.21 -    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
   17.22 -    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
   17.23 -
   17.24 -    err = do_dom0_op(&op);
   17.25 -
   17.26 -    return (err < 0) ? err : op.u.createdomain.domain;
   17.27 -}    
   17.28 -
   17.29 -
   17.30 -int xi_domain_start(unsigned int domid)
   17.31 -{
   17.32 -    dom0_op_t op;
   17.33 -    op.cmd = DOM0_STARTDOMAIN;
   17.34 -    op.u.startdomain.domain = domid;
   17.35 -    return do_dom0_op(&op);
   17.36 -}    
   17.37 -
   17.38 -
   17.39 -int xi_domain_stop(unsigned int domid)
   17.40 -{
   17.41 -    dom0_op_t op;
   17.42 -    op.cmd = DOM0_STOPDOMAIN;
   17.43 -    op.u.stopdomain.domain = domid;
   17.44 -    return do_dom0_op(&op);
   17.45 -}    
   17.46 -
   17.47 -
   17.48 -int xi_domain_destroy(unsigned int domid, int force)
   17.49 -{
   17.50 -    dom0_op_t op;
   17.51 -    op.cmd = DOM0_DESTROYDOMAIN;
   17.52 -    op.u.destroydomain.domain = domid;
   17.53 -    op.u.destroydomain.force  = !!force;
   17.54 -    return do_dom0_op(&op);
   17.55 -}
   17.56 -
   17.57 -int xi_domain_getinfo(unsigned int first_domid,
   17.58 -                      unsigned int max_doms,
   17.59 -                      xi_dominfo_t *info)
   17.60 -{
   17.61 -    unsigned int nr_doms, next_domid = first_domid;
   17.62 -    dom0_op_t op;
   17.63 -
   17.64 -    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
   17.65 -    {
   17.66 -        op.cmd = DOM0_GETDOMAININFO;
   17.67 -        op.u.getdomaininfo.domain = next_domid;
   17.68 -        if ( do_dom0_op(&op) < 0 )
   17.69 -            break;
   17.70 -        info->domid   = op.u.getdomaininfo.domain;
   17.71 -        info->cpu     = op.u.getdomaininfo.processor;
   17.72 -        info->has_cpu = op.u.getdomaininfo.has_cpu;
   17.73 -        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
   17.74 -        info->nr_pages = op.u.getdomaininfo.tot_pages;
   17.75 -        info->cpu_time = op.u.getdomaininfo.cpu_time;
   17.76 -        strncpy(info->name, op.u.getdomaininfo.name, XI_DOMINFO_MAXNAME);
   17.77 -        info->name[XI_DOMINFO_MAXNAME-1] = '\0';
   17.78 -
   17.79 -        next_domid = op.u.getdomaininfo.domain + 1;
   17.80 -    }
   17.81 -
   17.82 -    return nr_doms;
   17.83 -}
    18.1 --- a/tools/libxi/libxi_linux_build.c	Wed Nov 19 17:22:42 2003 +0000
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,481 +0,0 @@
    18.4 -/******************************************************************************
    18.5 - * libxi_linux_build.c
    18.6 - */
    18.7 -
    18.8 -#include "libxi_private.h"
    18.9 -#include <zlib.h>
   18.10 -
   18.11 -/* This string is written to the head of every guest kernel image. */
   18.12 -#define GUEST_SIG   "XenoGues"
   18.13 -#define SIG_LEN    8
   18.14 -
   18.15 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   18.16 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   18.17 -
   18.18 -static long get_tot_pages(int domid)
   18.19 -{
   18.20 -    dom0_op_t op;
   18.21 -    op.cmd = DOM0_GETDOMAININFO;
   18.22 -    op.u.getdomaininfo.domain = domid;
   18.23 -    return (do_dom0_op(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages;
   18.24 -}
   18.25 -
   18.26 -static int get_pfn_list(
   18.27 -    int domid, unsigned long *pfn_buf, unsigned long max_pfns)
   18.28 -{
   18.29 -    dom0_op_t op;
   18.30 -    int ret;
   18.31 -    op.cmd = DOM0_GETMEMLIST;
   18.32 -    op.u.getmemlist.domain   = domid;
   18.33 -    op.u.getmemlist.max_pfns = max_pfns;
   18.34 -    op.u.getmemlist.buffer   = pfn_buf;
   18.35 -
   18.36 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   18.37 -        return -1;
   18.38 -
   18.39 -    ret = do_dom0_op(&op);
   18.40 -
   18.41 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   18.42 -
   18.43 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   18.44 -}
   18.45 -
   18.46 -static int send_pgupdates(mmu_update_t *updates, int nr_updates)
   18.47 -{
   18.48 -    int ret = -1;
   18.49 -    privcmd_hypercall_t hypercall;
   18.50 -
   18.51 -    hypercall.op     = __HYPERVISOR_mmu_update;
   18.52 -    hypercall.arg[0] = (unsigned long)updates;
   18.53 -    hypercall.arg[1] = (unsigned long)nr_updates;
   18.54 -
   18.55 -    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
   18.56 -        goto out1;
   18.57 -
   18.58 -    if ( do_xen_hypercall(&hypercall) < 0 )
   18.59 -        goto out2;
   18.60 -
   18.61 -    ret = 0;
   18.62 -
   18.63 - out2: (void)munlock(updates, nr_updates * sizeof(*updates));
   18.64 - out1: return ret;
   18.65 -}
   18.66 -
   18.67 -/* Read the kernel header, extracting the image size and load address. */
   18.68 -static int read_kernel_header(gzFile gfd, long dom_size, 
   18.69 -                              unsigned long *load_addr, int verbose)
   18.70 -{
   18.71 -    char signature[SIG_LEN];
   18.72 -
   18.73 -    gzread(gfd, signature, SIG_LEN);
   18.74 -    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
   18.75 -    {
   18.76 -        if ( verbose )
   18.77 -            ERROR("Kernel image does not contain required signature");
   18.78 -        return -1;
   18.79 -    }
   18.80 -
   18.81 -    /* Read the load address which immediately follows the Xeno signature. */
   18.82 -    gzread(gfd, load_addr, sizeof(unsigned long));
   18.83 -
   18.84 -    return 0;
   18.85 -}
   18.86 -
   18.87 -static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
   18.88 -{
   18.89 -    void *vaddr = map_pfn(dst_pfn);
   18.90 -    if ( vaddr == NULL )
   18.91 -        return -1;
   18.92 -    memcpy(vaddr, src_page, PAGE_SIZE);
   18.93 -    unmap_pfn(vaddr);
   18.94 -    return 0;
   18.95 -}
   18.96 -
   18.97 -static int setup_guestos(
   18.98 -    int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages,
   18.99 -    unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 
  18.100 -    dom0_builddomain_t *builddomain, const char *cmdline,
  18.101 -    unsigned long shared_info_frame, int verbose)
  18.102 -{
  18.103 -    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
  18.104 -    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
  18.105 -    unsigned long *page_array = NULL;
  18.106 -    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
  18.107 -    int alloc_index, num_pt_pages;
  18.108 -    unsigned long l2tab;
  18.109 -    unsigned long l1tab = 0;
  18.110 -    unsigned long num_pgt_updates = 0;
  18.111 -    unsigned long count, pt_start, i, j;
  18.112 -    unsigned long initrd_addr = 0, initrd_len = 0;
  18.113 -    start_info_t *start_info;
  18.114 -    shared_info_t *shared_info;
  18.115 -    unsigned long ksize;
  18.116 -
  18.117 -    memset(builddomain, 0, sizeof(*builddomain));
  18.118 -
  18.119 -    if ( init_pfn_mapper() < 0 )
  18.120 -        goto error_out;
  18.121 -
  18.122 -    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
  18.123 -    page_array = malloc(tot_pages * sizeof(unsigned long));
  18.124 -    pgt_update_arr = pgt_updates;
  18.125 -    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
  18.126 -    {
  18.127 -        if ( verbose )
  18.128 -            PERROR("Could not allocate memory");
  18.129 -        goto error_out;
  18.130 -    }
  18.131 -
  18.132 -    if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
  18.133 -    {
  18.134 -        if ( verbose )
  18.135 -            PERROR("Could not get the page frame list");
  18.136 -        goto error_out;
  18.137 -    }
  18.138 -
  18.139 -    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
  18.140 -    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
  18.141 -    {
  18.142 -        char page[PAGE_SIZE];
  18.143 -        int size;
  18.144 -        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
  18.145 -        {
  18.146 -            if ( verbose )
  18.147 -                PERROR("Error reading kernel image, could not"
  18.148 -                       " read the whole image.");
  18.149 -            goto error_out;
  18.150 -        }
  18.151 -        if ( size == 0 )
  18.152 -            goto kernel_copied;
  18.153 -        copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
  18.154 -    }
  18.155 -    if ( verbose )
  18.156 -        ERROR("Kernel too big to safely fit in domain memory");
  18.157 -    goto error_out;
  18.158 -
  18.159 - kernel_copied:
  18.160 -    /* ksize is kernel-image size rounded up to a page boundary. */
  18.161 -    ksize = i;
  18.162 -
  18.163 -    /* Load the initial ramdisk image. */
  18.164 -    if ( initrd_fd >= 0 )
  18.165 -    {
  18.166 -        struct stat stat;
  18.167 -        unsigned long isize;
  18.168 -
  18.169 -        if ( fstat(initrd_fd, &stat) < 0 )
  18.170 -        {
  18.171 -            if ( verbose )
  18.172 -                PERROR("Could not stat the initrd image");
  18.173 -            goto error_out;
  18.174 -        }
  18.175 -        isize = stat.st_size;
  18.176 -        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
  18.177 -        {
  18.178 -            if ( verbose )
  18.179 -                ERROR("Kernel/initrd too big to safely fit in domain memory");
  18.180 -            goto error_out;
  18.181 -        }
  18.182 -
  18.183 -        initrd_addr = virt_load_addr + ksize;
  18.184 -        initrd_len  = isize;
  18.185 -
  18.186 -        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
  18.187 -        {
  18.188 -            char page[PAGE_SIZE];
  18.189 -            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
  18.190 -            if ( read(initrd_fd, page, size) != size )
  18.191 -            {
  18.192 -                if ( verbose )
  18.193 -                    PERROR("Error reading initrd image, could not"
  18.194 -                           " read the whole image.");
  18.195 -                goto error_out;
  18.196 -            } 
  18.197 -            copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
  18.198 -        }
  18.199 -    }
  18.200 -
  18.201 -    alloc_index = tot_pages - 1;
  18.202 -
  18.203 -    /* Count bottom-level PTs, rounding up. */
  18.204 -    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
  18.205 -
  18.206 -    /* We must also count the page directory. */
  18.207 -    num_pt_pages++;
  18.208 -
  18.209 -    /* Index of first PT page. */
  18.210 -    pt_start = tot_pages - num_pt_pages;
  18.211 -
  18.212 -    /*
  18.213 -     * First allocate page for page dir. Allocation goes backwards from the end
  18.214 -     * of the allocated physical address space.
  18.215 -     */
  18.216 -    l2tab = page_array[alloc_index] << PAGE_SHIFT;
  18.217 -    alloc_index--;
  18.218 -    builddomain->ctxt.pt_base = l2tab;
  18.219 -
  18.220 -    /*
  18.221 -     * Pin down l2tab addr as page dir page - causes hypervisor to provide
  18.222 -     * correct protection for the page
  18.223 -     */ 
  18.224 -    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
  18.225 -    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
  18.226 -    pgt_updates++;
  18.227 -    num_pgt_updates++;
  18.228 -
  18.229 -    /* Initialise the page tables. */
  18.230 -    if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL )
  18.231 -        goto error_out;
  18.232 -    memset(vl2tab, 0, PAGE_SIZE);
  18.233 -    vl2e = vl2tab + l2_table_offset(virt_load_addr);
  18.234 -    for ( count = 0; count < tot_pages; count++ )
  18.235 -    {    
  18.236 -        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
  18.237 -        {
  18.238 -            l1tab = page_array[alloc_index] << PAGE_SHIFT;
  18.239 -            if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL )
  18.240 -                goto error_out;
  18.241 -            memset(vl1tab, 0, PAGE_SIZE);
  18.242 -            alloc_index--;
  18.243 -		
  18.244 -            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
  18.245 -                                            (count << PAGE_SHIFT));
  18.246 -
  18.247 -            /* make apropriate entry in the page directory */
  18.248 -            pgt_updates->ptr = (unsigned long)vl2e;
  18.249 -            pgt_updates->val = l1tab | L2_PROT;
  18.250 -            pgt_updates++;
  18.251 -            num_pgt_updates++;
  18.252 -            vl2e++;
  18.253 -        }
  18.254 -
  18.255 -        if ( count < pt_start )
  18.256 -        {
  18.257 -            pgt_updates->ptr = (unsigned long)vl1e;
  18.258 -            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
  18.259 -            pgt_updates++;
  18.260 -            num_pgt_updates++;
  18.261 -            vl1e++;
  18.262 -        }
  18.263 -        else
  18.264 -        {
  18.265 -            pgt_updates->ptr = (unsigned long)vl1e;
  18.266 -            pgt_updates->val = 
  18.267 -                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
  18.268 -            pgt_updates++;
  18.269 -            num_pgt_updates++;
  18.270 -            vl1e++;
  18.271 -        }
  18.272 -
  18.273 -        pgt_updates->ptr = 
  18.274 -            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
  18.275 -        pgt_updates->val = count;
  18.276 -        pgt_updates++;
  18.277 -        num_pgt_updates++;
  18.278 -    }
  18.279 -
  18.280 -    *virt_startinfo_addr =
  18.281 -        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
  18.282 -
  18.283 -    start_info = map_pfn(page_array[alloc_index-1]);
  18.284 -    memset(start_info, 0, sizeof(*start_info));
  18.285 -    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
  18.286 -    start_info->mod_start   = initrd_addr;
  18.287 -    start_info->mod_len     = initrd_len;
  18.288 -    start_info->nr_pages    = tot_pages;
  18.289 -    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  18.290 -    start_info->dom_id      = dom;
  18.291 -    start_info->flags       = 0;
  18.292 -    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
  18.293 -    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
  18.294 -
  18.295 -    unmap_pfn(start_info);
  18.296 -
  18.297 -    /* shared_info page starts its life empty. */
  18.298 -    shared_info = map_pfn(shared_info_frame);
  18.299 -    memset(shared_info, 0, PAGE_SIZE);
  18.300 -    unmap_pfn(shared_info);
  18.301 -
  18.302 -    /* Send the page update requests down to the hypervisor. */
  18.303 -    if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
  18.304 -        goto error_out;
  18.305 -
  18.306 -    free(page_array);
  18.307 -    free(pgt_update_arr);
  18.308 -    return 0;
  18.309 -
  18.310 - error_out:
  18.311 -    if ( page_array == NULL )
  18.312 -        free(page_array);
  18.313 -    if ( pgt_update_arr == NULL )
  18.314 -        free(pgt_update_arr);
  18.315 -    return -1;
  18.316 -}
  18.317 -
  18.318 -int xi_domain_build(unsigned int domid,
  18.319 -                    const char *image_name,
  18.320 -                    const char *ramdisk_name,
  18.321 -                    const char *cmdline,
  18.322 -                    int verbose)
  18.323 -{
  18.324 -    dom0_op_t launch_op, op;
  18.325 -    unsigned long load_addr;
  18.326 -    long tot_pages;
  18.327 -    int kernel_fd, initrd_fd = -1;
  18.328 -    gzFile kernel_gfd;
  18.329 -    int rc, i;
  18.330 -    full_execution_context_t *ctxt;
  18.331 -    unsigned long virt_startinfo_addr;
  18.332 -
  18.333 -    if ( (tot_pages = get_tot_pages(domid)) < 0 )
  18.334 -    {
  18.335 -        if ( verbose )
  18.336 -            PERROR("Could not find total pages for domain");
  18.337 -        return 1;
  18.338 -    }
  18.339 -
  18.340 -    kernel_fd = open(image_name, O_RDONLY);
  18.341 -    if ( kernel_fd < 0 )
  18.342 -    {
  18.343 -        if ( verbose )
  18.344 -            PERROR("Could not open kernel image");
  18.345 -        return 1;
  18.346 -    }
  18.347 -
  18.348 -    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
  18.349 -    {
  18.350 -        if ( verbose )
  18.351 -            PERROR("Could not allocate decompression state for state file");
  18.352 -        close(kernel_fd);
  18.353 -        return 1;
  18.354 -    }
  18.355 -
  18.356 -    rc = read_kernel_header(kernel_gfd,
  18.357 -                            tot_pages << (PAGE_SHIFT - 10), 
  18.358 -                            &load_addr, verbose);
  18.359 -    if ( rc < 0 )
  18.360 -        goto error_out;
  18.361 -    
  18.362 -    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
  18.363 -    {
  18.364 -        if ( verbose )
  18.365 -            ERROR("We can only deal with page-aligned load addresses");
  18.366 -        goto error_out;
  18.367 -    }
  18.368 -
  18.369 -    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
  18.370 -    {
  18.371 -        if ( verbose )
  18.372 -            ERROR("Cannot map all domain memory without hitting Xen space");
  18.373 -        goto error_out;
  18.374 -    }
  18.375 -
  18.376 -    if ( ramdisk_name != NULL )
  18.377 -    {
  18.378 -        initrd_fd = open(ramdisk_name, O_RDONLY);
  18.379 -        if ( initrd_fd < 0 )
  18.380 -        {
  18.381 -            if ( verbose )
  18.382 -                PERROR("Could not open the initial ramdisk image");
  18.383 -            goto error_out;
  18.384 -        }
  18.385 -    }
  18.386 -
  18.387 -    op.cmd = DOM0_GETDOMAININFO;
  18.388 -    op.u.getdomaininfo.domain = domid;
  18.389 -    if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
  18.390 -    {
  18.391 -        if ( verbose )
  18.392 -            PERROR("Could not get info on domain");
  18.393 -        goto error_out;
  18.394 -    }
  18.395 -    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
  18.396 -         (op.u.getdomaininfo.ctxt.pt_base != 0) )
  18.397 -    {
  18.398 -        if ( verbose )
  18.399 -            ERROR("Domain is already constructed");
  18.400 -        goto error_out;
  18.401 -    }
  18.402 -
  18.403 -    if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages,
  18.404 -                       &virt_startinfo_addr,
  18.405 -                       load_addr, &launch_op.u.builddomain, cmdline,
  18.406 -                       op.u.getdomaininfo.shared_info_frame, verbose) < 0 )
  18.407 -    {
  18.408 -        if ( verbose )
  18.409 -            ERROR("Error constructing guest OS");
  18.410 -        goto error_out;
  18.411 -    }
  18.412 -
  18.413 -    if ( initrd_fd >= 0 )
  18.414 -        close(initrd_fd);
  18.415 -    gzclose(kernel_gfd);
  18.416 -
  18.417 -    ctxt = &launch_op.u.builddomain.ctxt;
  18.418 -
  18.419 -    ctxt->flags = 0;
  18.420 -
  18.421 -    /*
  18.422 -     * Initial register values:
  18.423 -     *  DS,ES,FS,GS = FLAT_RING1_DS
  18.424 -     *       CS:EIP = FLAT_RING1_CS:start_pc
  18.425 -     *       SS:ESP = FLAT_RING1_DS:start_stack
  18.426 -     *          ESI = start_info
  18.427 -     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
  18.428 -     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
  18.429 -     */
  18.430 -    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
  18.431 -    ctxt->i386_ctxt.es = FLAT_RING1_DS;
  18.432 -    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
  18.433 -    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
  18.434 -    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
  18.435 -    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
  18.436 -    ctxt->i386_ctxt.eip = load_addr;
  18.437 -    ctxt->i386_ctxt.esp = virt_startinfo_addr;
  18.438 -    ctxt->i386_ctxt.esi = virt_startinfo_addr;
  18.439 -    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
  18.440 -
  18.441 -    /* FPU is set up to default initial state. */
  18.442 -    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
  18.443 -
  18.444 -    /* Virtual IDT is empty at start-of-day. */
  18.445 -    for ( i = 0; i < 256; i++ )
  18.446 -    {
  18.447 -        ctxt->trap_ctxt[i].vector = i;
  18.448 -        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
  18.449 -    }
  18.450 -    ctxt->fast_trap_idx = 0;
  18.451 -
  18.452 -    /* No LDT. */
  18.453 -    ctxt->ldt_ents = 0;
  18.454 -    
  18.455 -    /* Use the default Xen-provided GDT. */
  18.456 -    ctxt->gdt_ents = 0;
  18.457 -
  18.458 -    /* Ring 1 stack is the initial stack. */
  18.459 -    ctxt->ring1_ss  = FLAT_RING1_DS;
  18.460 -    ctxt->ring1_esp = virt_startinfo_addr;
  18.461 -
  18.462 -    /* No debugging. */
  18.463 -    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
  18.464 -
  18.465 -    /* No callback handlers. */
  18.466 -    ctxt->event_callback_cs     = FLAT_RING1_CS;
  18.467 -    ctxt->event_callback_eip    = 0;
  18.468 -    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
  18.469 -    ctxt->failsafe_callback_eip = 0;
  18.470 -
  18.471 -    launch_op.u.builddomain.domain   = domid;
  18.472 -    launch_op.u.builddomain.num_vifs = 1;
  18.473 -
  18.474 -    launch_op.cmd = DOM0_BUILDDOMAIN;
  18.475 -    rc = do_dom0_op(&launch_op);
  18.476 -    
  18.477 -    return rc;
  18.478 -
  18.479 - error_out:
  18.480 -    if ( initrd_fd >= 0 )
  18.481 -        close(initrd_fd);
  18.482 -    gzclose(kernel_gfd);
  18.483 -    return -1;
  18.484 -}
    19.1 --- a/tools/libxi/libxi_linux_restore.c	Wed Nov 19 17:22:42 2003 +0000
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,476 +0,0 @@
    19.4 -/******************************************************************************
    19.5 - * libxi_linux_restore.c
    19.6 - * 
    19.7 - * Restore the state of a Xenolinux session.
    19.8 - * 
    19.9 - * Copyright (c) 2003, K A Fraser.
   19.10 - */
   19.11 -
   19.12 -#include "libxi_private.h"
   19.13 -#include <asm-xeno/suspend.h>
   19.14 -#include <zlib.h>
   19.15 -
   19.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
   19.17 -#define verbose_printf(_f, _a...) \
   19.18 -    do {                          \
   19.19 -        if ( !verbose ) break;    \
   19.20 -        printf( _f , ## _a );     \
   19.21 -        fflush(stdout);           \
   19.22 -    } while ( 0 )
   19.23 -
   19.24 -static int get_pfn_list(
   19.25 -    int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
   19.26 -{
   19.27 -    dom0_op_t op;
   19.28 -    int ret;
   19.29 -    op.cmd = DOM0_GETMEMLIST;
   19.30 -    op.u.getmemlist.domain   = domain_id;
   19.31 -    op.u.getmemlist.max_pfns = max_pfns;
   19.32 -    op.u.getmemlist.buffer   = pfn_buf;
   19.33 -
   19.34 -    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   19.35 -    {
   19.36 -        PERROR("Could not lock pfn list buffer");
   19.37 -        return -1;
   19.38 -    }    
   19.39 -
   19.40 -    ret = do_dom0_op(&op);
   19.41 -
   19.42 -    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   19.43 -
   19.44 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   19.45 -}
   19.46 -
   19.47 -#define MAX_MMU_UPDATES 1024
   19.48 -
   19.49 -static int flush_mmu_updates(mmu_update_t *mmu_updates,
   19.50 -                             int *mmu_update_idx)
   19.51 -{
   19.52 -    int err = 0;
   19.53 -    privcmd_hypercall_t hypercall;
   19.54 -
   19.55 -    if ( *mmu_update_idx == 0 )
   19.56 -        return 0;
   19.57 -
   19.58 -    hypercall.op     = __HYPERVISOR_mmu_update;
   19.59 -    hypercall.arg[0] = (unsigned long)mmu_updates;
   19.60 -    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
   19.61 -
   19.62 -    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
   19.63 -    {
   19.64 -        PERROR("Could not lock pagetable update array");
   19.65 -        err = 1;
   19.66 -        goto out;
   19.67 -    }
   19.68 -
   19.69 -    if ( do_xen_hypercall(&hypercall) < 0 )
   19.70 -    {
   19.71 -        ERROR("Failure when submitting mmu updates");
   19.72 -        err = 1;
   19.73 -    }
   19.74 -
   19.75 -    *mmu_update_idx = 0;
   19.76 -    
   19.77 -    (void)munlock(mmu_updates, sizeof(mmu_updates));
   19.78 -
   19.79 - out:
   19.80 -    return err;
   19.81 -}
   19.82 -
   19.83 -static int add_mmu_update(mmu_update_t *mmu_updates,
   19.84 -                          int *mmu_update_idx,
   19.85 -                          unsigned long ptr, 
   19.86 -                          unsigned long val)
   19.87 -{
   19.88 -    mmu_updates[*mmu_update_idx].ptr = ptr;
   19.89 -    mmu_updates[*mmu_update_idx].val = val;
   19.90 -    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
   19.91 -        return flush_mmu_updates(mmu_updates, mmu_update_idx);
   19.92 -    return 0;
   19.93 -}
   19.94 -
   19.95 -static int checked_read(gzFile fd, void *buf, size_t count)
   19.96 -{
   19.97 -    int rc;
   19.98 -    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
   19.99 -        continue;
  19.100 -    return rc == count;
  19.101 -}
  19.102 -
  19.103 -int xi_linux_restore(const char *state_file, int verbose)
  19.104 -{
  19.105 -    dom0_op_t op;
  19.106 -    int rc = 1, i, j;
  19.107 -    unsigned long mfn, pfn, dom = 0;
  19.108 -    unsigned int prev_pc, this_pc;
  19.109 -    
  19.110 -    /* Number of page frames in use by this XenoLinux session. */
  19.111 -    unsigned long nr_pfns;
  19.112 -
  19.113 -    /* The new domain's shared-info frame number. */
  19.114 -    unsigned long shared_info_frame;
  19.115 -    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
  19.116 -    
  19.117 -    /* A copy of the CPU context of the guest. */
  19.118 -    full_execution_context_t ctxt;
  19.119 -
  19.120 -    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
  19.121 -    char signature[16];
  19.122 -    
  19.123 -    /* A copy of the domain's name. */
  19.124 -    char name[MAX_DOMAIN_NAME];
  19.125 -
  19.126 -    /* A table containg the type of each PFN (/not/ MFN!). */
  19.127 -    unsigned long *pfn_type = NULL;
  19.128 -
  19.129 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
  19.130 -    unsigned long *ppage, page[1024];
  19.131 -
  19.132 -    /* A copy of the pfn-to-mfn table frame list. */
  19.133 -    unsigned long pfn_to_mfn_frame_list[1024];
  19.134 -
  19.135 -    /* A table mapping each PFN to its new MFN. */
  19.136 -    unsigned long *pfn_to_mfn_table = NULL;
  19.137 -
  19.138 -    /* A temporary mapping of the guest's suspend record. */
  19.139 -    suspend_record_t *p_srec;
  19.140 -
  19.141 -    /* The name and descriptor of the file that we are reading from. */
  19.142 -    int    fd;
  19.143 -    gzFile gfd;
  19.144 -
  19.145 -    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
  19.146 -    int mmu_update_idx = 0;
  19.147 -
  19.148 -    if ( (fd = open(state_file, O_RDONLY)) == -1 )
  19.149 -    {
  19.150 -        PERROR("Could not open state file for reading");
  19.151 -        return 1;
  19.152 -    }
  19.153 -
  19.154 -    if ( (gfd = gzdopen(fd, "rb")) == NULL )
  19.155 -    {
  19.156 -        ERROR("Could not allocate decompression state for state file");
  19.157 -        close(fd);
  19.158 -        return 1;
  19.159 -    }
  19.160 -
  19.161 -    /* Start writing out the saved-domain record. */
  19.162 -    if ( !checked_read(gfd, signature, 16) ||
  19.163 -         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
  19.164 -    {
  19.165 -        ERROR("Unrecognised state format -- no signature found");
  19.166 -        goto out;
  19.167 -    }
  19.168 -
  19.169 -    if ( !checked_read(gfd, name,                  sizeof(name)) ||
  19.170 -         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
  19.171 -         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
  19.172 -         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
  19.173 -         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
  19.174 -    {
  19.175 -        ERROR("Error when reading from state file");
  19.176 -        goto out;
  19.177 -    }
  19.178 -
  19.179 -    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
  19.180 -    {
  19.181 -        if ( name[i] == '\0' ) break;
  19.182 -        if ( name[i] & 0x80 )
  19.183 -        {
  19.184 -            ERROR("Random characters in domain name");
  19.185 -            goto out;
  19.186 -        }
  19.187 -    }
  19.188 -    name[MAX_DOMAIN_NAME-1] = '\0';
  19.189 -
  19.190 -    if ( nr_pfns > 1024*1024 )
  19.191 -    {
  19.192 -        ERROR("Invalid state file -- pfn count out of range");
  19.193 -        goto out;
  19.194 -    }
  19.195 -
  19.196 -    /* We want zeroed memory so use calloc rather than malloc. */
  19.197 -    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
  19.198 -    pfn_type         = calloc(1, 4 * nr_pfns);    
  19.199 -
  19.200 -    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
  19.201 -    {
  19.202 -        errno = ENOMEM;
  19.203 -        goto out;
  19.204 -    }
  19.205 -
  19.206 -    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
  19.207 -    {
  19.208 -        ERROR("Error when reading from state file");
  19.209 -        goto out;
  19.210 -    }
  19.211 -
  19.212 -    /* Create a new domain of the appropriate size, and find it's dom_id. */
  19.213 -    op.cmd = DOM0_CREATEDOMAIN;
  19.214 -    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
  19.215 -    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
  19.216 -    if ( do_dom0_op(&op) < 0 )
  19.217 -    {
  19.218 -        ERROR("Could not create new domain");
  19.219 -        goto out;
  19.220 -    }
  19.221 -    dom = op.u.createdomain.domain;
  19.222 -
  19.223 -    /* Get the domain's shared-info frame. */
  19.224 -    op.cmd = DOM0_GETDOMAININFO;
  19.225 -    op.u.getdomaininfo.domain = dom;
  19.226 -    if ( do_dom0_op(&op) < 0 )
  19.227 -    {
  19.228 -        ERROR("Could not get information on new domain");
  19.229 -        goto out;
  19.230 -    }
  19.231 -    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  19.232 -
  19.233 -    if ( init_pfn_mapper() < 0 )
  19.234 -        goto out;
  19.235 -
  19.236 -    /* Copy saved contents of shared-info page. No checking needed. */
  19.237 -    ppage = map_pfn(shared_info_frame);
  19.238 -    memcpy(ppage, shared_info, PAGE_SIZE);
  19.239 -    unmap_pfn(ppage);
  19.240 -
  19.241 -    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
  19.242 -    if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
  19.243 -    {
  19.244 -        ERROR("Did not read correct number of frame numbers for new dom");
  19.245 -        goto out;
  19.246 -    }
  19.247 -
  19.248 -    verbose_printf("Reloading memory pages:   0%%");
  19.249 -
  19.250 -    /*
  19.251 -     * Now simply read each saved frame into its new machine frame.
  19.252 -     * We uncanonicalise page tables as we go.
  19.253 -     */
  19.254 -    prev_pc = 0;
  19.255 -    for ( i = 0; i < nr_pfns; i++ )
  19.256 -    {
  19.257 -        this_pc = (i * 100) / nr_pfns;
  19.258 -        if ( (this_pc - prev_pc) >= 5 )
  19.259 -        {
  19.260 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
  19.261 -            prev_pc = this_pc;
  19.262 -        }
  19.263 -
  19.264 -        mfn = pfn_to_mfn_table[i];
  19.265 -
  19.266 -        if ( !checked_read(gfd, page, PAGE_SIZE) )
  19.267 -        {
  19.268 -            ERROR("Error when reading from state file");
  19.269 -            goto out;
  19.270 -        }
  19.271 -
  19.272 -        ppage = map_pfn(mfn);
  19.273 -        switch ( pfn_type[i] )
  19.274 -        {
  19.275 -        case L1TAB:
  19.276 -            memset(ppage, 0, PAGE_SIZE);
  19.277 -            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
  19.278 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  19.279 -                                MMUEXT_PIN_L1_TABLE) )
  19.280 -                goto out;
  19.281 -            for ( j = 0; j < 1024; j++ )
  19.282 -            {
  19.283 -                if ( page[j] & _PAGE_PRESENT )
  19.284 -                {
  19.285 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  19.286 -                    {
  19.287 -                        ERROR("Frame number in page table is out of range");
  19.288 -                        goto out;
  19.289 -                    }
  19.290 -                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
  19.291 -                    {
  19.292 -                        ERROR("Write access requested for a restricted frame");
  19.293 -                        goto out;
  19.294 -                    }
  19.295 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
  19.296 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  19.297 -                }
  19.298 -                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
  19.299 -                                    (unsigned long)&ppage[j], page[j]) )
  19.300 -                    goto out;
  19.301 -            }
  19.302 -            break;
  19.303 -        case L2TAB:
  19.304 -            memset(ppage, 0, PAGE_SIZE);
  19.305 -            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
  19.306 -                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
  19.307 -                                MMUEXT_PIN_L2_TABLE) )
  19.308 -                goto out;
  19.309 -            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
  19.310 -            {
  19.311 -                if ( page[j] & _PAGE_PRESENT )
  19.312 -                {
  19.313 -                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
  19.314 -                    {
  19.315 -                        ERROR("Frame number in page table is out of range");
  19.316 -                        goto out;
  19.317 -                    }
  19.318 -                    if ( pfn_type[pfn] != L1TAB )
  19.319 -                    {
  19.320 -                        ERROR("Page table mistyping");
  19.321 -                        goto out;
  19.322 -                    }
  19.323 -                    /* Haven't reached the L1 table yet. Ensure it is safe! */
  19.324 -                    if ( pfn > i )
  19.325 -                    {
  19.326 -                        unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]);
  19.327 -                        memset(l1, 0, PAGE_SIZE);
  19.328 -                        unmap_pfn(l1);
  19.329 -                    }
  19.330 -                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
  19.331 -                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  19.332 -                }
  19.333 -                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
  19.334 -                                    (unsigned long)&ppage[j], page[j]) )
  19.335 -                    goto out;
  19.336 -            }
  19.337 -            break;
  19.338 -        default:
  19.339 -            memcpy(ppage, page, PAGE_SIZE);
  19.340 -            break;
  19.341 -        }
  19.342 -        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
  19.343 -        if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
  19.344 -            goto out;
  19.345 -        unmap_pfn(ppage);
  19.346 -
  19.347 -        if ( add_mmu_update(mmu_updates, &mmu_update_idx,
  19.348 -                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
  19.349 -            goto out;
  19.350 -    }
  19.351 -
  19.352 -    if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
  19.353 -        goto out;
  19.354 -
  19.355 -    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
  19.356 -
  19.357 -    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
  19.358 -    pfn = ctxt.i386_ctxt.esi;
  19.359 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  19.360 -    {
  19.361 -        ERROR("Suspend record frame number is bad");
  19.362 -        goto out;
  19.363 -    }
  19.364 -    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
  19.365 -    p_srec = map_pfn(mfn);
  19.366 -    p_srec->resume_info.nr_pages    = nr_pfns;
  19.367 -    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
  19.368 -    p_srec->resume_info.dom_id      = dom;
  19.369 -    p_srec->resume_info.flags       = 0;
  19.370 -    unmap_pfn(p_srec);
  19.371 -
  19.372 -    /* Uncanonicalise each GDT frame number. */
  19.373 -    if ( ctxt.gdt_ents > 8192 )
  19.374 -    {
  19.375 -        ERROR("GDT entry count out of range");
  19.376 -        goto out;
  19.377 -    }
  19.378 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  19.379 -    {
  19.380 -        pfn = ctxt.gdt_frames[i];
  19.381 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  19.382 -        {
  19.383 -            ERROR("GDT frame number is bad");
  19.384 -            goto out;
  19.385 -        }
  19.386 -        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
  19.387 -    }
  19.388 -
  19.389 -    /* Uncanonicalise the page table base pointer. */
  19.390 -    pfn = ctxt.pt_base >> PAGE_SHIFT;
  19.391 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
  19.392 -    {
  19.393 -        ERROR("PT base is bad");
  19.394 -        goto out;
  19.395 -    }
  19.396 -    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  19.397 -
  19.398 -    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
  19.399 -    for ( i = 0; i < nr_pfns; i += 1024 )
  19.400 -    {
  19.401 -        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
  19.402 -        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
  19.403 -        pfn = pfn_to_mfn_frame_list[i/1024];
  19.404 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
  19.405 -        {
  19.406 -            ERROR("PFN-to-MFN frame number is bad");
  19.407 -            goto out;
  19.408 -        }
  19.409 -        ppage = map_pfn(pfn_to_mfn_table[pfn]);
  19.410 -        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
  19.411 -        unmap_pfn(ppage);
  19.412 -    }
  19.413 -
  19.414 -    /*
  19.415 -     * Safety checking of saved context:
  19.416 -     *  1. i386_ctxt is fine, as Xen checks that on context switch.
  19.417 -     *  2. i387_ctxt is fine, as it can't hurt Xen.
  19.418 -     *  3. trap_ctxt needs the code selectors checked.
  19.419 -     *  4. fast_trap_idx is checked by Xen.
  19.420 -     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
  19.421 -     *  6. gdt already done, and further checking is done by Xen.
  19.422 -     *  7. check that ring1_ss is safe.
  19.423 -     *  8. pt_base is already done.
  19.424 -     *  9. debugregs are checked by Xen.
  19.425 -     *  10. callback code selectors need checking.
  19.426 -     */
  19.427 -    for ( i = 0; i < 256; i++ )
  19.428 -    {
  19.429 -        ctxt.trap_ctxt[i].vector = i;
  19.430 -        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
  19.431 -            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
  19.432 -    }
  19.433 -    if ( (ctxt.ring1_ss & 3) == 0 )
  19.434 -        ctxt.ring1_ss = FLAT_RING1_DS;
  19.435 -    if ( (ctxt.event_callback_cs & 3) == 0 )
  19.436 -        ctxt.event_callback_cs = FLAT_RING1_CS;
  19.437 -    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
  19.438 -        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
  19.439 -    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
  19.440 -         (ctxt.ldt_ents > 8192) ||
  19.441 -         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
  19.442 -         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
  19.443 -    {
  19.444 -        ERROR("Bad LDT base or size");
  19.445 -        goto out;
  19.446 -    }
  19.447 -
  19.448 -    op.cmd = DOM0_BUILDDOMAIN;
  19.449 -    op.u.builddomain.domain   = dom;
  19.450 -    op.u.builddomain.num_vifs = 1;
  19.451 -    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
  19.452 -    rc = do_dom0_op(&op);
  19.453 -
  19.454 - out:
  19.455 -    if ( rc != 0 )
  19.456 -    {
  19.457 -        if ( dom != 0 )
  19.458 -        {
  19.459 -            op.cmd = DOM0_DESTROYDOMAIN;
  19.460 -            op.u.destroydomain.domain = dom;
  19.461 -            op.u.destroydomain.force  = 1;
  19.462 -            (void)do_dom0_op(&op);
  19.463 -        }
  19.464 -    }
  19.465 -    else
  19.466 -    {
  19.467 -        /* Success: print the domain id. */
  19.468 -        verbose_printf("DOM=%ld\n", dom);
  19.469 -    }
  19.470 -
  19.471 -    if ( pfn_to_mfn_table != NULL )
  19.472 -        free(pfn_to_mfn_table);
  19.473 -    if ( pfn_type != NULL )
  19.474 -        free(pfn_type);
  19.475 -
  19.476 -    gzclose(gfd);
  19.477 -
  19.478 -    return (rc == 0) ? dom : rc;
  19.479 -}
    20.1 --- a/tools/libxi/libxi_linux_save.c	Wed Nov 19 17:22:42 2003 +0000
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,380 +0,0 @@
    20.4 -/******************************************************************************
    20.5 - * libxi_linux_save.c
    20.6 - * 
    20.7 - * Save the state of a running Xenolinux session.
    20.8 - * 
    20.9 - * Copyright (c) 2003, K A Fraser.
   20.10 - */
   20.11 -
   20.12 -#include "libxi_private.h"
   20.13 -#include <asm-xeno/suspend.h>
   20.14 -#include <zlib.h>
   20.15 -
   20.16 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
   20.17 -#define verbose_printf(_f, _a...) \
   20.18 -    do {                          \
   20.19 -        if ( !verbose ) break;    \
   20.20 -        printf( _f , ## _a );     \
   20.21 -        fflush(stdout);           \
   20.22 -    } while ( 0 )
   20.23 -
   20.24 -/*
   20.25 - * Returns TRUE if the given machine frame number has a unique mapping
   20.26 - * in the guest's pseudophysical map.
   20.27 - */
   20.28 -#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
   20.29 -    (((_mfn) < (1024*1024)) &&          \
   20.30 -     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
   20.31 -
   20.32 -/* Returns TRUE if MFN is successfully converted to a PFN. */
   20.33 -#define translate_mfn_to_pfn(_pmfn)         \
   20.34 -({                                          \
   20.35 -    unsigned long mfn = *(_pmfn);           \
   20.36 -    int _res = 1;                           \
   20.37 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
   20.38 -        _res = 0;                           \
   20.39 -    else                                    \
   20.40 -        *(_pmfn) = mfn_to_pfn_table[mfn];   \
   20.41 -    _res;                                   \
   20.42 -})
   20.43 -
   20.44 -static int check_pfn_ownership(unsigned long mfn, unsigned int dom)
   20.45 -{
   20.46 -    dom0_op_t op;
   20.47 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
   20.48 -    op.u.getpageframeinfo.pfn = mfn;
   20.49 -    if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) )
   20.50 -        return 0;
   20.51 -    return 1;
   20.52 -}
   20.53 -
   20.54 -#define GETPFN_ERR (~0U)
   20.55 -static unsigned int get_pfn_type(unsigned long mfn)
   20.56 -{
   20.57 -    dom0_op_t op;
   20.58 -    op.cmd = DOM0_GETPAGEFRAMEINFO;
   20.59 -    op.u.getpageframeinfo.pfn = mfn;
   20.60 -    if ( do_dom0_op(&op) < 0 )
   20.61 -    {
   20.62 -        PERROR("Unexpected failure when getting page frame info!");
   20.63 -        return GETPFN_ERR;
   20.64 -    }
   20.65 -    return op.u.getpageframeinfo.type;
   20.66 -}
   20.67 -
   20.68 -static int checked_write(gzFile fd, void *buf, size_t count)
   20.69 -{
   20.70 -    int rc;
   20.71 -    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
   20.72 -        continue;
   20.73 -    return rc == count;
   20.74 -}
   20.75 -
   20.76 -int xi_linux_save(unsigned int domid, const char *state_file, int verbose)
   20.77 -{
   20.78 -    dom0_op_t op;
   20.79 -    int rc = 1, i, j;
   20.80 -    unsigned long mfn;
   20.81 -    unsigned int prev_pc, this_pc;
   20.82 -
   20.83 -    /* Remember if we stopped the guest, so we can restart it on exit. */
   20.84 -    int we_stopped_it = 0;
   20.85 -
   20.86 -    /* The new domain's shared-info frame number. */
   20.87 -    unsigned long shared_info_frame;
   20.88 -    
   20.89 -    /* A copy of the CPU context of the guest. */
   20.90 -    full_execution_context_t ctxt;
   20.91 -
   20.92 -    /* A copy of the domain's name. */
   20.93 -    char name[MAX_DOMAIN_NAME];
   20.94 -
   20.95 -    /* A table containg the type of each PFN (/not/ MFN!). */
   20.96 -    unsigned long *pfn_type = NULL;
   20.97 -
   20.98 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
   20.99 -    unsigned long *ppage, page[1024];
  20.100 -
  20.101 -    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
  20.102 -    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
  20.103 -    /* A temporary mapping of one frame in the above list. */
  20.104 -    unsigned long *pfn_to_mfn_frame;
  20.105 -
  20.106 -    /* A table mapping each PFN to its current MFN. */
  20.107 -    unsigned long *pfn_to_mfn_table = NULL;
  20.108 -    /* A table mapping each current MFN to its canonical PFN. */
  20.109 -    unsigned long *mfn_to_pfn_table = NULL;
  20.110 -    
  20.111 -    /* A temporary mapping, and a copy, of the guest's suspend record. */
  20.112 -    suspend_record_t *p_srec, srec;
  20.113 -
  20.114 -    /* The name and descriptor of the file that we are writing to. */
  20.115 -    int    fd;
  20.116 -    gzFile gfd;
  20.117 -
  20.118 -    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
  20.119 -    {
  20.120 -        PERROR("Could not open file for writing");
  20.121 -        return 1;
  20.122 -    }
  20.123 -
  20.124 -    /*
  20.125 -     * Compression rate 1: we want speed over compression. We're mainly going
  20.126 -     * for those zero pages, after all.
  20.127 -     */
  20.128 -    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
  20.129 -    {
  20.130 -        ERROR("Could not allocate compression state for state file");
  20.131 -        close(fd);
  20.132 -        return 1;
  20.133 -    }
  20.134 -
  20.135 -    /* Ensure that the domain exists, and that it is stopped. */
  20.136 -    for ( ; ; )
  20.137 -    {
  20.138 -        op.cmd = DOM0_GETDOMAININFO;
  20.139 -        op.u.getdomaininfo.domain = domid;
  20.140 -        if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
  20.141 -        {
  20.142 -            PERROR("Could not get info on domain");
  20.143 -            goto out;
  20.144 -        }
  20.145 -
  20.146 -        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
  20.147 -        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
  20.148 -        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  20.149 -
  20.150 -        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
  20.151 -            break;
  20.152 -
  20.153 -        we_stopped_it = 1;
  20.154 -
  20.155 -        op.cmd = DOM0_STOPDOMAIN;
  20.156 -        op.u.stopdomain.domain = domid;
  20.157 -        (void)do_dom0_op(&op);
  20.158 -
  20.159 -        sleep(1);
  20.160 -    }
  20.161 -
  20.162 -    /* A cheesy test to see whether the domain contains valid state. */
  20.163 -    if ( ctxt.pt_base == 0 )
  20.164 -    {
  20.165 -        ERROR("Domain is not in a valid Xenolinux state");
  20.166 -        goto out;
  20.167 -    }
  20.168 -
  20.169 -    if ( init_pfn_mapper() < 0 )
  20.170 -        goto out;
  20.171 -
  20.172 -    /* Is the suspend-record MFN actually valid for this domain? */
  20.173 -    if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) )
  20.174 -    {
  20.175 -        ERROR("Invalid state record pointer");
  20.176 -        goto out;
  20.177 -    }
  20.178 -
  20.179 -    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
  20.180 -    p_srec = map_pfn(ctxt.i386_ctxt.esi);
  20.181 -    memcpy(&srec, p_srec, sizeof(srec));
  20.182 -    unmap_pfn(p_srec);
  20.183 -
  20.184 -    if ( srec.nr_pfns > 1024*1024 )
  20.185 -    {
  20.186 -        ERROR("Invalid state record -- pfn count out of range");
  20.187 -        goto out;
  20.188 -    }
  20.189 -
  20.190 -    if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) )
  20.191 -    {
  20.192 -        ERROR("Invalid pfn-to-mfn frame list pointer");
  20.193 -        goto out;
  20.194 -    }
  20.195 -
  20.196 -    /* Grab a copy of the pfn-to-mfn table frame list. */
  20.197 -    p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list);
  20.198 -    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
  20.199 -    unmap_pfn(p_pfn_to_mfn_frame_list);
  20.200 -
  20.201 -    /* We want zeroed memory so use calloc rather than malloc. */
  20.202 -    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
  20.203 -    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
  20.204 -    pfn_type         = calloc(1, 4 * srec.nr_pfns);
  20.205 -
  20.206 -    if ( (mfn_to_pfn_table == NULL) ||
  20.207 -         (pfn_to_mfn_table == NULL) ||
  20.208 -         (pfn_type == NULL) )
  20.209 -    {
  20.210 -        errno = ENOMEM;
  20.211 -        goto out;
  20.212 -    }
  20.213 -
  20.214 -
  20.215 -    /*
  20.216 -     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
  20.217 -     * loop we have each MFN mapped at most once. Note that there may be MFNs
  20.218 -     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
  20.219 -     */
  20.220 -    pfn_to_mfn_frame = NULL;
  20.221 -    for ( i = 0; i < srec.nr_pfns; i++ )
  20.222 -    {
  20.223 -        /* Each frameful of table frames must be checked & mapped on demand. */
  20.224 -        if ( (i & 1023) == 0 )
  20.225 -        {
  20.226 -            mfn = pfn_to_mfn_frame_list[i/1024];
  20.227 -            if ( !check_pfn_ownership(mfn, domid) )
  20.228 -            {
  20.229 -                ERROR("Invalid frame number if pfn-to-mfn frame list");
  20.230 -                goto out;
  20.231 -            }
  20.232 -            if ( pfn_to_mfn_frame != NULL )
  20.233 -                unmap_pfn(pfn_to_mfn_frame);
  20.234 -            pfn_to_mfn_frame = map_pfn(mfn);
  20.235 -        }
  20.236 -        
  20.237 -        mfn = pfn_to_mfn_frame[i & 1023];
  20.238 -
  20.239 -        if ( !check_pfn_ownership(mfn, domid) )
  20.240 -        {
  20.241 -            ERROR("Invalid frame specified with pfn-to-mfn table");
  20.242 -            goto out;
  20.243 -        }
  20.244 -
  20.245 -        /* Did we map this MFN already? That would be invalid! */
  20.246 -        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  20.247 -        {
  20.248 -            ERROR("A machine frame appears twice in pseudophys space");
  20.249 -            goto out;
  20.250 -        }
  20.251 -
  20.252 -        pfn_to_mfn_table[i] = mfn;
  20.253 -        mfn_to_pfn_table[mfn] = i;
  20.254 -
  20.255 -        /* Query page type by MFN, but store it by PFN. */
  20.256 -        if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR )
  20.257 -            goto out;
  20.258 -    }
  20.259 -
  20.260 -    /* Canonicalise the suspend-record frame number. */
  20.261 -    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
  20.262 -    {
  20.263 -        ERROR("State record is not in range of pseudophys map");
  20.264 -        goto out;
  20.265 -    }
  20.266 -
  20.267 -    /* Canonicalise each GDT frame number. */
  20.268 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  20.269 -    {
  20.270 -        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
  20.271 -        {
  20.272 -            ERROR("GDT frame is not in range of pseudophys map");
  20.273 -            goto out;
  20.274 -        }
  20.275 -    }
  20.276 -
  20.277 -    /* Canonicalise the page table base pointer. */
  20.278 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
  20.279 -    {
  20.280 -        ERROR("PT base is not in range of pseudophys map");
  20.281 -        goto out;
  20.282 -    }
  20.283 -    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
  20.284 -
  20.285 -    /* Canonicalise the pfn-to-mfn table frame-number list. */
  20.286 -    for ( i = 0; i < srec.nr_pfns; i += 1024 )
  20.287 -    {
  20.288 -        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
  20.289 -        {
  20.290 -            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
  20.291 -            goto out;
  20.292 -        }
  20.293 -    }
  20.294 -
  20.295 -    /* Start writing out the saved-domain record. */
  20.296 -    ppage = map_pfn(shared_info_frame);
  20.297 -    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
  20.298 -         !checked_write(gfd, name,                  sizeof(name)) ||
  20.299 -         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
  20.300 -         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
  20.301 -         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
  20.302 -         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
  20.303 -         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
  20.304 -    {
  20.305 -        ERROR("Error when writing to state file");
  20.306 -        goto out;
  20.307 -    }
  20.308 -    unmap_pfn(ppage);
  20.309 -
  20.310 -    verbose_printf("Saving memory pages:   0%%");
  20.311 -
  20.312 -    /* Now write out each data page, canonicalising page tables as we go... */
  20.313 -    prev_pc = 0;
  20.314 -    for ( i = 0; i < srec.nr_pfns; i++ )
  20.315 -    {
  20.316 -        this_pc = (i * 100) / srec.nr_pfns;
  20.317 -        if ( (this_pc - prev_pc) >= 5 )
  20.318 -        {
  20.319 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
  20.320 -            prev_pc = this_pc;
  20.321 -        }
  20.322 -
  20.323 -        mfn = pfn_to_mfn_table[i];
  20.324 -
  20.325 -        ppage = map_pfn(mfn);
  20.326 -        memcpy(page, ppage, PAGE_SIZE);
  20.327 -        unmap_pfn(ppage);
  20.328 -
  20.329 -        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
  20.330 -        {
  20.331 -            for ( j = 0; 
  20.332 -                  j < ((pfn_type[i] == L2TAB) ? 
  20.333 -                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
  20.334 -                  j++ )
  20.335 -            {
  20.336 -                if ( !(page[j] & _PAGE_PRESENT) ) continue;
  20.337 -                mfn = page[j] >> PAGE_SHIFT;
  20.338 -                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
  20.339 -                {
  20.340 -                    ERROR("Frame number in pagetable page is invalid");
  20.341 -                    goto out;
  20.342 -                }
  20.343 -                page[j] &= PAGE_SIZE - 1;
  20.344 -                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
  20.345 -            }
  20.346 -        }
  20.347 -
  20.348 -        if ( !checked_write(gfd, page, PAGE_SIZE) )
  20.349 -        {
  20.350 -            ERROR("Error when writing to state file");
  20.351 -            goto out;
  20.352 -        }
  20.353 -    }
  20.354 -
  20.355 -    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
  20.356 -
  20.357 -    /* Success! */
  20.358 -    rc = 0;
  20.359 -
  20.360 - out:
  20.361 -    /* Restart the domain if we had to stop it to save its state. */
  20.362 -    if ( we_stopped_it )
  20.363 -    {
  20.364 -        op.cmd = DOM0_STARTDOMAIN;
  20.365 -        op.u.startdomain.domain = domid;
  20.366 -        (void)do_dom0_op(&op);
  20.367 -    }
  20.368 -
  20.369 -    gzclose(gfd);
  20.370 -
  20.371 -    if ( pfn_to_mfn_table != NULL )
  20.372 -        free(pfn_to_mfn_table);
  20.373 -    if ( mfn_to_pfn_table != NULL )
  20.374 -        free(mfn_to_pfn_table);
  20.375 -    if ( pfn_type != NULL )
  20.376 -        free(pfn_type);
  20.377 -
  20.378 -    /* On error, make sure the file is deleted. */
  20.379 -    if ( rc != 0 )
  20.380 -        unlink(state_file);
  20.381 -    
  20.382 -    return !!rc;
  20.383 -}
    21.1 --- a/tools/libxi/libxi_misc.c	Wed Nov 19 17:22:42 2003 +0000
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,50 +0,0 @@
    21.4 -/******************************************************************************
    21.5 - * libxi_misc.c
    21.6 - * 
    21.7 - * Miscellaneous control interface functions.
    21.8 - */
    21.9 -
   21.10 -#include "libxi_private.h"
   21.11 -
   21.12 -int privcmd_fd = -1;
   21.13 -
   21.14 -int xi_interface_open(void)
   21.15 -{
   21.16 -    if ( (privcmd_fd == -1) &&
   21.17 -         ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) )
   21.18 -    {
   21.19 -        privcmd_fd = -1;
   21.20 -        return -1;
   21.21 -    }
   21.22 -    return 0;
   21.23 -}
   21.24 -
   21.25 -int xi_interface_close(void)
   21.26 -{
   21.27 -    if ( privcmd_fd != -1 )
   21.28 -    {
   21.29 -        close(privcmd_fd);
   21.30 -        privcmd_fd = -1;
   21.31 -    }
   21.32 -    return 0;
   21.33 -}
   21.34 -
   21.35 -
   21.36 -#define CONSOLE_RING_CLEAR	1
   21.37 -
   21.38 -int xi_readconsolering(char *str, unsigned int max_chars, int clear)
   21.39 -{
   21.40 -    int ret;
   21.41 -    dom0_op_t op;
   21.42 -
   21.43 -    op.cmd = DOM0_READCONSOLE;
   21.44 -    op.u.readconsole.str = (unsigned long)str;
   21.45 -    op.u.readconsole.count = max_chars;
   21.46 -    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
   21.47 -
   21.48 -    if ( (ret = do_dom0_op(&op)) > 0 )
   21.49 -        str[ret] = '\0';
   21.50 -
   21.51 -    return ret;
   21.52 -}    
   21.53 -
    22.1 --- a/tools/libxi/libxi_private.c	Wed Nov 19 17:22:42 2003 +0000
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,34 +0,0 @@
    22.4 -/******************************************************************************
    22.5 - * libxi_private.c
    22.6 - * 
    22.7 - * Helper functions for the rest of the library.
    22.8 - */
    22.9 -
   22.10 -#include "libxi_private.h"
   22.11 -
   22.12 -static int devmem_fd = -1;
   22.13 -
   22.14 -int init_pfn_mapper(void)
   22.15 -{
   22.16 -    if ( (devmem_fd == -1) &&
   22.17 -         ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) )
   22.18 -    {
   22.19 -        devmem_fd = -1;
   22.20 -        return -1;
   22.21 -    }
   22.22 -    return 0;
   22.23 -}
   22.24 -
   22.25 -void *map_pfn(unsigned long pfn)
   22.26 -{
   22.27 -    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   22.28 -                       MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT);
   22.29 -    if ( vaddr == MAP_FAILED )
   22.30 -        return NULL;
   22.31 -    return vaddr;
   22.32 -}
   22.33 -
   22.34 -void unmap_pfn(void *vaddr)
   22.35 -{
   22.36 -    (void)munmap(vaddr, PAGE_SIZE);
   22.37 -}
    23.1 --- a/tools/libxi/libxi_private.h	Wed Nov 19 17:22:42 2003 +0000
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,155 +0,0 @@
    23.4 -
    23.5 -#ifndef __LIBXI_PRIVATE_H__
    23.6 -#define __LIBXI_PRIVATE_H__
    23.7 -
    23.8 -typedef unsigned char      u8;
    23.9 -typedef unsigned short     u16;
   23.10 -typedef unsigned long      u32;
   23.11 -typedef unsigned long long u64;
   23.12 -typedef signed char        s8;
   23.13 -typedef signed short       s16;
   23.14 -typedef signed long        s32;
   23.15 -typedef signed long long   s64;
   23.16 -
   23.17 -#include <unistd.h>
   23.18 -#include <stdio.h>
   23.19 -#include <errno.h>
   23.20 -#include <fcntl.h>
   23.21 -#include <sys/mman.h>
   23.22 -#include <sys/types.h>
   23.23 -#include <sys/stat.h>
   23.24 -#include <stdlib.h>
   23.25 -#include <sys/ioctl.h>
   23.26 -#include <errno.h>
   23.27 -#include <string.h>
   23.28 -
   23.29 -#include "xi.h"
   23.30 -
   23.31 -#include <asm-xeno/proc_cmd.h>
   23.32 -#include <hypervisor-ifs/hypervisor-if.h>
   23.33 -#include <hypervisor-ifs/dom0_ops.h>
   23.34 -#include <hypervisor-ifs/vbd.h>
   23.35 -
   23.36 -#define _PAGE_PRESENT   0x001
   23.37 -#define _PAGE_RW        0x002
   23.38 -#define _PAGE_USER      0x004
   23.39 -#define _PAGE_PWT       0x008
   23.40 -#define _PAGE_PCD       0x010
   23.41 -#define _PAGE_ACCESSED  0x020
   23.42 -#define _PAGE_DIRTY     0x040
   23.43 -#define _PAGE_PAT       0x080
   23.44 -#define _PAGE_PSE       0x080
   23.45 -#define _PAGE_GLOBAL    0x100
   23.46 -
   23.47 -
   23.48 -#define L1_PAGETABLE_SHIFT       12
   23.49 -#define L2_PAGETABLE_SHIFT       22
   23.50 - 
   23.51 -#define ENTRIES_PER_L1_PAGETABLE 1024
   23.52 -#define ENTRIES_PER_L2_PAGETABLE 1024
   23.53 - 
   23.54 -#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
   23.55 -#define PAGE_SIZE               (1UL << PAGE_SHIFT)
   23.56 -#define PAGE_MASK               (~(PAGE_SIZE-1))
   23.57 -
   23.58 -typedef struct { unsigned long l1_lo; } l1_pgentry_t;
   23.59 -typedef struct { unsigned long l2_lo; } l2_pgentry_t;
   23.60 -
   23.61 -#define l1_table_offset(_a) \
   23.62 -          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
   23.63 -#define l2_table_offset(_a) \
   23.64 -          ((_a) >> L2_PAGETABLE_SHIFT)
   23.65 -
   23.66 -#define ERROR(_m)  \
   23.67 -    fprintf(stderr, "ERROR: %s\n", (_m))
   23.68 -
   23.69 -#define PERROR(_m) \
   23.70 -    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
   23.71 -
   23.72 -extern int privcmd_fd;
   23.73 -static inline int do_privcmd(unsigned int cmd, unsigned long data)
   23.74 -{
   23.75 -    return ioctl(privcmd_fd, cmd, data);
   23.76 -}
   23.77 -
   23.78 -static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
   23.79 -{
   23.80 -    return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
   23.81 -}
   23.82 -
   23.83 -static inline int do_dom0_op(dom0_op_t *op)
   23.84 -{
   23.85 -    int ret = -1;
   23.86 -    privcmd_hypercall_t hypercall;
   23.87 -
   23.88 -    op->interface_version = DOM0_INTERFACE_VERSION;
   23.89 -
   23.90 -    hypercall.op     = __HYPERVISOR_dom0_op;
   23.91 -    hypercall.arg[0] = (unsigned long)op;
   23.92 -
   23.93 -    if ( mlock(op, sizeof(*op)) != 0 )
   23.94 -        goto out1;
   23.95 -
   23.96 -    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
   23.97 -    {
   23.98 -        if ( errno == EACCES )
   23.99 -            fprintf(stderr, "Dom0 operation failed -- need to"
  23.100 -                    " rebuild the user-space tool set?\n");
  23.101 -        goto out2;
  23.102 -    }
  23.103 -
  23.104 -    ret = 0;
  23.105 -
  23.106 - out2: (void)munlock(op, sizeof(*op));
  23.107 - out1: return ret;
  23.108 -}
  23.109 -
  23.110 -static inline int do_network_op(network_op_t *op)
  23.111 -{
  23.112 -    int ret = -1;
  23.113 -    privcmd_hypercall_t hypercall;
  23.114 -
  23.115 -    hypercall.op     = __HYPERVISOR_network_op;
  23.116 -    hypercall.arg[0] = (unsigned long)op;
  23.117 -
  23.118 -    if ( mlock(op, sizeof(*op)) != 0 )
  23.119 -        goto out1;
  23.120 -
  23.121 -    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
  23.122 -        goto out2;
  23.123 -
  23.124 -    ret = 0;
  23.125 -
  23.126 - out2: (void)munlock(op, sizeof(*op));
  23.127 - out1: return ret;
  23.128 -}
  23.129 -
  23.130 -
  23.131 -static inline int do_block_io_op(block_io_op_t *op)
  23.132 -{
  23.133 -    int ret = -1;
  23.134 -    privcmd_hypercall_t hypercall;
  23.135 -
  23.136 -    hypercall.op     = __HYPERVISOR_block_io_op;
  23.137 -    hypercall.arg[0] = (unsigned long)op;
  23.138 -
  23.139 -    if ( mlock(op, sizeof(*op)) != 0 )
  23.140 -        goto out1;
  23.141 -
  23.142 -    if ( do_xen_hypercall(&hypercall) < 0 )
  23.143 -        goto out2;
  23.144 -
  23.145 -    ret = 0;
  23.146 -
  23.147 - out2: (void)munlock(op, sizeof(*op));
  23.148 - out1: return ret;
  23.149 -}
  23.150 -
  23.151 -/*
  23.152 - * PFN mapping.
  23.153 - */
  23.154 -int init_pfn_mapper(void);
  23.155 -void *map_pfn(unsigned long pfn);
  23.156 -void unmap_pfn(void *vaddr);
  23.157 -
  23.158 -#endif /* __LIBXI_PRIVATE_H__ */
    24.1 --- a/tools/libxi/libxi_vbd.c	Wed Nov 19 17:22:42 2003 +0000
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,116 +0,0 @@
    24.4 -/******************************************************************************
    24.5 - * libxi_vbd.c
    24.6 - * 
    24.7 - * API for manipulating and accessing per-domain virtual block devices.
    24.8 - * 
    24.9 - * Copyright (c) 2003, K A Fraser.
   24.10 - */
   24.11 -
   24.12 -#define _GNU_SOURCE
   24.13 -#include "libxi_private.h"
   24.14 -
   24.15 -int xi_vbd_create(unsigned int domid, unsigned short vbdid, int writeable)
   24.16 -{
   24.17 -    block_io_op_t op; 
   24.18 -    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
   24.19 -    op.u.create_params.domain  = domid;
   24.20 -    op.u.create_params.vdevice = vbdid;
   24.21 -    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
   24.22 -    return do_block_io_op(&op);
   24.23 -}
   24.24 -
   24.25 -
   24.26 -int xi_vbd_destroy(unsigned int domid, unsigned short vbdid)
   24.27 -{
   24.28 -    block_io_op_t op; 
   24.29 -    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
   24.30 -    op.u.delete_params.domain  = domid;
   24.31 -    op.u.delete_params.vdevice = vbdid;
   24.32 -    return do_block_io_op(&op);
   24.33 -}
   24.34 -
   24.35 -
   24.36 -int xi_vbd_add_extent(unsigned int domid, 
   24.37 -                      unsigned short vbdid,
   24.38 -                      unsigned short real_device,
   24.39 -                      unsigned long start_sector,
   24.40 -                      unsigned long nr_sectors)
   24.41 -{
   24.42 -    block_io_op_t op; 
   24.43 -    op.cmd = BLOCK_IO_OP_VBD_ADD; 
   24.44 -    op.u.add_params.domain  = domid; 
   24.45 -    op.u.add_params.vdevice = vbdid;
   24.46 -    op.u.add_params.extent.device       = real_device; 
   24.47 -    op.u.add_params.extent.start_sector = start_sector;
   24.48 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   24.49 -    return do_block_io_op(&op);
   24.50 -}
   24.51 -
   24.52 -
   24.53 -int xi_vbd_delete_extent(unsigned int domid, 
   24.54 -                         unsigned short vbdid,
   24.55 -                         unsigned short real_device,
   24.56 -                         unsigned long start_sector,
   24.57 -                         unsigned long nr_sectors)
   24.58 -{
   24.59 -    block_io_op_t op; 
   24.60 -    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
   24.61 -    op.u.add_params.domain  = domid; 
   24.62 -    op.u.add_params.vdevice = vbdid;
   24.63 -    op.u.add_params.extent.device       = real_device; 
   24.64 -    op.u.add_params.extent.start_sector = start_sector;
   24.65 -    op.u.add_params.extent.nr_sectors   = nr_sectors;
   24.66 -    return do_block_io_op(&op);
   24.67 -}
   24.68 -
   24.69 -
   24.70 -int xi_vbd_probe(unsigned int domid,
   24.71 -                 unsigned short vbdid,
   24.72 -                 unsigned int max_vbds,
   24.73 -                 xi_vbd_t *vbds)
   24.74 -{
   24.75 -    block_io_op_t op; 
   24.76 -    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
   24.77 -    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
   24.78 -
   24.79 -    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
   24.80 -    op.u.probe_params.domain    = domid; 
   24.81 -    
   24.82 -    xdi->max   = max_vbds;
   24.83 -    xdi->disks = malloc(allocsz);
   24.84 -    xdi->count = 0;
   24.85 -
   24.86 -    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
   24.87 -    {
   24.88 -        if ( xdi->disks != NULL )
   24.89 -            free(xdi->disks);
   24.90 -        return -ENOMEM;
   24.91 -    }
   24.92 -
   24.93 -    ret = do_block_io_op(&op);
   24.94 -
   24.95 -    (void)munlock(xdi->disks, allocsz);
   24.96 -
   24.97 -    if ( ret >= 0 )
   24.98 -    {
   24.99 -	for ( i = 0, j = 0; i < xdi->count; i++ )
  24.100 -        {
  24.101 -            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
  24.102 -                continue;
  24.103 -            
  24.104 -            vbds[j].domid = xdi->disks[i].domain;
  24.105 -            vbds[j].vbdid = xdi->disks[i].device;
  24.106 -            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
  24.107 -                0 : XI_VBDF_WRITEABLE;
  24.108 -            vbds[j].nr_sectors = xdi->disks[i].capacity;
  24.109 -            
  24.110 -            j++;
  24.111 -        }
  24.112 -
  24.113 -        ret = j;
  24.114 -    }
  24.115 -    
  24.116 -    free(xdi->disks);
  24.117 -
  24.118 -    return ret;
  24.119 -}
    25.1 --- a/tools/libxi/libxi_vif.c	Wed Nov 19 17:22:42 2003 +0000
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,66 +0,0 @@
    25.4 -/******************************************************************************
    25.5 - * libxi_vif.c
    25.6 - * 
    25.7 - * API for manipulating and accessing per-network-interface parameters.
    25.8 - * 
    25.9 - * Copyright (c) 2003, K A Fraser.
   25.10 - */
   25.11 -
   25.12 -#include "libxi_private.h"
   25.13 -
   25.14 -int xi_vif_scheduler_set(unsigned int domid, 
   25.15 -                         unsigned int vifid, 
   25.16 -                         xi_vif_sched_params_t *params)
   25.17 -{
   25.18 -    network_op_t  netop;
   25.19 -    netop.cmd = NETWORK_OP_VIFSETPARAMS;
   25.20 -    netop.u.vif_setparams.domain       = domid;
   25.21 -    netop.u.vif_setparams.vif          = vifid;
   25.22 -    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
   25.23 -    netop.u.vif_setparams.credit_usec  = params->credit_usec;
   25.24 -    return do_network_op(&netop);
   25.25 -}
   25.26 -
   25.27 -
   25.28 -int xi_vif_scheduler_get(unsigned int domid, 
   25.29 -                         unsigned int vifid, 
   25.30 -                         xi_vif_sched_params_t *params)
   25.31 -{
   25.32 -    network_op_t  netop;
   25.33 -    int rc;
   25.34 -
   25.35 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   25.36 -    netop.u.vif_getinfo.domain = domid;
   25.37 -    netop.u.vif_getinfo.vif    = vifid;
   25.38 -
   25.39 -    if ( (rc = do_network_op(&netop)) >= 0 )
   25.40 -    {
   25.41 -        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
   25.42 -        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
   25.43 -    }
   25.44 -
   25.45 -    return rc;
   25.46 -}
   25.47 -
   25.48 -
   25.49 -int xi_vif_stats_get(unsigned int domid, 
   25.50 -                     unsigned int vifid, 
   25.51 -                     xi_vif_stats_t *stats)
   25.52 -{
   25.53 -    network_op_t  netop;
   25.54 -    int rc;
   25.55 -
   25.56 -    netop.cmd = NETWORK_OP_VIFGETINFO;
   25.57 -    netop.u.vif_getinfo.domain = domid;
   25.58 -    netop.u.vif_getinfo.vif    = vifid;
   25.59 -
   25.60 -    if ( (rc = do_network_op(&netop)) >= 0 )
   25.61 -    {
   25.62 -        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
   25.63 -        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
   25.64 -        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
   25.65 -        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
   25.66 -    }
   25.67 -
   25.68 -    return rc;
   25.69 -}
    26.1 --- a/tools/libxi/rpm.spec	Wed Nov 19 17:22:42 2003 +0000
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,28 +0,0 @@
    26.4 -Summary: Xen control interface library
    26.5 -Name: xen-internal-library
    26.6 -Version: 1.2
    26.7 -Release: 1
    26.8 -License: Xen
    26.9 -Group: Xen
   26.10 -BuildRoot: %{staging}
   26.11 -%description
   26.12 -Library to make it easier to access the Xen control interfaces.
   26.13 -
   26.14 -%pre
   26.15 -%preun
   26.16 -%install
   26.17 -install -m 0755 -d $RPM_BUILD_ROOT/lib
   26.18 -install -m 0755 libxi.a $RPM_BUILD_ROOT/lib/libxi.a
   26.19 -install -m 0755 libxi.so $RPM_BUILD_ROOT/lib/libxi.so
   26.20 -install -m 0755 -d $RPM_BUILD_ROOT/include
   26.21 -install -m 0644 xi.h $RPM_BUILD_ROOT/include/xi.h
   26.22 -%clean
   26.23 -%post
   26.24 -%postun
   26.25 -%files
   26.26 -%defattr(-,root,root)
   26.27 -%dir /lib
   26.28 -/lib/libxi.a
   26.29 -/lib/libxi.so
   26.30 -%dir /include
   26.31 -/include/xi.h
    27.1 --- a/tools/libxi/xi.h	Wed Nov 19 17:22:42 2003 +0000
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,99 +0,0 @@
    27.4 -/******************************************************************************
    27.5 - * xi.h
    27.6 - * 
    27.7 - * A library for low-level access to the Xen control interfaces.
    27.8 - * 
    27.9 - * Copyright (c) 2003, K A Fraser.
   27.10 - */
   27.11 -
   27.12 -#ifndef __XI_H__
   27.13 -#define __XI_H__
   27.14 -
   27.15 -int xi_interface_open(void);
   27.16 -int xi_interface_close(void);
   27.17 -
   27.18 -typedef struct {
   27.19 -    unsigned int  domid;
   27.20 -    unsigned int  cpu;
   27.21 -    int           has_cpu;
   27.22 -    int           stopped;
   27.23 -    unsigned long nr_pages;
   27.24 -    unsigned long long cpu_time;
   27.25 -#define XI_DOMINFO_MAXNAME 16
   27.26 -    char          name[XI_DOMINFO_MAXNAME];
   27.27 -} xi_dominfo_t;
   27.28 -
   27.29 -int xi_domain_create(unsigned int mem_kb, const char *name);
   27.30 -int xi_domain_start(unsigned int domid);
   27.31 -int xi_domain_stop(unsigned int domid);
   27.32 -int xi_domain_destroy(unsigned int domid, int force);
   27.33 -int xi_domain_getinfo(unsigned int first_domid, 
   27.34 -                      unsigned int max_doms,
   27.35 -                      xi_dominfo_t *info);
   27.36 -
   27.37 -int xi_linux_save(unsigned int domid, const char *state_file, int verbose);
   27.38 -int xi_linux_restore(const char *state_file, int verbose);
   27.39 -int xi_linux_build(unsigned int domid,
   27.40 -                   const char *image_name,
   27.41 -                   const char *ramdisk_name,
   27.42 -                   const char *cmdline,
   27.43 -                   int verbose);
   27.44 -
   27.45 -int xi_bvtsched_global_set(unsigned long ctx_allow);
   27.46 -int xi_bvtsched_domain_set(unsigned int domid,
   27.47 -                           unsigned long mcuadv,
   27.48 -                           unsigned long warp,
   27.49 -                           unsigned long warpl,
   27.50 -                           unsigned long warpu);
   27.51 -
   27.52 -typedef struct {
   27.53 -    unsigned long credit_bytes;
   27.54 -    unsigned long credit_usec;
   27.55 -} xi_vif_sched_params_t;
   27.56 -
   27.57 -typedef struct {
   27.58 -    unsigned long long tx_bytes, tx_pkts;
   27.59 -    unsigned long long rx_bytes, rx_pkts;
   27.60 -} xi_vif_stats_t;
   27.61 -
   27.62 -int xi_vif_scheduler_set(unsigned int domid, 
   27.63 -                         unsigned int vifid,
   27.64 -                         xi_vif_sched_params_t *params);
   27.65 -int xi_vif_scheduler_get(unsigned int domid, 
   27.66 -                         unsigned int vifid,
   27.67 -                         xi_vif_sched_params_t *params);
   27.68 -int xi_vif_stats_get(unsigned int domid, 
   27.69 -                         unsigned int vifid,
   27.70 -                         xi_vif_stats_t *stats);
   27.71 -
   27.72 -typedef struct {
   27.73 -#define XI_VBDDOM_PROBE_ALL (~0U)
   27.74 -    unsigned int   domid;
   27.75 -    unsigned short vbdid;
   27.76 -#define XI_VBDF_WRITEABLE (1<<0)
   27.77 -    unsigned long  flags;
   27.78 -    unsigned long  nr_sectors;
   27.79 -} xi_vbd_t;
   27.80 -
   27.81 -
   27.82 -int xi_vbd_create(unsigned int domid, unsigned short vbdid, int writeable);
   27.83 -int xi_vbd_destroy(unsigned int domid, unsigned short vbdid);
   27.84 -int xi_vbd_add_extent(unsigned int domid, 
   27.85 -                      unsigned short vbdid,
   27.86 -                      unsigned short real_device,
   27.87 -                      unsigned long start_sector,
   27.88 -                      unsigned long nr_sectors);
   27.89 -int xi_vbd_delete_extent(unsigned int domid, 
   27.90 -                         unsigned short vbdid,
   27.91 -                         unsigned short real_device,
   27.92 -                         unsigned long start_sector,
   27.93 -                         unsigned long nr_sectors);
   27.94 -int xi_vbd_probe(unsigned int domid,
   27.95 -                 unsigned short vbdid,
   27.96 -                 unsigned int max_vbds,
   27.97 -                 xi_vbd_t *vbds);
   27.98 -
   27.99 -int xi_readconsolering(char *str, unsigned int max_chars, int clear);
  27.100 -
  27.101 -
  27.102 -#endif /* __XI_H__ */